Каждый разработчик рано или поздно сталкивается с необходимостью выполнять какие-то действия по расписанию: рассылки, очистка кэша, синхронизация данных. В Yii2 для этого есть удобные инструменты. Сегодня разберём, как подружить cron с Yii2 и написать свой планировщик задач.

Digital-студия WNDER

Что такое cron и зачем он нужен в Yii2

Cron — это системный планировщик в Unix-подобных системах. Он запускает команды по расписанию. В Yii2 мы можем создавать консольные команды, которые cron будет вызывать. Это идеально для фоновых задач: отправка email, обновление статистики, резервное копирование.

Представьте, что вы хотите каждый день в 3 часа ночи чистить логи. Вместо того чтобы просыпаться и делать это вручную, вы пишете команду и говорите cron'у: «Запускай её каждую ночь». Yii2 даёт удобный интерфейс для таких команд.

Создаём консольную команду в Yii2

Для начала убедимся, что у нас есть консольное приложение. В стандартном шаблоне Yii2 advanced есть папка console. Если вы используете basic, создайте её. Внутри будет файл controllers для команд.

Создадим команду для очистки кэша. Например, CacheController с действием actionClear.

cache->flush()) {
            echo "Кэш очищен!\n";
            return 0;
        }
        echo "Не удалось очистить кэш.\n";
        return 1;
    }
}

Теперь эту команду можно запустить вручную: php yii cache/clear. Убедитесь, что путь к yii правильный — обычно он в корне проекта.

Правило: Всегда возвращайте код выхода из консольной команды (0 — успех, 1 — ошибка). Это поможет cron'у и мониторингу понять, всё ли прошло гладко.

Настраиваем cron для запуска команды

Откройте crontab на сервере командой crontab -e. Добавьте строку, которая будет запускать нашу команду каждый день в 3:00.

0 3 * * * /usr/bin/php /path/to/project/yii cache/clear >> /var/log/yii-cache.log 2>&1

Здесь 0 3 * * * означает «в 3:00 каждый день». /usr/bin/php — путь к PHP (уточните через which php). /path/to/project/yii — путь к вашему Yii-скрипту. Логи перенаправляем в файл, чтобы потом можно было посмотреть, что происходило.

Чтобы проверить, что cron работает, можно временно поставить запуск каждую минуту: * * * * * и посмотреть логи.

Планировщик задач внутри Yii2

Иногда cron'а недостаточно: нужно гибко управлять расписанием из админки, без правки crontab. Тогда на помощь приходит планировщик задач. В Yii2 нет встроенного, но можно использовать расширения, например yii2-scheduler, или написать свой.

Рассмотрим простой вариант: таблица в БД с задачами и cron, который раз в минуту проверяет, что нужно выполнить.

Создадим миграцию для таблицы scheduler_task:

createTable('scheduler_task', [
            'id' => $this->primaryKey(),
            'command' => $this->string()->notNull(),
            'cron_expression' => $this->string()->notNull(),
            'last_run' => $this->integer(),
            'next_run' => $this->integer(),
            'status' => $this->smallInteger()->defaultValue(1),
        ]);
    }

    public function safeDown()
    {
        $this->dropTable('scheduler_task');
    }
}

Теперь команда, которая будет запускаться каждую минуту и проверять задачи:

where(['<=', 'next_run', $now])
            ->andWhere(['status' => 1])
            ->all();

        foreach ($tasks as $task) {
            // Выполняем команду
            $output = [];
            $returnVar = 0;
            exec(Yii::getAlias('@app/yii') . ' ' . $task->command, $output, $returnVar);

            // Обновляем время следующего запуска
            $task->last_run = $now;
            $task->next_run = $this->calculateNextRun($task->cron_expression, $now);
            $task->save();
        }
    }

    private function calculateNextRun($cronExpression, $currentTime)
    {
        // Здесь можно использовать библиотеку для парсинга cron-выражений
        // Например, dragonmantank/cron-expression
        // Для простоты примера просто добавим 1 час
        return $currentTime + 3600;
    }
}

В crontab добавляем запуск каждую минуту:

* * * * * /usr/bin/php /path/to/project/yii scheduler/run

Теперь задачи можно добавлять через админку, и они будут выполняться по расписанию. Для парсинга cron-выражений советую подключить библиотеку dragonmantank/cron-expression.

Лайфхак: Чтобы избежать параллельного запуска одной и той же задачи, используйте блокировки. Например, файловые локи или блокировку в Redis. Иначе при долгой задаче cron может запустить её снова.

Сравнение подходов: чистый cron vs планировщик в Yii2

Что выбрать? Зависит от задачи. Вот таблица для сравнения.

Критерий Чистый cron Планировщик в Yii2
Гибкость расписания Меняется только в crontab Можно менять из админки
Логирование Только через перенаправление вывода Можно писать в БД, файлы, отправлять уведомления
Сложность настройки Низкая Средняя (нужно писать код)
Зависимость от сервера Высокая (нужен доступ к crontab) Низкая (достаточно одного cron на запуск проверки)

Если у вас простые задачи и нет необходимости менять расписание часто — чистый cron проще. Если же требуется управление из веб-интерфейса, логирование и гибкость — планировщик в Yii2 оправдан.

Полезные советы и подводные камни

  • Пути к PHP и Yii: В crontab всегда указывайте полные пути. Переменные окружения могут отличаться от тех, что в терминале.
  • Права на файлы: Убедитесь, что пользователь, от которого работает cron, имеет права на запись в логи и кэш.
  • Обработка ошибок: В консольных командах используйте try-catch, чтобы неожиданное исключение не ломало весь процесс.
  • Тестирование: Запускайте команды вручную перед добавлением в cron. Убедитесь, что они работают.
  • Мониторинг: Настройте уведомления об ошибках. Например, отправляйте email при ненулевом коде возврата.
Совет: Для сложных расписаний (например, «каждый второй вторник месяца») используйте библиотеку dragonmantank/cron-expression. Она умеет вычислять следующую дату запуска по cron-выражению.

Заключение

Мы разобрали, как работать с cron и планировщиком задач в Yii2. Начали с простых консольных команд, научились запускать их через cron, а затем создали гибкий планировщик с хранением задач в БД. Теперь вы можете автоматизировать рутину и спать спокойно.

Помните: автоматизация — это не роскошь, а необходимость для любого серьёзного проекта. Используйте cron и планировщики, чтобы сосредоточиться на более важных задачах.

Студия WNDER