Рано или поздно любой веб-проект обрастает задачами, которые нужно выполнять регулярно: рассылки, очистка кэша, синхронизация данных. И тут на сцену выходит cron. В Yii есть удобные инструменты, чтобы не превратить это в хаос. Давай разберёмся, как настроить планировщик и не сойти с ума.
Почему cron — это не страшно, а удобно
Cron — это демон в Unix-подобных системах, который запускает команды по расписанию. В Yii есть консольные команды, которые идеально подходят для таких задач. Вместо того чтобы писать костыли на PHP, ты просто создаёшь контроллер для консоли и указываешь его в crontab.
Представь: каждый день в 3 часа ночи нужно чистить логи. Ты можешь, конечно, делать это вручную, но лучше поручить крону. Yii предоставляет удобный интерфейс для консольных команд — yii\console\Controller.
Вот пример простой команды, которая удаляет старые логи:
<?php
namespace app\commands;
use yii\console\Controller;
use Yii;
use yii\helpers\FileHelper;
class LogController extends Controller
{
public function actionClean()
{
$logPath = Yii::getAlias('@runtime/logs');
$files = FileHelper::findFiles($logPath, ['only' => ['*.log']]);
foreach ($files as $file) {
if (filemtime($file) < time() - 7 * 24 * 3600) {
unlink($file);
}
}
echo "Старые логи удалены.\n";
}
}
Теперь достаточно добавить в crontab строку:
0 3 * * * /usr/bin/php /path/to/yii log/clean
И всё, задача работает без твоего участия.
Планировщик задач в Yii: зачем он нужен, если есть cron
Cron — штука мощная, но не всегда удобная. Например, если нужно запускать задачу каждые 5 минут, а сервер перегружен, или если ты хочешь управлять расписанием из админки. Тут на помощь приходит планировщик задач — компонент, который сам решает, когда что запускать.
В Yii нет встроенного планировщика, но его легко сделать самому. Идея проста: создаём команду, которая запускается каждую минуту через cron, а внутри проверяет, какие задачи пора выполнить. Для этого можно использовать таблицу в базе данных с расписанием.
Пример миграции для таблицы задач:
<?php
use yii\db\Migration;
class m250101_000000_create_scheduler_table extends Migration
{
public function up()
{
$this->createTable('{{%scheduler_task}}', [
'id' => $this->primaryKey(),
'name' => $this->string()->notNull(),
'command' => $this->string()->notNull(),
'interval' => $this->integer()->notNull(), // в секундах
'last_run' => $this->integer()->null(),
'is_active' => $this->boolean()->defaultValue(true),
]);
}
public function down()
{
$this->dropTable('{{%scheduler_task}}');
}
}
Теперь создадим консольную команду, которая будет проверять задачи и запускать те, чьё время пришло:
<?php
namespace app\commands;
use yii\console\Controller;
use app\models\SchedulerTask;
use Yii;
class SchedulerController extends Controller
{
public function actionRun()
{
$tasks = SchedulerTask::find()->where(['is_active' => true])->all();
foreach ($tasks as $task) {
if ($task->last_run === null || (time() - $task->last_run) >= $task->interval) {
$command = $task->command;
Yii::$app->run($command);
$task->last_run = time();
$task->save(false);
}
}
}
}
И добавляем в crontab запуск каждую минуту:
* * * * * /usr/bin/php /path/to/yii scheduler/run
Теперь ты можешь управлять расписанием через базу данных или админку.
Как избежать типичных грабель
Работа с кроном и планировщиком полна подводных камней. Вот несколько советов, которые сэкономят тебе нервы.
- Не запускайте тяжёлые задачи каждую минуту. Если задача выполняется дольше минуты, cron может запустить её повторно, пока предыдущая ещё не завершилась. Используйте блокировки (например, через файл или мьютекс).
- Указывайте полные пути. В crontab окружение может отличаться от твоего терминала, поэтому используйте абсолютные пути к PHP и к файлу yii.
- Проверяйте права. Убедитесь, что пользователь, от имени которого работает cron, имеет доступ к файлам и базе данных.
- Используйте try-catch. Ошибка в одной задаче не должна ронять весь планировщик.
Вот пример блокировки через файл:
public function actionRun()
{
$lockFile = Yii::getAlias('@runtime/scheduler.lock');
if (file_exists($lockFile)) {
echo "Планировщик уже запущен.\n";
return;
}
file_put_contents($lockFile, getmypid());
try {
// ... логика
} finally {
unlink($lockFile);
}
}
Сравнение подходов: cron vs планировщик
Что выбрать? Зависит от задачи. Вот таблица, которая поможет определиться.
| Критерий | Cron | Планировщик в Yii |
|---|---|---|
| Простота настройки | Высокая | Средняя |
| Гибкость расписания | Ограничена | Высокая |
| Управление из админки | Нет | Да |
| Зависимость от ОС | Unix-подобные | Любая |
Если у тебя простые задачи и ты не хочешь городить огород — cron. Если нужен контроль и гибкость — планировщик.
Практический пример: рассылка писем
Допустим, у нас есть задача — каждую ночь отправлять письма пользователям. Создадим команду, которая выбирает пользователей и ставит письма в очередь.
<?php
namespace app\commands;
use yii\console\Controller;
use app\models\User;
use Yii;
class NewsletterController extends Controller
{
public function actionSend()
{
$users = User::find()->where(['is_subscribed' => true])->all();
foreach ($users as $user) {
Yii::$app->mailer->compose()
->setTo($user->email)
->setSubject('Новости')
->setTextBody('Привет!')
->send();
}
echo "Рассылка завершена.\n";
}
}
Добавляем в crontab:
0 2 * * * /usr/bin/php /path/to/yii newsletter/send
Всё, письма уходят каждую ночь.
Что в итоге
Cron и планировщик в Yii — это мощные инструменты для автоматизации. Главное — не бояться экспериментировать и всегда помнить о безопасности и логировании. Начни с простых задач, а потом усложняй. И не забудь про блокировки, чтобы избежать наложения задач.
Если хочешь, чтобы всё работало как часы, следуй правилам: используй консольные команды, проверяй расписание, логируй и тестируй. Тогда фоновые задачи станут твоими незаметными помощниками.
Студия WNDER



