Skip to content

Support invokable console commands#91

Open
maryo wants to merge 4 commits into
contributte:masterfrom
maryo:master
Open

Support invokable console commands#91
maryo wants to merge 4 commits into
contributte:masterfrom
maryo:master

Conversation

@maryo

@maryo maryo commented Jul 12, 2026

Copy link
Copy Markdown

Symfony 7.3 introduced invokable commands - plain classes with a public __invoke() method that don't extend Command at all. This PR adds support for that.

What changed

ConsoleExtension no longer only looks for services via findByType(Command::class). A service is now registered as a console command if it meets at least one of these conditions:

  • it extends Symfony\Component\Console\Command\Command (unchanged, existing behavior)
  • it carries the console.command tag
  • it's annotated with #[AsCommand]

Services that don't extend Command are wrapped into a synthetic console.<service>.command Command instance via Command::setCode(), the same way Symfony's own AddConsoleCommandPass does it for the framework bundle. If a service is tagged/annotated but neither extends Command nor has a public __invoke() method, a Nette\DI\ServiceCreationException is thrown.

Also adds support for #[AsCommand]'s usages option (extra usage examples shown in --help).
This bumped the minimum required symfony/console version to ^7.4.0 (from ^7.2.0), since that's when the usages parameter was added to the attribute.

Dropped the Command::$defaultName property fallback - the currently installed Command class (and the whole ^7.4.0 || ^8.0.0 range we now require) no longer declares that property at all, having replaced it first with getDefaultName() and later with #[AsCommand], so this branch could only ever fire for a hand-rolled Command subclass still using the pre-Symfony-5.0 convention, which isn't realistic to encounter alongside such a recent symfony/console requirement.

Symfony also supports #[AsCommand] on individual methods, so the method doesn't have to be named __invoke and a single class can expose multiple commands this way. I didn't want to add that complexity here, so I only added support for __invoke.

maryo added 2 commits July 12, 2026 21:45
Services no longer need to extend Symfony's Command class to be registered
as console commands. A service is now treated as one if it extends Command,
carries the "console.command" tag, or is annotated with #[AsCommand] - the
latter two are wrapped into a synthetic "<service>.command" Command instance
via Command::setCode(), mirroring Symfony's own AddConsoleCommandPass.

Also adds support for #[AsCommand]'s "usages" (extra usage examples shown
in --help).
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.47619% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.65%. Comparing base (0d0e339) to head (9234fed).

Files with missing lines Patch % Lines
src/DI/ConsoleExtension.php 90.47% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #91      +/-   ##
==========================================
- Coverage   96.07%   94.65%   -1.43%     
==========================================
  Files           5        5              
  Lines         102      131      +29     
==========================================
+ Hits           98      124      +26     
- Misses          4        7       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maryo

maryo commented Jul 12, 2026

Copy link
Copy Markdown
Author

After looking at the Codecov report, I bumped the minimum required version of symfony/console and added a bit more coverage. What's still uncovered isn't easy to test, so I wouldn't worry about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant