Magento 2のデータベースからcronjob動的スケジュールを設定する方法


7

私はMagento 2のカスタムモジュールに取り組んでいます。そこでcrontabをセットアップしましたが、静的スケジュールでうまく機能しています。

<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>

しかし、データベースに保存されている値から動的な値が必要<schedule>* * * * * *</schedule>です。ここでは3つのスケジュールを使用する必要がありますDaily Weekly Monthly

頻度はすでにデータベースに保存されています ここに画像の説明を入力してください

動的スケジュールをそこに追加するにはどうすればよいですか?

回答:


10

思ったほど簡単ではありません。

まずcrontab.xml、設定パスを周波数に設定するようにを更新する必要があります。

<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>

ここで、頻度を選択できるように構成にフィールドを追加する必要があります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>

次にVendor\Module\Model\Config\Backend\Frequency、周波数バックエンドモデルを作成する必要があります。

<?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();
    }
}

このコードは一見トリッキーに見えますが、基本的crontab/default/jobs/tm_feed_job/schedule/cron_exprには周波数ドロップダウンで選択したものに基づいて構成パスを生成します。

興味深いサイドノートの発見:これは、M2のいくつかのモジュールにネイティブに実装され、通貨、製品アラート、バックアップ、サイトマップが含まれます。興味深いのは、これらのモジュールのいくつかに対してバックエンドモデルが定義されているところです。

  • 製品アラート: Magento\Cron\Model\Config\Backend\Product\Alert
  • サイトマップ: Magento\Cron\Model\Config\Backend\Sitemap

ええ、あなたはそれを正しく読みました。これらのバックエンドモデルは、対応するモジュールフォルダーではなく、Magento\Cronモジュールフォルダーの下にあります。


注意をありがとう-しかし、ここでrunModelが何をしているのかを尋ねたかった。Pelaseの説明
Abid Malik

あなたはいつも良い解決策を思い付きます。+1 :)
Shoaib Munir

どのような使用runModelPathですか?これを追加する必要がありますか?
DJ Dev

magento 2.3.3では機能しません。cronは、構成で設定された時間どおりに実行されません。私のcronは毎日00:01に実行されますが、時間を10:30に設定し、頻度を「毎日」に設定しています。
nil108

0

見てみる\Magento\Cron\Observer\ProcessCronQueueObserver::_generateJobsと、それぞれの<config_path>値を読み取るために、指定された構成キーにvarchar入力を作成するだけで十分ですcore_config_data

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.