我正在 CakePHP 3.8 中构建一个应用程序,它使用控制台命令来执行多个进程。
这些过程非常耗费资源,所以我用命令编写它们,因为如果在浏览器中执行它们很容易超时。
有 5 个不同的脚本执行不同的任务:src/Command/Stage1Command.php
, ... src/Command/Stage5Command.php
。
脚本正在按顺序(第 1 阶段 ... 第 5 阶段)手动执行,即src/Command/Stage1Command.php
通过以下方式执行:
$ php bin/cake.php stage1
所有 5 个命令都接受一个参数 - 一个 ID - 然后执行一些工作。这已设置如下(buildOptionsParser()
每个命令中都存在代码):
class Stage1Command extends Command
{
protected function buildOptionParser(ConsoleOptionParser $parser)
{
$parser->addArgument('filter_id', [
'help' => 'Filter ID must be passed as an argument',
'required' => true
]);
return $parser;
}
}
所以我可以如下执行“Stage 1”,假设428
是我要传递的ID。
$ php bin/cake.php stage1 428
我不想手动执行这些,而是要实现以下目标:
创建一个循环遍历一组过滤器 ID 的新命令,然后调用 5 个命令中的每一个,并传递 ID。
更新表格以显示每个命令的结果(成功、错误)。
对于 (1) 我已经创建src/Command/RunAllCommand.php
然后在我的过滤器表上使用一个循环来生成 ID,然后执行 5 个命令,传递 ID。脚本如下所示:
namespace App\Command;
use Cake\ORM\TableRegistry;
// ...
class RunAllCommand extends Command
{
public function execute(Arguments $args, ConsoleIo $io)
{
$FiltersTable = TableRegistry::getTableLocator()->get('Filters');
$all_filters = $FiltersTable->find()->toArray();
foreach ($all_filters as $k => $filter) {
$io->out($filter['id']);
// execute Stage1Command.php
$command = new Stage1Command(['filter_id' => $filter['id']]);
$this->executeCommand($command);
// ...
// execute Stage5Command.php
$command5 = new Stage5Command(['filter_id' => $filter['id']]);
$this->executeCommand($command5);
}
}
}
这行不通。它给出了一个错误:
过滤器 ID 必须作为参数传递
我可以看出正在调用这些命令,因为这些是我自己的错误消息buildOptionsParser()
。
这是没有意义的,因为输入的行$io->out($filter['id'])
显示RunAllCommand.php
过滤器 ID 正在从我的数据库中读取。你如何以这种方式传递论点?我正在关注有关调用其他命令的文档(https://book.cakephp.org/3/en/console-and-shells/commands.html#calling-other-commands)。
我不明白如何实现(2)。在每个命令中,我添加了这样的代码,当发生错误时会停止执行该命令的其余部分。例如,如果这被执行,Stage1Command
它应该中止并移动到Stage2Command
:
// e.g. this code can be anywhere in execute() in any of the 5 commands where an error occurs.
$io->error('error message');
$this->abort();
如果$this->abort()
在任何地方被调用,我需要将其记录到数据库中的另一个表中。$this->abort()
在将其写入数据库之前是否需要添加代码,或者是否有其他方式try...catch
,例如RunAllCommand
?
背景信息:这个想法是RunAllCommand.php
通过Cron执行。这意味着每个阶段执行的过程将定期发生,而无需手动执行任何脚本 - 或手动传递 ID 作为命令参数。