Я создаю приложение на Cake PHP 3.8, которое использует консольные команды для выполнения нескольких процессов.
Эти процессы довольно ресурсоемкие, поэтому я написал их с помощью команд потому что они могут легко истечь по тайм-ауту, если они выполняются в браузере. выполняется по порядку (Этап 1 ... Этап 5) вручную , т.е. src/Command/Stage1Command.php
выполняется с:
$ php bin/cake.php stage1
Все 5 команд принимают один параметр - идентификатор - а затем выполняют некоторые работы. Это было настроено следующим образом (код в 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;
}
}
Итак, я могу выполнить «Этап 1» следующим образом, предполагая, что 428
- это идентификатор, который я хочу pass.
$ php bin/cake.php stage1 428
Вместо того, чтобы выполнять их вручную, я хочу достичь следующего:
Создайте новую команду, которая проходит через набор идентификаторов фильтра, а затем вызывает каждую из 5 команд, передавая идентификатор.
Обновить таблицу, чтобы показать результат (успех, ошибка) каждой команды.
Для (1) я создал src/Command/RunAllCommand.php
, а затем использовал al oop в моей таблице фильтров, чтобы сгенерировать идентификаторы, а затем выполнить 5 команд, передав идентификатор. Скрипт выглядит так:
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);
}
}
}
Это не работает. Выдает ошибку:
Идентификатор фильтра должен быть передан в качестве аргумента
Я могу сказать, что команды вызываются, потому что это мои собственные сообщения об ошибках от buildOptionsParser()
.
Это не имеет смысла, потому что строка $io->out($filter['id'])
в RunAllCommand.php
показывает, что идентификаторы фильтров считываются из моей базы данных. Как передать аргумент таким образом? Я слежу за документами по вызову других команд (https://book.cakephp.org/3/en/console-and-shells/commands.html#calling -другие-команды ).
Я не понимаю, как достичь (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 . Это означает, что процессы, выполняемые каждым этапом, будут происходить через равные промежутки времени, не требуя ручного выполнения каких-либо сценариев или передачи идентификаторов вручную в качестве параметров команды.