tp框架开启定时任务(通过workerman+事件)完成

99 阅读1分钟
安装 composer require topthink/think-worker 扩展
配置指令在 app/config/console 文件中定义指令  'timer' => \app\console\command\Timer::class,
配置监听事件  在 app\event 文件中 
    'listen' => [  
        // 定时总任务  
        'MainTask' => [app\console\task\Main::class],  
        // 定时xx 任务  
        'Test' => [app\console\task\Test::class]  
    ],

开始创建定时任务目录

1、创建 app\console\command目录,并创建一个Timer.php 文件

<?php  
declare (strict_types = 1);  
  
namespace app\console\command;  
  
use think\console\Command;  
use think\console\Input;  
use think\console\input\Argument;  
use think\console\input\Option;  
use think\console\Output;  
use think\facade\Event;  
use Workerman\Worker;  
  
/**  
* 定时器 (Workerman)  
* 用于执行系统里的定时任务,  
* 使用方法: 打开命令行 - 执行命令: php think timer start  
* Class Timer  
* @package app\common\command  
*/  
class Timer extends Command  
{  
    // 定时器句柄/ID  
    protected $timer;  

    // 时间间隔 (单位: 秒, 默认5秒)  
    protected $interval = 1;  

    /**  
    * 指令配置  
    * @return void  
    */  
    protected function configure()  
    {  
        // 指令配置  
        $this->setName('timer')  
            ->addArgument('status', Argument::REQUIRED, 'start/stop/reload/status/connections')  
            ->addOption('d', null, Option::VALUE_NONE, 'daemon(守护进程)方式启动')  
            ->addOption('i', null, Option::VALUE_OPTIONAL, '多长时间执行一次')  
            ->setDescription('start/stop/restart 定时任务');  
    }  

    /**  
    * 初始化  
    * @param Input $input  
    * @param Output $output  
    * @return void  
    */  
    protected function init(Input $input, Output $output)  
    {  
        global $argv;  

        if ($input->hasOption('i'))  
        $this->interval = floatval($input->getOption('i'));  

        $argv[1] = $input->getArgument('status') ?: 'start';  
        if ($input->hasOption('d')) {  
            $argv[2] = '-d';  
        } else {  
            unset($argv[2]);  
        }  
    }  

    /**  
    * 创建定时器  
    * @param Input $input  
    * @param Output $output  
    * @return int|void|null  
    */  
    protected function execute(Input $input, Output $output)  
    {  
        $this->init($input, $output);  
        // 创建定时器任务  
        $worker = new Worker();  
        $worker->onWorkerStart = [$this, 'start'];  
        $worker->runAll();  
    }  

    /**  
    * 定时器执行的内容  
    * @return false|int  
    */  
    public function start()  
    {  
        // 每隔n秒执行一次  
        return $this->timer = \Workerman\Lib\Timer::add($this->interval, function () {  
            try {  
                // 这里执行系统预设的定时任务事件  
                echo 'timer...' . PHP_EOL;  
                Event::trigger('MainTask');  
            } catch (\Throwable $e) {  
                echo 'ERROR: ' . $e->getMessage() . PHP_EOL;  
                $this->stop();  
            }  
        });  
    }  

    /**  
    * 停止/删除定时器  
    * @return bool  
    */  
    public function stop()  
    {  
        return \Workerman\Lib\Timer::del($this->timer);  
    }  
}

2、创建app\console\task目录,里面创建Task.phpMain.phpTest.php文件。

1.Task.php

<?php  
  
namespace app\console\task;  
  
use think\facade\Cache;  
  
/**  
* 定时任务监听器  
* Class Listener  
* @package app\console\task  
*/  
class Task  
{  
    /**  
    * 定时执行任务  
    * @param string $key  
    * @param int $expire  
    * @param callable $callback  
    */  
    protected function setInterval(string $key, int $expire, callable $callback)  
    {  
        if (!$this->hasTaskId($key)) {  
            $this->setTaskId($key, $expire);  
            return call_user_func($callback);  
        }  
    }  

    /**  
    * 获取任务ID  
    * @param string $key  
    * @return bool  
    */  
    protected function hasTaskId(string $key): bool  
    {  
        return Cache::has("Listener:$key");  
    }  

    /**  
    * 设置任务ID  
    * 用于实现定时任务的间隔时间, 如果任务ID存在并未过期, 则不执行任务  
    * @param string $key  
    * @param int $expire 任务ID过期时长(单位:秒)  
    * @return bool  
    */  
    protected function setTaskId(string $key, int $expire = 60): bool  
    {  
        return Cache::set("Listener:$key", true, $expire);  
    }  
}
  1. Main.php
<?php  
  
namespace app\console\task;  
  
  
use think\facade\Event;  
  
class Main extends Task  
{  
    /**  
    * 任务处理  
    */  
    public function handle()  
    {  
        Event::trigger('Test',[1,2,3]);  
    }  
}

3.Test.php

<?php  
  
namespace app\console\task;  
  
class Test extends Task  
{  
    // 当前任务唯一标识  
    private $taskKey = 'xxTest';  

    // 任务执行间隔时长 (单位:秒)  
    protected $taskExpire = 10;  

    /**  
    * 任务处理  
    * @param array $param  
    */  
    public function handle(array $param)  
    {  
        $this->setInterval($this->taskKey, $this->taskExpire, function () {  
            echo $this->taskKey . PHP_EOL;  
        });  
    }  
}