tp5.1最新版集成workerman如何自定义命令并把业务逻辑写到控制器里

最新的tp5.1集成workerman提供了两个web_server和socket_server的例子,其中socket_server可以在配置文件中直接设置workerman回调函数,也是很方便的.

不过我个人觉得这样很不方便,不太优雅,这种方式只是把原来workerman的业务代码放到tp5里,如果是我,我会觉得把这部分代码写到控制器里会舒服一些.

并且官方没有给出更灵活的开发workerman的方式,比如我只想用workerman的多进程特性做爬虫,官方的手册没有提供相关例子,所以我在这记录下我的解决方式.

目标

我可以使用下面的命令启动我的爬虫,并且我只需要关注workerman的onworkerstart回调,把业务代码写到控制器里.

php think spider start

方式

  • 利用tp5.1的自定义指令特性
  • 在相关控制器直接继承wokerman的worker类
  • 在指令部分把控制器的方法赋值到wokerman的属性中做为回调方法

自定义指令

详细的做法请参考tp官方手册,这里直接贴步骤.

修改application/command.php

return [
    'app\common\command\Spider',
];

新建common模块,command目录,spider类

tp5.1最新版集成workerman如何自定义命令并把业务逻辑写到控制器里_第1张图片

代码:可以直接复制,我也是在文档上复制下来的

setName('spider')
            ->addArgument('status', Argument::OPTIONAL, "命令")
        	->setDescription('spider control');
    }

    protected function execute(Input $input, Output $output)
    {
        $status  = $input->getArgument('status');
        if(!$status){
            $output->writeln('pelase input control command , like start');
        }

        if($status == 'start'){

            $output->writeln('start running spider');
            $spider = new Start();
            

            foreach (['onWorkerStart', 'onConnect', 'onMessage', 'onClose', 'onError', 'onBufferFull', 'onBufferDrain', 'onWorkerStop', 'onWorkerReload'] as $event) {
                if (method_exists($spider, $event)) {
                    
                    $spider->$event = [$spider,$event];
                    
                }
            }
            
            $spider->runAll();
        }
    }
}

代码的基本逻辑:

执行指令,

如果是"start"参数,那么实例化start类(该类继承自worker),

将spider里的方法赋值到worker的属性中,作为回调函数

运行.

自定义类

该类继承worker类,里面设置方法作为workerman的回调,

新建模块spider,控制器start,里面设置onworkerstart等方法.

tp5.1最新版集成workerman如何自定义命令并把业务逻辑写到控制器里_第2张图片

代码:

基本逻辑:

在这个类里重写了worker的两个方法,否则不能运行.

在onworkerstart里写逻辑即可.

 


注意:

为什么重写这两个方法:

public static function runAll(){
}

public static function parseCommand(){
}

这两个是worker的基本的方法,按理说不用理会才对,但是我在运行中发现,如果不重写,就不会运行spider模块start类里的方法.

程序运行到parseCommand处,会引入业务文件,其中会判断这个是否有"php"扩展名,没有的话跳过.

在我们运行的"php think spider start"中,think就是我们运行的文件,但这个文件不带有php扩展,workerman就不会把这个文件当做业务文件引入,不会执行其中的逻辑,就是说根本就没运行你写的start类.

并且我发现如果修改think为think.php会报错,暂时不清楚出错的原因.

解决这个问题有两个方法,一个是直接修改worker的parseCommand方法,把这段代码注释掉,就想在上面的代码那样.但是修改vender的内容很粗鲁(很不优雅),所以只有在子类中重写才可以.

那为什么还要重写runAll方法呢?

如上面代码中所示,runAll方法是静态方法,且调用其他静态方法,由于php的后期静态绑定特性,不能重写即:

show();

上面这段代码,如果son类中,没有show方法,输出为"father",只有重写了show方法才会输出"son".

另外:我记得一开始father类中show方法不加static,能输出son,就是说子类的sayMyName重写了父类的方法,但是在项目中并不生效,后来查了手册,发现了这个特性,但是这时无论我怎么做,都不能输出son了,重写show方法才能输出son,好幽灵啊~就想一个假世界一样,我不清楚的内容是随机的,当我清楚之后才是固定的.

因为这个原因,必须重写这两个方法才行.


这样,终于可以把workerman的业务代码写到控制器里.

你可能感兴趣的:(php)