Cách đặt lịch trình động cronjob từ cơ sở dữ liệu trong Magento 2


7

Tôi đang làm việc trên một mô-đun tùy chỉnh cho Magento 2. Tôi đã thiết lập crontab ở đó và nó hoạt động tốt với lịch trình tĩnh.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../app/code/Magento/Cron/etc/crontab.xsd">
    <group id="default">
        <job name="tm-feed-job" instance="TM\Feed\Model\Cron" method="export">
            <schedule>* * * * * *</schedule>
        </job>
    </group>
</config>

Nhưng tôi cần <schedule>* * * * * *</schedule>động từ giá trị lưu cơ sở dữ liệu của tôi. Ở đây tôi cần sử dụng 3 lịch trìnhDaily Weekly Monthly

Tần suất đã được lưu trong cơ sở dữ liệu nhập mô tả hình ảnh ở đây

Làm thế nào tôi có thể thêm lịch trình năng động ở đó?

Câu trả lời:


10

Không dễ như tôi tưởng.

Trước tiên, bạn cần cập nhật crontab.xmlđể thiết lập đường dẫn cấu hình theo tần số của bạn:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../app/code/Magento/Cron/etc/crontab.xsd">
    <group id="default">
        <job name="tm-feed-job" instance="TM\Feed\Model\Cron" method="export">
            <config_path>crontab/default/jobs/tm_feed_job/schedule/cron_expr</config_path>
        </job>
    </group>
</config>

Bây giờ bạn cần thêm một trường vào cấu hình để có thể chọn tần số trong adminhtml/system.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="vendor">
            <group id="module" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                <label>Cron Settings</label>
                <field id="frequency" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>Frequency</label>
                    <source_model>Magento\Cron\Model\Config\Source\Frequency</source_model>
                    <backend_model>Vendor\Module\Model\Config\Backend\Frequency</backend_model>
                </field>
                <field id="time" translate="label" type="time" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>Start Time</label>
                </field>
            </group>
        </section>
    </system>
</config>

Bây giờ chúng ta cần tạo Vendor\Module\Model\Config\Backend\Frequencycho mô hình phụ trợ tần số:

<?php

namespace Vendor\Module\Model\Config\Backend;

class Frequency extends \Magento\Framework\App\Config\Value
{
    /**
     * Cron string path
     */
    const CRON_STRING_PATH = 'crontab/default/jobs/tm_feed_job/schedule/cron_expr';

    /**
     * Cron model path
     */
    const CRON_MODEL_PATH = 'crontab/default/jobs/tm_feed_job/run/model';

    /**
     * @var \Magento\Framework\App\Config\ValueFactory
     */
    protected $_configValueFactory;

    /**
     * @var string
     */
    protected $_runModelPath = '';

    /**
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $config
     * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
     * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory
     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
     * @param string $runModelPath
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\App\Config\ScopeConfigInterface $config,
        \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
        \Magento\Framework\App\Config\ValueFactory $configValueFactory,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        $runModelPath = '',
        array $data = []
    ) {
        $this->_runModelPath = $runModelPath;
        $this->_configValueFactory = $configValueFactory;
        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
    }

    /**
     * {@inheritdoc}
     *
     * @return $this
     * @throws \Exception
     */
    public function afterSave()
    {
        $time = $this->getData('groups/module/fields/time/value');
        $frequency = $this->getData('groups/module/fields/frequency/value');

        $cronExprArray = [
            intval($time[1]), //Minute
            intval($time[0]), //Hour
            $frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_MONTHLY ? '1' : '*', //Day of the Month
            '*', //Month of the Year
            $frequency == \Magento\Cron\Model\Config\Source\Frequency::CRON_WEEKLY ? '1' : '*', //Day of the Week
        ];

        $cronExprString = join(' ', $cronExprArray);

        try {
            $this->_configValueFactory->create()->load(
                self::CRON_STRING_PATH,
                'path'
            )->setValue(
                $cronExprString
            )->setPath(
                self::CRON_STRING_PATH
            )->save();
            $this->_configValueFactory->create()->load(
                self::CRON_MODEL_PATH,
                'path'
            )->setValue(
                $this->_runModelPath
            )->setPath(
                self::CRON_MODEL_PATH
            )->save();
        } catch (\Exception $e) {
            throw new \Exception(__('We can\'t save the cron expression.'));
        }

        return parent::afterSave();
    }
}

Mã này thoạt nhìn có vẻ khó khăn nhưng về cơ bản nó tạo ra crontab/default/jobs/tm_feed_job/schedule/cron_exprđường dẫn cấu hình dựa trên những gì bạn đã chọn trong trình đơn thả xuống tần số.

Tìm kiếm ghi chú bên thú vị: điều này được triển khai cho một vài mô-đun trong M2 nguyên bản bao gồm tiền tệ, cảnh báo sản phẩm, sao lưu, sơ đồ trang web. Điều thú vị là nơi mô hình phụ trợ được xác định cho một số mô-đun đó:

  • Thông báo sản phẩm: Magento\Cron\Model\Config\Backend\Product\Alert
  • Sơ đồ trang web: Magento\Cron\Model\Config\Backend\Sitemap

Vì vậy, yeah bạn đọc nó đúng. Thay vì nằm trong thư mục mô-đun tương ứng, các mô hình phụ trợ này được đặt trong Magento\Cronthư mục mô-đun.


cảm ơn bạn đã lưu ý - nhưng muốn hỏi runModel đang làm gì ở đây. Pelase giải thích
Abid Malik

Bạn luôn đưa ra một giải pháp tốt. +1 :)
Shoaib Munir

Việc sử dụng là runModelPathgì? Có cần phải thêm điều này?
DJ Dev

nó không hoạt động trong magento 2.3.3. cron không chạy theo thời gian được đặt trong cấu hình. cron của tôi chạy lúc 00:01 mỗi ngày nhưng tôi đã đặt thời gian 10:30 và Tần suất "Hàng ngày".
108

0

Khi nhìn vào \Magento\Cron\Observer\ProcessCronQueueObserver::_generateJobsnó sẽ đủ để tạo ra một đầu vào varchar tại khóa cấu hình được chỉ định cho <config_path>giá trị tương ứng của bạn được đọc từ đó core_config_data.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.