Задачи по расписанию
Некоторую работу нужно выполнять регулярно и без участия человека: удалять старые записи, обновлять курсы валют, отправлять отчёты. В Magento для этого есть планировщик (cron): модуль описывает задачу и время запуска в файле XML, а код пишет в обычном классе.
Где лежат файлы
| Файл | Что в нём |
|---|---|
etc/crontab.xml | Список задач и расписание |
Cron/CleanReviews.php | Класс задачи |
Оба файла создают вручную.
app/code/Acme/Hello/
├── Cron/
│ └── CleanReviews.php новый файл
└── etc/
├── crontab.xml новый файл
└── module.xmlКласс задачи
Задача будет удалять отзывы без текста, которым больше года:
// app/code/Acme/Hello/Cron/CleanReviews.php
namespace Acme\Hello\Cron;
use Acme\Hello\Model\ResourceModel\Review as ReviewResource;
use Psr\Log\LoggerInterface;
class CleanReviews
{
public function __construct(
private ReviewResource $resource,
private LoggerInterface $logger,
) {}
public function execute(): void
{
$deleted = $this->resource->getConnection()->delete(
$this->resource->getMainTable(),
[
'created_at < ?' => date('Y-m-d H:i:s', strtotime('-1 year')),
'content IS NULL',
],
);
$this->logger->info('Удалено старых отзывов: ' . $deleted);
}
}Класс ни от чего не наследуется: нужен только открытый метод, который вызовет планировщик. Он удаляет строки одним запросом и пишет их число в журнал.
Расписание
<?xml version="1.0"?>
<!-- app/code/Acme/Hello/etc/crontab.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job name="acme_hello_clean_reviews" instance="Acme\Hello\Cron\CleanReviews" method="execute">
<schedule>0 3 * * *</schedule>
</job>
</group>
</config>Задача acme_hello_clean_reviews будет запускаться каждый день в три часа ночи. Тег schedule содержит пять полей: минута, час, день месяца, месяц, день недели.
| Расписание | Когда срабатывает |
|---|---|
* * * * * | Каждую минуту |
*/15 * * * * | Каждые 15 минут |
0 * * * * | В начале каждого часа |
0 3 * * * | Каждый день в 03:00 |
0 9 * * 1 | По понедельникам в 09:00 |
Проверка
Чтобы не ждать ночи, на время проверки поставьте расписание * * * * * и запустите планировщик вручную:
bin/magento cache:clean
bin/magento cron:run --group=default
bin/magento cron:run --group=defaultПервый запуск вносит задачу в очередь — таблицу cron_schedule, второй выполняет её. В файле var/log/system.log появится строка «Удалено старых отзывов». В таблице cron_schedule у задачи видны состояние (pending, success, error) и текст ошибки, если она была.
Включение планировщика на сервере
bin/magento cron:installКоманда добавляет в системный планировщик текущего пользователя строку, которая каждую минуту вызывает bin/magento cron:run. Без этого шага задачи не выполняются вовсе, а вместе с ними — индексы по расписанию и отправка писем. Проверить результат можно командой crontab -l.
Очереди сообщений
Планировщик подходит для работы «по часам». Для работы «по событию» — отправить письмо после заказа, передать заказ на склад — в Magento есть очереди сообщений. Код кладёт в очередь короткое сообщение и сразу продолжает работу, а отдельный фоновый процесс (consumer) забирает сообщения и выполняет их. Очередь описывают файлами communication.xml, queue_topology.xml, queue_publisher.xml и queue_consumer.xml, а хранится она в базе данных или в RabbitMQ. Это тема для отдельного изучения; пока достаточно знать, что такой инструмент есть.
Частая ошибка
Задача описана верно, но не выполняется, и таблица cron_schedule пуста. Причина почти всегда одна: на сервере не выполнена bin/magento cron:install или планировщик запущен от другого пользователя. Проверьте crontab -l от имени пользователя, под которым работает PHP.