Skip to content

[Console][FrameworkBundle] Simplify using invokable commands when the component is used standalone #60394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

HypeMC
Copy link
Member

@HypeMC HypeMC commented May 9, 2025

Q A
Branch? 7.4
Bug fix? no
New feature? yes
Deprecations? yes
Issues -
License MIT

Inspired by #60389 (comment) .

This PR enables using invokable command when the component is used standalone:

#[AsCommand(name: 'app:example')]
class ExampleCommand implements SignalableCommandInterface
{
    public function __invoke(InputInterface $input, OutputInterface $output): int
    {
        // ...

        return Command::SUCCESS;
    }

    public function getSubscribedSignals(): array
    {
        return [\SIGINT, \SIGTERM];
    }

    public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
    {
        // handle signal

        return 0;
    }
}

$application = new Application();
$application->addCommand(new ExampleCommand());
$application->run();

@OskarStark
Copy link
Contributor

So we really need the extra method addInvokable() or could we handle this automatically?

@xabbuh
Copy link
Member

xabbuh commented May 10, 2025

We cannot widen the argument type in add() as that would be a BC break for child classes overriding the method.

@HypeMC HypeMC force-pushed the simplify-invokable-commands-when-standalone branch from e07ce18 to 5cf2a0d Compare May 10, 2025 08:33
@OskarStark
Copy link
Contributor

We could remove it and handle it internally, couldn't we?

Do we need to adjust addCommands() method as well?

@chalasr
Copy link
Member

chalasr commented May 11, 2025

Cool, thanks for working on this.

We could remove it and handle it internally, couldn't we?

@OskarStark If you mean removing the type declaration then it's a BC break too unfortunately, see https://3v4l.org/5dhmc.

I'd prefer the invokable concept not to leak into public API though. What about adding Application::addCommand(callable|Command $command): Command instead? It would be great if that new method could provide a way to make the command lazy also.

@HypeMC HypeMC force-pushed the simplify-invokable-commands-when-standalone branch 2 times, most recently from 758b85e to 2a19b9b Compare May 13, 2025 23:18
@HypeMC
Copy link
Member Author

HypeMC commented May 13, 2025

I'd prefer the invokable concept not to leak into public API though. What about adding Application::addCommand(callable|Command $command): Command instead? It would be great if that new method could provide a way to make the command lazy also.

@chalasr I've made the changes you requested, please let me know what you think.

@fabpot fabpot modified the milestones: 7.3, 7.4 May 26, 2025
Copy link
Contributor

@weitzman weitzman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. This PR would be helpful for the Drush project (the main CLI for Drupal).

@yceruto
Copy link
Member

yceruto commented Jun 5, 2025

Wondering now that a new method is being added with support for both types of commands, shouldn’t we deprecate the Application::add() in favor of Application::addCommand() method to improve the API in version 8.0?

@@ -2514,6 +2570,22 @@ public function isEnabled(): bool
}
}

#[AsCommand(name: 'invokable')]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[AsCommand(name: 'invokable')]
#[AsCommand(name: 'invokable', aliases: 'invk')]

I did some testing on Drush and I am seeing the PR fail when an invokable command uses an alias. If you accept my suggestion above, hopefully the tests fail.

The problem is that $attribute->name is a pipe delimited string consisting of the name, followed by the aliases. See \Symfony\Component\Console\Attribute\AsCommand::__construct.

The code below helped me get past this bug. Not sure if there are better ways to solve it

$aliases = explode('|', $attribute->name);
$name = array_shift($aliases);
$commandHandler = (new Command($name))
    ->setAliases($aliases)
    ...
       

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #60739

@chalasr
Copy link
Member

chalasr commented Jun 5, 2025

@yceruto 👍 for deprecating add(), that's what I had in mind.

@carsonbot carsonbot changed the title [Console] Simplify using invokable commands when the component is used standalone [Console][FrameworkBundle] Simplify using invokable commands when the component is used standalone Jun 7, 2025
@HypeMC
Copy link
Member Author

HypeMC commented Jun 7, 2025

@yceruto @chalasr I've deprecated the add() method.

@HypeMC HypeMC reopened this Jun 8, 2025
@HypeMC HypeMC force-pushed the simplify-invokable-commands-when-standalone branch from f2722a2 to c3f55f3 Compare June 8, 2025 12:53
@yceruto
Copy link
Member

yceruto commented Jun 8, 2025

@HypeMC it seems high-deps failures are related https://github.com/symfony/symfony/actions/runs/15518654102/job/43689003684?pr=60394, right?

Copy link
Member

@yceruto yceruto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HypeMC it seems high-deps failures are related https://github.com/symfony/symfony/actions/runs/15518654102/job/43689003684?pr=60394, right?

Nevermind, it might be related to the 8.0 branch and should be resolved once this PR is merged into it.

@HypeMC HypeMC force-pushed the simplify-invokable-commands-when-standalone branch from c3f55f3 to 1886c10 Compare June 9, 2025 15:40
@chalasr
Copy link
Member

chalasr commented Jun 11, 2025

Thank you @HypeMC.

@chalasr chalasr merged commit e9ad816 into symfony:7.4 Jun 11, 2025
8 of 11 checks passed
@HypeMC HypeMC deleted the simplify-invokable-commands-when-standalone branch June 11, 2025 22:45
crynobone added a commit to laravel/framework that referenced this pull request Jun 12, 2025
Symfony Console deprecate `add()` method and instead calls
`addCommand()` method from `addCommands()`. This cause the application
not to have the correct instance of `$laravel` property.

PR: <symfony/symfony#60394>

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
taylorotwell pushed a commit to laravel/framework that referenced this pull request Jun 12, 2025
Symfony Console deprecate `add()` method and instead calls
`addCommand()` method from `addCommands()`. This cause the application
not to have the correct instance of `$laravel` property.

PR: <symfony/symfony#60394>

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
taylorotwell pushed a commit to illuminate/console that referenced this pull request Jun 12, 2025
Symfony Console deprecate `add()` method and instead calls
`addCommand()` method from `addCommands()`. This cause the application
not to have the correct instance of `$laravel` property.

PR: <symfony/symfony#60394>

Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
nicolas-grekas added a commit that referenced this pull request Jun 13, 2025
This PR was merged into the 6.4 branch.

Discussion
----------

[Runtime] fix compatibility with Symfony 7.4

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        |
| License       | MIT

Since #60394 using `add()` is deprecated. This means that our tests can trigger deprecations on older branches when the high deps job is run. This usually is not an issue as we silence them with the `SYMFONY_DEPRECATIONS_HELPER` env var. However, phpt tests are run in a child process where the deprecation error handler of the PHPUnit bridge doesn't step in. Thus, for them deprecations are not silenced leading to failures.

We did something similar before in #60376.

Commits
-------

d39a7ac fix compatibility with Symfony 7.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants