Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Console] Make attributes accessible on invokable commands #61078

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

Open
wants to merge 9 commits into
base: 7.4
Choose a base branch
from

Conversation

weitzman
Copy link
Contributor

@weitzman weitzman commented Jul 9, 2025

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

I'm playing with Invokable Commands and am seeing a limitation which is bothersome. Attributes attached to the invokable class are lost by the time we have a Command added to the Application. Consider an invokable class like below. The #[CLI\FieldLabels] and #[CLI\DefaultFields] Attributes are not retrievable from the Command. That is, there is no easy way to access the actual InvokableCommand object instead of the wrapping Command.

With this PR, Attributes become accessible via $command->getCode()->getCallable()

namespace Drush\Commands\core;

#[AsCommand(
    name: 'twig:unused',
    description: 'Find potentially unused Twig templates.',
    aliases: ['twu'],
)]
#[CLI\FieldLabels(labels: ['template' => 'Template', 'compiled' => 'Compiled'])]
#[CLI\DefaultFields(fields: ['template', 'compiled'])]
final class TwigUnusedCommand
{
    public function __invoke(
        #[Argument(description: 'A comma delimited list of paths to recursively search')] string $searchpaths,
        InputInterface $input,
        OutputInterface $output
    ): int
    {
        $data = $this->doExecute($searchpaths);
        $this->writeFormattedOutput($input, $output, $data);
        return Command::SUCCESS;
    }
}

@weitzman weitzman requested a review from chalasr as a code owner July 9, 2025 11:31
@carsonbot carsonbot added this to the 7.4 milestone Jul 9, 2025
@carsonbot
Copy link

Hey!

Thanks for your PR. You are targeting branch "7.4" but it seems your PR description refers to branch "7.4 for features".
Could you update the PR description or change target branch? This helps core maintainers a lot.

Cheers!

Carsonbot

@derrabus
Copy link
Member

derrabus commented Jul 9, 2025

Attributes attached to the invokable class are lost by the time we have a Command added to the Application.

Can you elaborate on this? Why are they lost?

Also: Please always provide tests that cover your change.

@weitzman
Copy link
Contributor Author

weitzman commented Jul 9, 2025

@derrabus - I added a hyperlink to the OP explaining whats meant by "wrapping command". Let me know if its still unclear.

If anyone can suggest an existing test to modify, I will do so.

@GromNaN
Copy link
Member

GromNaN commented Jul 9, 2025

I don't understand why you need to access attributes of the wrapped invokable command from the actual Command class. Attributes should not be read at runtime (for performance). You can create an autoconfiguration mechanism to read the attributes during container compilation and inject them into a service.

@chalasr
Copy link
Member

chalasr commented Jul 9, 2025

Jérôme has a good point about manipulating the command at compile time instead of runtime. When accessing the service you get the real instance .

@derrabus
Copy link
Member

derrabus commented Jul 9, 2025

Let me know if its still unclear.

It is. Your link is pointing to some line in our codebase, but that line does not explain your use-case. It neither tells me what you're trying to achieve, nor why you want to do that, nor how you tried to do that.

If anyone can suggest an existing test to modify, I will do so.

This is a new feature, which means we need new tests. You can have a look at the existing test suite for inspiration, but we won't write those tests for you. And we won't merge a new feature without any tests.

@OskarStark OskarStark changed the title Make Attributes accessible on Invokable Commands Make attributes accessible on invokable commands Jul 9, 2025
@weitzman
Copy link
Contributor Author

weitzman commented Jul 9, 2025

Apologies for not including my use case originally. I'm no Symfony expert, so your expertise here is much appreciated.

I'm the maintainer of Drush, the CLI for Drupal. Drush is a happy user of the standalone Console component.

I am exploring using Invokable Commands in our next version. Symfony made this possible in May in #60394. Drush has no command services at this time, so the suggestion to read Attributes at compile time won't work. We need a runtime solution, and so will other standalone Console users. We could read the Attributes as we add commands to the Application, but then we would have to store them separate from the Command object. Or we would have to extend Command and add a method to get the callable with its Attributes. That feels awkward enough that we wouldn't support Invokable Commands which is a shame IMO - they are great.

@GromNaN
Copy link
Member

GromNaN commented Jul 9, 2025

Thanks for the context.

I see that Drush is built with consolidation/annotated-command. Looking at its documentation for the FieldLabels and DefaultFields attributes, it looks very close to what we built with invokable commands. I do think that the two attribute systems (Symfony and Consolidation) are mutually exclusive to configure the command.

@weitzman
Copy link
Contributor Author

weitzman commented Jul 9, 2025

We are working to remove the dependency on consolidation/annotated-command in favor native Symfony Console conventions. See drush-ops/drush#6135. This Console PR is part of the effort.

Symfony Console supports a few Attributes like AsCommand and Argument and Option - we need a lot more in Drush. We can add declare Attribute classes and add them to our Invokable Commands but we can't cleanly read the Attributes - thus this PR.

FYI, I removed the return type hint to an Internal class.

@weitzman
Copy link
Contributor Author

weitzman commented Jul 10, 2025

I have added tests to the PR. I'm getting a failure because I removed the return type hint to an internal class. How can we best resolve this?

So, do we think this is solvable for us and other standalone Console users? I hope so.

Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

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

Here is a solution so keep the InvokableCommand internal.

Do you want to read the Consolidation attributes for backward compatibility? I still don't get how you will proceed.

weitzman and others added 3 commits July 10, 2025 06:19
@carsonbot carsonbot changed the title Make attributes accessible on invokable commands [Console] Make attributes accessible on invokable commands Jul 10, 2025
Co-authored-by: Jérôme Tamarelle <[email protected]>

public function __construct(
private readonly Command $command,
callable $code,
Copy link
Member

Choose a reason for hiding this comment

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

I would not rename the argument here. Naming it code is clearer about what the callable is about.

Copy link
Contributor Author

@weitzman weitzman Jul 10, 2025

Choose a reason for hiding this comment

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

I pushed some tweaks variable names. This one is now unchanged. I'm open to alternatives.

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.

7 participants