如何在 CakePHP 4 的插件中创建自定义命令?

How do you create a custom command in a plugin in CakePHP 4?

我正在插件中构建命令,但难以协调 plugin example in the book with the Command one。我明白了:

Exception: Cannot use 'MyNamespace\MyCommand' for command 'my_namespace my'. It is not a subclass of Cake\Console\Shell or Cake\Command\CommandInterface.
In [/path/to/vendor/cakephp/cakephp/src/Console/CommandCollection.php, line 68]

仔细观察 CommandCollection::add() 我明白了

    /**
     * Add a command to the collection
     *
     * @param string $name The name of the command you want to map.
     * @param string|\Cake\Console\Shell|\Cake\Console\CommandInterface $command The command to map.
     *   Can be a FQCN, Shell instance or CommandInterface instance.
     * @return $this
     * @throws \InvalidArgumentException
     */
    public function add(string $name, $command)
    {
        if (!is_subclass_of($command, Shell::class) && !is_subclass_of($command, CommandInterface::class)) {
            $class = is_string($command) ? $command : get_class($command);
            throw new InvalidArgumentException(sprintf(
                "Cannot use '%s' for command '%s'. " .
                "It is not a subclass of Cake\Console\Shell or Cake\Command\CommandInterface.",
                $class,
                $name
            ));
        }
...

有两件事跳出来了:

  1. 为什么要检查 $command 是接口的子类?它不应该迭代 class_implements() 而不是检查吗?
  2. 异常消息看起来有错别字:它不应该引用 Cake\Console\CommandInterface 吗?

如果有更完整的使用命令创建自定义插件的示例,我将不胜感激。

  1. \Cake\Console\Shell 没有实现接口,所以 class_implements() 不起作用。 \Cake\Console\Command(分别是新的 \Cake\Command\Command)确实实现了一个接口,所以 class_implements() 可以工作,但是 is_subclass_of() 也可以,它也会检查接口,所以它实际上并没有有所作为。

  2. 是的,应该的。当命令被移动到 Command 命名空间时,这可能被意外更改(\Cake\Command\Command 以前是 \Cake\Console\Command)。

错误消息表明您的自定义命令 class 既没有扩展 \Cake\Command\Command(或 \Cake\Console\BaseCommand),也没有实现 \Cake\Console\CommandInterface,或者传递给 CommandCollection::add() 指向一个 wrong/non-existent class.