framework icon indicating copy to clipboard operation
framework copied to clipboard

Input类hasArgument()和hasOption()处理不一致

Open amonest opened this issue 3 years ago • 0 comments

我使用TP6.0.12创建自定义的命令HelloCommand:

<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;

class HelloCommand extends Command
{
    protected function configure()
    {
        $this->setName('hello')
            ->setDescription('Hello command')
            ->addArgument('name', Argument::OPTIONAL, "your name")
            ->addOption('city', null, Option::VALUE_REQUIRED, 'city name');
    }

    protected function execute(Input $input, Output $output)
    {
        $name = trim($input->getArgument('name')) ?: 'thinkphp';

        if ($input->hasOption('city')) {
            $city = PHP_EOL . 'From ' . $input->getOption('city');
        } else {
            $city = '';
        }

        $output->writeln("Hello, " . $name . '!' . $city);
    }
}

当执行如下命令时

php think hello

提示如下的错误信息

[TypeError]
trim() expects parameter 1 to be string, null given

Exception trace:
 () at D:\PHPSTUDY\WWW\thinkphp6\app\command\HelloCommand.php:25
 trim() at D:\PHPSTUDY\WWW\thinkphp6\app\command\HelloCommand.php:25
 app\command\HelloCommand->execute() at D:\PHPSTUDY\WWW\thinkphp6\vendor\topthink\framework\src\think\console\Command.php:210
 think\console\Command->run() at D:\PHPSTUDY\WWW\thinkphp6\vendor\topthink\framework\src\think\Console.php:655
 think\Console->doRunCommand() at D:\PHPSTUDY\WWW\thinkphp6\vendor\topthink\framework\src\think\Console.php:314
 think\Console->doRun() at D:\PHPSTUDY\WWW\thinkphp6\vendor\topthink\framework\src\think\Console.php:251
 think\Console->run() at D:\PHPSTUDY\WWW\thinkphp6\think:10

我查了Input类这两个方法的实现方式,发现hasArgument()方法的实现与hasOption()不同。 hasArgument()方法取消isset($this->arguments)的检查,这样才能确保有CLI有提供值时才会返回true。

    /**
     * 检查是否存在某个参数
     * @param string|int $name 参数名或位置
     * @return bool
     */
    public function hasArgument($name): bool
    {
        return $this->definition->hasArgument($name);
    }

    /**
     * 是否有某个选项
     * @param string $name 选项名
     * @return bool
     */
    public function hasOption(string $name): bool
    {
        return $this->definition->hasOption($name) && isset($this->options[$name]);
    }

amonest avatar May 19 '22 03:05 amonest