如何创建cron任务和功能

案例分析:

每5分钟检查所有pending的订单,如果有超过3小时的pending订单就自动cancel掉。

以下代码以Zou_Demo插件为例。代码都写在Zou_Demo插件里。

1,crontab.xml里定义cron,设置时间和类

vim etc/crontab.xml
<?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="PendingOrderAutoCancel" instance="Zou\Demo\Model\Cron\PendingOrderAutoCancel" method="run">
            <schedule>*/5 * * * *</schedule>
        </job>
    </group>
</config>
  1. <schedule>*/5 * * * *</schedule>里设置crontab时间
  2. instance="Zou\Demo\Model\Cron\PendingOrderAutoCancel"里定义类 逻辑代码

2,写逻辑代码

vim Model/Cron/PendingOrderAutoCancel.php
<?php
namespace Zou\Demo\Model\Cron;
class PendingOrderAutoCancel {
    public function run() {
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $scopeConfig = $objectManager->get('\Magento\Framework\App\Config\ScopeConfigInterface');
        $hours = 3;
        $_orderCollectionFactory = $objectManager->get('\Magento\Sales\Model\ResourceModel\Order\CollectionFactory');
        $orders = $_orderCollectionFactory->create()
                    // ->addAttributeToSelect(
                    //        '*'
                    //    )
                    ->addAttributeToFilter(
                        'state', ['in' => ['new', 'pending', 'pending_payment', '']]
                    )->addAttributeToSort(
                    'created_at', 'desc'
                )->load();
        //echo $orders->getSelect();
        $total = $orders->getSize();
            
        $timezoneObj = $objectManager->get('\Magento\Framework\Stdlib\DateTime\TimezoneInterface');
        $currentTime = $timezoneObj->date()->format('Y-m-d H:i:s');
        $num = 0;
        //echo date('Y-m-d h:i:s');
        $orderManagement = $objectManager->get('Magento\Sales\Api\OrderManagementInterface');
        echo "START | AUTO CANCEL AFTER [{$hours}] HOURS >>>>> \r\n";
        foreach ($orders as $order) {
            if (!$order->canCancel()) {
                continue;
            }
            $num ++;
            $oid = $order->getId();
            echo "({$num}/{$total}) #{$oid} ... ";
            $paymentMethod = $order->getPayment()->getMethodInstance()->getCode();
            //echo $paymentMethod;
            //echo $order->getUpdatedAt().'   ';
            $updatedTime = $timezoneObj->date(new \DateTime($order->getUpdatedAt()))->format('Y-m-d H:i:s');
            $times = floor((strtotime($currentTime) - strtotime($updatedTime)) / 3600);
            echo "UPDATED AT: [{$updatedTime}] | CURREN TIME: [{$currentTime}] | DIFF HOURS: [{$times}] ... ";
            if ($times > $hours) {
            	echo "CANCELING ... ";
                try {
                    $orderManagement->cancel($oid);
                    echo "DONE!\r\n";
                } catch (Exception $e) {
                    echo "FAILED: {$e->getMessage()}\n";
                }
                continue;
            }
            echo "ignore!\r\n";
        }
        echo "End \r\n";
    }
}

3,测试

你需要在服务器里配置crontab。
安装和配置M2那一章有说到。

crontab -e
* * * * * /usr/bin/php /var/www/magento2/bin/magento cron:run | grep -v "Ran jobs by schedule" >> /var/www/magento2/var/log/magento.cron.log

如何知道是否真的执行了呢?

比较死板的办法 就是看magento.cron.log了,每5分钟执行的时候 会把代码里的调试信息输出到magento.cron.log里去。

如何调试逻辑代码是否有问题呢?

需要配置下自定义的命令行工具。

1,在di.xml里定义命令行

vim etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="demo_cmd" xsi:type="object">Zou\Demo\Command\Run</item>
            </argument>
        </arguments>
    </type>
</config>

也就是说,把自定义命令行工具的逻辑代码写在Zou\Demo\Command\Run类里。

2,写逻辑代码

vim Command/Run.php
<?php
namespace Zou\Demo\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;

class Run extends Command
{
    protected $_state;
    protected $_pendingOrderAutoCancel;
    public function __construct(
        \Magento\Framework\App\State $state,
        \Zou\Demo\Model\Cron\PendingOrderAutoCancel $pendingOrderAutoCancel
    ){
        $this->_state = $state;
        $this->_pendingOrderAutoCancel = $pendingOrderAutoCancel;
        parent::__construct();
    }

    protected function configure()
    {
        $this->setName('zou:demo_run');
        $this->setDescription('Run Zou_Demo');
        parent::configure();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->_state->setAreaCode('adminhtml');
        $this->_pendingOrderAutoCancel->run();die;
    }

}

设置的命令为zou:demo_run,也就是说,在终端里执行:

php bin/magento zou:demo_run

就会执行到这个类里去,调用execute方法。

在本代码里是调用执行我们之前写的PendingOrderAutoCancel类。
如果你写了多个cron逻辑类的话,那么就定义在构造函数里,在execute方法里调用执行你想测试的类。

3,测试zou:demo_run命令是否有效
需要清下缓存。

rm generated/* -rf
rm var/di/* -rf
php bin/magento cache:clean && php bin/magento cache:flush

复制

再执行:

php bin/magento

看有没有我们的命令

再执行:

php bin/magento zou:demo_run

ok了,执行进去了,有cancel订单类的调试信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值