案例分析:
每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>
<schedule>*/5 * * * *</schedule>
里设置crontab时间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订单类的调试信息。