How To Set up Custom Cron Job in Magento 2?

Today, we’re going to teach you guys how to set up a custom cron job in Magento 2 store.

Setting up a custom cron job basically allows you to schedule Cron dynamically. But many times developers use static time expressions for setting a Cron Job in a custom module.

Later, when they make any sort of changes to the time expression, it becomes necessary to change the crontab.xml file.

Fortunately, it is possible to avoid this issue. In other words, it is possible to make changes to the time expression without necessarily having to make changes to the crontab.xml file.

In this tutorial, we’ll show you exactly how you can set up a custom cron job by configuration in your Magento 2 store.

Steps to Set Up a Custom Cron Job By Configuration in Magento 2

Please follow the below steps to learn how to set up a custom cron job by configuration so that you don’t have to make changes to the crontab.xml file when you make changes to the time expression.

Step - 1

First of all, you need to create a crontab.xml file in the app\code\MageDelight\Crontime\etc\ folder and paste the following code:

<?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 instance="MageDelight\Crontime\Cron\Cronfile" method="execute" name="my_cron_job">

            <config_path>crontab/default/jobs/my_cron_job/schedule/cron_expr</config_path>

        </job>

    </group>

</config>

Step - 2

After that, you need to create a system.xml file for the CRON configuration in the app\code\MageDelight\Crontime\etc\adminhtml\ folder and paste the following code:

<group id="configurable_cron"

       translate="label"

       type="text" sortOrder="10" showInDefault="1" showInWebsite="1" 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>MageDelight\Crontime\Model\Config\Cronconfig</backend_model>

    </field>

    <field id="time" 

           translate="label comment"

           sortOrder="2" type="time" showInDefault="1" showInWebsite="1" showInStore="1">

        <label>Start Time</label>

    </field>

</group>

Step - 3

Next, create a Cronconfig.php file in the app\code\MageDelight\Crontime\Model\Config\ folder and paste the following code:

<?php

namespace MageDelight\Crontime\Model\Config;

use Magento\Cron\Model\Config\Source\Frequency;

use Magento\Framework\App\Cache\TypeListInterface;

use Magento\Framework\App\Config\ScopeConfigInterface;

use Magento\Framework\App\Config\Value;

use Magento\Framework\App\Config\ValueFactory;

use Magento\Framework\Data\Collection\AbstractDb;

use Magento\Framework\Model\Context;

use Magento\Framework\Model\ResourceModel\AbstractResource;

use Magento\Framework\Registry;

class Cronconfig extends Value

{

    public const CRON_STRING_PATH = 'crontab/default/jobs/my_cron_job/schedule/cron_expr';

    public const CRON_MODEL_PATH = 'crontab/default/jobs/my_cron_job/run/model';

    /**

     * @var ValueFactory

     */

    protected $_configValueFactory;

    /**

     * @var mixed|string

     */

    protected $_runModelPath = '';

    /**

     * CronConfig constructor.

     * 

     * @param Context $context

     * @param Registry $registry

     * @param ScopeConfigInterface $config

     * @param TypeListInterface $cacheTypeList

     * @param ValueFactory $configValueFactory

     * @param AbstractResource|null $resource

     * @param AbstractDb|null $resourceCollection

     * @param string $runModelPath

     * @param array $data

     */

    public function __construct(

        Context $context,

        Registry $registry,

        ScopeConfigInterface $config,

        TypeListInterface $cacheTypeList,

        ValueFactory $configValueFactory,

        AbstractResource $resource = null,

        AbstractDb $resourceCollection = null,

        $runModelPath = '',

        array $data = []

    ) {

        $this->_runModelPath = $runModelPath;

        $this->_configValueFactory = $configValueFactory;

        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);

    }

    /**

     * @return CronConfig

     * @throws \Exception

     */

    public function afterSave()

    {

        $time = $this->getData('groups/configurable_cron/fields/time/value');

        $frequency = $this->getData('groups/configurable_cron/fields/frequency/value');

        $cronExprArray = [

            (int)$time[1],

            (int)$time[0],

            $frequency == Frequency::CRON_MONTHLY ? '1' : '*',

            '*',

            $frequency == Frequency::CRON_WEEKLY ? '1' : '*',

        ];

        $cronExprString = implode(' ', $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(__('Some Thing Want Wrong , We can\'t save the cron expression.'));

        }

        return parent::afterSave();

    }

}

Step - 4

Now, create a Cronfile.php file in the app\code\MageDelight\Crontime\Cron\ folder and paste the following code:

<?php

namespace MageDelight\Crontime\Cron;

class Cronfile

{

    public function execute()

    {

        //Add your cron executed code here.

    }

}

Lastly, save all files and check the output.

Final Words…

And that’s it!

This is how you can set up a custom Cron Job quickly in your Magento 2 store.

And if you need our professional assistance, feel free to contact us at any time.