Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Задачи по расписанию

Некоторую работу нужно выполнять регулярно и без участия человека: удалять старые записи, обновлять курсы валют, отправлять отчёты. В 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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.