更新记录的预定命令

Scheduled Command to update records

大家早上好,

我正在尝试创建一个命令,我可以安排它来检查认证日期是否已过期,如果已过期,则将布尔值从 0 更新为 1。我以前从未使用过命令,我已经阅读了 OctoberCMS 文档但我发现它很混乱。

如果有人能帮助我,那将是完美的。

这是我目前的情况。

<?php

namespace Bitpixlimited\Concert\Console;

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use BitpixLimited\ConCert\Models\Certification;
use Carbon\Carbon;

/**
 * CheckExpiredCertifications Command
 */
class CheckExpiredCertifications extends Command
{
    /**
     * @var string name is the console command name
     */
    protected $name = 'concert:checkexpiredcertifications';

    /**
     * @var string description is the console command description
     */
    protected $description = 'No description provided yet...';

    /**
     * handle executes the console command
     */
    public function handle()
    {
        $certifications = Certification::all();
        $date = now();
        $expiredValue = '1';

        foreach ($certifications as $certification) {

            if ($certification->expiry_date < $date) {

                $certification->status = $expiredValue;
            
            }

            $certification->save();
        }
    }

    /**
     * getArguments get the console command arguments
     */
    protected function getArguments()
    {
        return [];
    }

    /**
     * getOptions get the console command options
     */
    protected function getOptions()
    {
        return [];
    }
}

看看这段代码:

public function handle()
{
    $certifications = Certification::query()
        ->where('expiry_date', '<', now())
        ->update(['status' => '1'])
}

它实现了您想要实现的目标,它是您代码的简化版本,而且性能更高。

  1. 我们实际上 get 没有记录,我们直接更新它们
  2. 我们更新所有在 now()
  3. 之前具有 expiry_date 的记录
  4. 所有这些记录现在 status 等于 1

由于我们不将记录存储在内存中并且我们不需要“构建”集合,因此性能要好得多。

缺点是您会丢失模型事件(如果您声明了任何事件)和修改器,但我认为这里不是这种情况。

如果您需要访问所有模型的修改器、方法、事件(现在或将来),请使用以下代码:

public function handle()
{
    $certifications = Certification::query()
        ->where('expiry_date', '<', now())
        ->each(function(Certification $certification){
            $certification->status = '1';
            $certification->save();
        });
}

主要区别在于我们实际上检索记录并构建所有 Certification 实例。它为您提供更多功能,但性能会受到影响。

有更多优化方法可以做到这一点,尤其是当你有大量行时,但这是另一个话题。


您应该 运行 在您的调度程序中以您希望的频率执行此命令,例如每分钟:

protected function schedule(Schedule $schedule)
{
    $schedule->command('concert:checkexpiredcertifications')->everyMinute();
}

每分钟,我们将更新所有过去有 expiry_date 的记录,并将它们的 status 设置为 '1'

当然,您必须有一个有效的调度程序才能执行此操作,但这有点偏离主题(此处的文档:https://laravel.com/docs/8.x/scheduling#running-the-scheduler)。