Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Yii Console Laravel Package

yiisoft/yii-console

Yii Console provides a lightweight framework for building command-line applications with Yii3. Define commands, route arguments and options, handle input/output, generate help, and manage exit codes. It includes a console runner, command routing, and flexible I/O abstractions for extensible CLI tool...

Deep Wiki
Context7

Getting Started

  • Install: composer require yiisoft/yii-console. In a Yii3 application template it is already present (usually pulled in by yiisoft/yii-runner-console), which also gives you the yii entry script at the project root.
  • Look here first:
    • ./yii (or vendor/bin/yii) — the runner entrypoint.
    • config/console.php / config/commands.php — where Application and CommandLoader are wired.
    • vendor/yiisoft/yii-console/src/ — a small surface: Application, Command, CommandLoader, ExitCode, Stdio. Read it in ~20 minutes.
    • vendor/symfony/console — 90% of behavior lives here; yii-console is a thin DI/loader layer on top.
  • Smoke test: ./yii list, ./yii help, ./yii help <command>.
  • First command (register it in the loader/commands map, then run ./yii hello):
<?php
declare(strict_types=1);
namespace App\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Yiisoft\Yii\Console\Command;
use Yiisoft\Yii\Console\ExitCode;

final class HelloCommand extends Command
{
    public function __construct(private readonly Clock $clock)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->setName('hello')
            ->setDescription('Say hello');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $output->writeln('Hello, ' . $this->clock->now()->format('H:i'));
        return ExitCode::OK;
    }
}
  • First real use case: replace a shell script with an injectable command — cache:clear, db:seed, user:create — reusing the services you already register in the container instead of bootstrapping by hand.

Implementation Patterns

Pick a base class

  • Yiisoft\Yii\Console\Command for app commands — DI-friendly convenience base.
  • Symfony\Component\Console\Command\Command directly when reusing third-party commands.
  • #[ConsoleCommand(name: 'user:create', description: '...', hidden: false)] on the class when your loader supports attribute discovery; keep argument/option declarations in configure() regardless.

Constructor injection is the point

  • Resolve repositories, mailers, caches, clocks through the container.
  • CommandLoader is lazy: heavy dependencies are only built when the command actually runs, so ./yii list stays fast.
  • Keep constructors cheap; do all work in execute().

Arguments and options

  • InputArgument::REQUIRED|OPTIONAL|IS_ARRAY and InputOption::VALUE_NONE|VALUE_REQUIRED|VALUE_OPTIONAL|VALUE_IS_ARRAY|VALUE_NEGATABLE.
  • No attribute-based binding here — declare in configure(), read with $input->getArgument() / $input->getOption().
  • Provide sensible defaults and the usual --dry-run / --force / --limit conventions.

Output and UX

  • Prefer SymfonyStyle for tables, sections, progress bars and questions: $io = new SymfonyStyle($input, $output); $io->table(...).
  • Respect verbosity: $output->writeln($msg, OutputInterface::VERBOSITY_VERBOSE).
  • Send diagnostics to STDERR ($output->getErrorOutput() or fwrite(STDERR, ...)), never mix them into machine-readable stdout.
  • Gate prompts on $input->isInteractive(); always support -n / --no-interaction.

Exit codes

  • Always return an int. ExitCode::OK (0) for success; non-zero for failure.
  • Throwing a RuntimeException is fine — the Application renders it — but returning 0 from a failed command is the most common CI bug.

Startup / shutdown hooks

  • Register listeners on ApplicationStartup and ApplicationShutdown for timing, logging, advisory locks, memory guards and cleanup.
  • These fire around the top-level Application::run(), not for commands invoked programmatically — don't rely on them for invariants inside the command itself.

Long-running commands

  • Implement SignalableCommandInterface and handle SIGINT/SIGTERM for a clean exit code.
  • Bound loops with --limit / --max-iterations, print progress, and make commands idempotent.

Testing

  • CommandTester / ApplicationTester from symfony/console; build the command with real services or test doubles.
  • Assert getStatusCode() and getDisplay(); use setInputs() for prompts and ['interactive' => false] in CI.

Registration and naming

  • Register once, centrally (config/commands.php, or the CommandLoader commands map, or attribute scan).
  • Namespace with : (user:create, cache:clear) so ./yii list groups them.

Gotchas and Tips

  • Registration is the #1 stumble. A class with execute() is not a command until the loader/container knows it. Attribute discovery only works when the loader is configured to scan; otherwise add it to the commands map. ./yii list is the first debug step.
  • exit() inside execute() breaks everything — no shutdown events, no testability, CommandTester can't capture the code. Return the int.
  • Reserved names and options. help, list, completion, --help, --version, --quiet, --verbose, --no-interaction are Symfony-owned. Don't shadow them.
  • Command name collisions silently pick one; prefix with the module name.
  • Use setAutoExit(false) and setCatchExceptions(false) in tests so failures surface instead of being swallowed and rendered by the Application.
  • Constructor side effects slow list. DB connects, HTTP clients and similar belong behind lazy container resolution inside execute(). If ./yii list takes more than ~200ms, you're bootstrapping too much.
  • OutputInterface vs ConsoleOutputInterface. Check/cast before calling getErrorOutput(). Under -q (common in CI) all writeln output disappears — write errors to STDERR so they survive.
  • Interactive prompts block in CI and daemons. Gate on $input->isInteractive(), and guard fgets(STDIN)/QuestionHelper too — STDIN may not exist without a tty.
  • Returning null from execute() is fatal in Symfony Console. Return an int or throw.
  • Debugging: ./yii list -vvv, ./yii help <cmd>, and fwrite(STDERR, ...) for ad-hoc dumps so machine-readable stdout stays clean.
  • Extension points: the underlying Application is a Symfony Application — add(), getDefinition(), getHelperSet(), setCatchExceptions() all work. For middleware-like behavior, wrap the runner in the yii script rather than monkey-patching commands.
  • Scheduling is not in this package. Wire ./yii <command> into cron/systemd timers; keep commands idempotent and safe to re-run.
  • Version pinning: yiisoft/yii-console tracks Symfony Console majors; a Symfony bump can change helpers and SignalableCommandInterface behavior. Read the changelog before a major upgrade and run your command test suite.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo