Skip to content

[Console] Command::addArgument accepts mixed $default, passed to InputArgument constructor not accepting mixed #45110

Closed
@Ahummeling

Description

@Ahummeling

Symfony version(s) affected

6.0.0 6.1.x-dev

Description

Consider my method: Command::configure:

    protected function configure(): void
    {
        $this->setName('app:admin:create')
            ->setDescription('Creates a new admin user')
            ->addArgument('username', InputArgument::REQUIRED, 'Sets the username of the user to create')
            ->addArgument('password', InputArgument::OPTIONAL, 'Sets the initial password for the user', fn() => $this->passwordGenerator->generatePassword());
    }

This leads to the following error:

Symfony\Component\Console\Input\InputArgument::__construct(): Argument #4 ($default) must be of type array|string|int|float|bool|null, Closure given

How to reproduce

See code in description
Running bin/console --version was enough to trigger the type error.

Take a skeleton 6.0 symfony project, include the following snippet, and try running bin/console cache:clear -vvv for full details.

<?php
namespace App\Command;

class PasswordGenerator 
{
    public function generatePassword(): string
    {
        return 'password';
    }
}

use Symfony\Component\Console\Command\Command;
class AppCommand extends Command
    private PasswordGenerator $passwordGenerator;
    protected function configure(): void
    {
        $this->passwordGenerator = new PasswordGenerator();
        $this->setName('app:admin:create')
            ->setDescription('Creates a new admin user')
            ->addArgument('username', InputArgument::REQUIRED, 'Sets the username of the user to create')
            ->addArgument('password', InputArgument::OPTIONAL, 'Sets the initial password for the user', fn() => $this->passwordGenerator->generatePassword());
    }
}

Possible Solution

I'm actually not sure about the best way to approach this, a few ideas popped into my mind:

  • Widen the parameter type in InputArgument::__construct to accept mixed (no BC break)
  • Narrow the parameter type in Command::addArgument to also only accept string|bool|int|float|array|null (introduces BC break)
  • Narrow the parameter annotation as in the solution above, but don't change the actual function signature and then trigger a deprecation warning.
  • Validate the passed $defaultValue for the correct type and throw an InvalidArgumentException in case it's an object|resource|closure. This keeps BC in the function signatures. But it doesn't really accomplish much.

Additional Context

Would be happy to work out a solution and submit a PR if this is indeed something to be fixed.
Also, I am well aware I can transform my closure into a callable array and have it work, but the point of this issue is to point out the inconsistency in argument types.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions