Показаны сообщения с ярлыком yii2. Показать все сообщения
Показаны сообщения с ярлыком yii2. Показать все сообщения

пятница, 25 апреля 2025 г.

Экспорт из PHP в CSV большого кол-во данных

В PHP существует удобный инструмент php://output, который, подобно конструкциям print и echo, позволяет выводить данные в выходной буфер, не загружая память сервера. Как его использовать? Прежде чем привести пример, отмечу, что в ООП экспорт данных (например, сохранение) должен выполняться в контроллере, а бизнес-логика (выборка, агрегация и т.д.) — в модели. Ниже представлен простой пример без использования ООП:

// Отключаем кэширование
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Expires: 0');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');

// Устанавливаем заголовки для CSV
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="export.csv"');
header('Content-Transfer-Encoding: binary');

// Пример получения данных (заменить на реальную выборку из БД)
$list = [
    ['_id' => 1, 'date' => time(), 'user' => 'John'],
    ['_id' => 2, 'date' => time(), 'user' => 'Jane'],
    // ... другие данные
];

// Заголовки для CSV
$titles = ['ID', 'Date', 'User'];

// Открываем поток php://output
$df = fopen('php://output', 'w');
if ($df === false) {
    die('Ошибка открытия потока php://output');
}

// Записываем заголовки
fputcsv($df, $titles);

// Записываем данные
foreach ($list as $row) {
    // Проверяем, не прервано ли соединение
    if (connection_aborted()) {
        fclose($df);
        die('Соединение с клиентом прервано');
    }

    fputcsv($df, [
        $row['_id'],
        date('Y-m-d H:i:s', $row['date']),
        $row['user'],
        // Добавить другие поля, если нужно
    ]);

    // Очищаем буфер для экономии памяти
    flush();
}

// Закрываем поток
fclose($df);

При выполнении такого кода в браузере файл export.csv автоматически сохранится на вашем компьютере с указанным содержимым. При этом, независимо от количества строк, память будет использоваться только для текущей итерации цикла foreach.

Хотя этот подход позволяет обрабатывать сотни тысяч строк без перегрузки сервера, существует риск прерывания соединения между клиентом и сервером, что может привести к потере части данных.

В чем еще проблема? Несмотря на экономию серверной памяти, у метода есть недостаток: во время потоковой передачи данных в файл скрипт продолжает выполняться. Однако время выполнения скрипта ограничено (обычно около 15 секунд, если не изменять настройки). Если сохранение, например, 50 тысяч записей занимает больше 15 секунд, возникнет ошибка fatal error из-за превышения времени выполнения.

Источник

четверг, 16 мая 2019 г.

Подключение javascript в yii2

Inline js

Во view можно подключить произвольный javascript код:

$var = 123;
//начало многосточной строки, можно использовать любые кавычки
$script = <<< JS
    function foo() {
        return $var; //можно использовать переменные
    }
JS; //маркер конца строки, обязательно сразу, без пробелов и табуляции

$this->registerJs($script, yii\web\View::POS_READY);

получим сразу перед закрытием body:


<script type="text/javascript">
jQuery(document).ready(function () {
    function foo() {
        return 123;
    }
});</script>

другие варианты места подключения скрипта: (документация)
  • POS_HEAD: перед тегом </head>
  • POS_BEGIN: после тэга <body>
  • POS_END: перед тэгом </body>
  • POS_LOAD: оборачивается в jQuery(window).load(). Note that by using this position, the method will automatically register the jQuery js file.
  • POS_READY: оборачивается вjQuery(document).ready(). This is the default value. Note that by using this position, the method will automatically register the jQuery js file.

js-файл

$this->registerJsFile('url/to/file.js',  ['position' => yii\web\View::POS_END]);
источник  

вторник, 30 мая 2017 г.

yii2 полезные мелочи

Как в yii2 проверить isNewRecord в afterSave()

Теперь алгоритм проверки после сохранения такой:
app\models\Model
public function afterSave($insert, $changedAttributes)
    {
        if ($insert) {
                // Да это новая запись (insert)
        } else {
                // Нет, старая (update)
        }
        parent::afterSave($insert, $changedAttributes);
}

 

Не находит action из контроллера Not Found (#404)

В yii2 есть особенность с именование action в отличие от yii1:
в контроллере создаем action
public function actionLastNews()
{
////
}
при стандартных rules этот экшн будет доступен по адресу: /last-news
Эта мелочь может попортить немало нервов.

Подключение javascript в yii2

Inline js

Во view можно подключить произвольный javascript код:
$var = 123;
//начало многосточной строки, можно использовать любые кавычки
$script = <<< JS
    function foo() {
        return $var; //можно использовать переменные
    }
JS;
//маркер конца строки, обязательно сразу, без пробелов и табуляции
$this->registerJs($script, yii\web\View::POS_READY);
получим сразу перед закрытием body:
<script type="text/javascript">
jQuery(document).ready(function () {
    function foo() {
        return 123;
    }
});</script>
</body>
другие варианты места подключения скрипта: (документация)
  • POS_HEAD
  • POS_BEGIN: после тэга
  • POS_END: перед тэгом
  • POS_LOAD: оборачивается в jQuery(window).load(). Note that by using this position, the method will automatically register the jQuery js file.
  • POS_READY: оборачивается вjQuery(document).ready(). This is the default value. Note that by using this position, the method will automatically register the jQuery js file.
  • js-файл

    $this->registerJsFile('url/to/file.js',  ['position' => yii\web\View::POS_END]);
     
    Скопировано отсюда