Magento 2 – How to Use Configuration Field for Crontab Expression

configurationcroncrontabmagento-2.0magento2

In Magento 1, instead of declaring the cron expression directly like this:

<crontab> 
    <jobs> 
        <vendor_module_cron>
            <schedule>*/30 * * * *</schedule>
            <run>
                <model>module/observer::runCron</model>
            </run>
        </vendor_module_cron>
    </jobs> 
</crontab>

you could setup your crontab like this in the config.xml:

<crontab> 
    <jobs> 
        <vendor_module_cron>
            <schedule>
                <config_path>vendor/module/cron_expr</config_path>
            </schedule>
            <run>
                <model>module/observer::runCron</model>
            </run>
        </vendor_module_cron>
    </jobs> 
</crontab>

Where Magento would use Mage::getStoreConfig((string)$jobConfig->schedule->config_path) to get the cron schedule expression.

This way you could dynamically change the schedule from the backend without having to modify the config.xml file directly.

How can we achieve this in Magento 2 ? Is it still possible ?

Best Answer

Following ProductAlerts in M2:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="catalog_product_alert" instance="Magento\ProductAlert\Model\Observer" method="process">
            <config_path>crontab/default/jobs/catalog_product_alert/schedule/cron_expr</config_path>
        </job>
    </group>
</config>

You should be able to define something similarly:

<?xml version="1.0"?>
<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="custom_job_name" instance="Namespace\Module\Model\Observer" method="process">
            <config_path>namespace/module/schedule/cron_expr</config_path>
        </job>
    </group>
</config>

You could leverage the way they interpret the expression through multiple fields but it shouldn't be required, such as:

<group id="productalert_cron" translate="label" type="text" sortOrder="260" showInDefault="1" showInWebsite="0" showInStore="0">
    <label>Product Alerts Run 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>Magento\Cron\Model\Config\Backend\Product\Alert</backend_model>
    </field>
    <field id="time" translate="label" type="time" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
        <label>Start Time</label>
    </field>

This would make the input user-friendly (so-to-speak) but is not required, a simple text field that allows you to enter an expression like 7 7 * * * would be fine as well, I would just put some validation on that field to make sure the expression is correct.

Related Topic