The Quantum PHP Framework ships with a real console application, not just a few helper scripts.
In the starter project, the qt file boots the console app like this:
$status = AppFactory::create(AppType::CONSOLE, __DIR__)->start();That means when you run commands such as php qt serve, you are using the framework's console layer directly.
The console command system is split across the core framework and the starter project.
The core framework provides:
- the base command class:
Quantum\Console\CliCommand - command discovery:
Quantum\Console\CommandDiscovery - built-in commands such as:
serveroute:listmodule:generatemigration:generatemigration:migratecore:envcore:keyinstall:toolkitcache:clearinstall:openapicron:run(See Cron Scheduling)install:debugbarcore:version
The starter project adds its own project-level commands under:
shared/Commands/
Examples from the starter project include:
DemoCommandUserCreateCommandUserDeleteCommandUserShowCommandPostCreateCommandPostUpdateCommandPostDeleteCommandPostShowCommandCommentCreateCommandCommentDeleteCommand
So the command system is designed to be extendable. The framework gives you the console infrastructure, and the project can add its own app-specific commands.
From the upstream CommandDiscovery, Quantum scans a directory of PHP classes, checks whether each class exists, and keeps only classes that are instantiable subclasses of CliCommand.
In practice, that means a command is discovered when it:
- exists in the expected commands directory
- is autoloadable
- extends
Quantum\Console\CliCommand - can be instantiated
Note: The ConsoleAppAdapter special-cases core:env boot stages to ensure the environment is ready for command discovery and execution.
This makes the console layer convention-based, similar to other Quantum subsystems.
All framework-style commands extend Quantum\Console\CliCommand.
That base class gives commands:
- a command name
- a description
- optional help text
- argument definitions
- option definitions
- helper methods such as:
getArgument()getOption()info()comment()question()error()confirm()
The actual command logic lives in:
public function exec(): voidThat is the method your command implements.
A typical command class in Quantum defines a few protected properties and then implements exec().
A simplified example, based on the real command structure, looks like this:
class ExampleCommand extends CliCommand
{
protected ?string $name = 'example:run';
protected ?string $description = 'Runs the example command';
protected array $args = [
['name', 'required', 'The name value'],
];
protected array $options = [
['yes', 'y', 'none', 'Accept confirmation'],
];
public function exec(): void
{
$name = $this->getArgument('name');
if (!$this->getOption('yes') && !$this->confirm('Continue?')) {
$this->info('Operation was canceled!');
return;
}
$this->info('Hello ' . $name);
}
}The exact business logic depends on the command, but the class shape stays consistent.
From the current upstream commands, the built-in console commands roughly group into these categories.
serve
This starts the PHP development server from the project, scans for an available port, and can optionally open a browser.
route:list
This loads module routes, builds a route collection, and renders a console table with module, method, URI, action, and middleware.
module:generate
This creates a new module using a selected template such as DefaultWeb, DefaultApi, DemoWeb, or DemoApi.
It also updates module configuration after generating the files.
migration:generatemigration:migrate
These commands create migration files and apply migrations.
The migrate command also supports:
- optional direction argument such as
down --stepoption- confirmation before destructive rollback behavior
core:envcore:key
These commands help prepare the local project environment.
core:env copies .env.example to .env.
core:key generates an APP_KEY and writes it into .env.
install:debugbarinstall:openapiinstall:toolkitcache:clear
These commands handle framework-published assets, OpenAPI resources, Toolkit scaffolding, and resource cache cleanup.
The starter project also demonstrates how application-specific commands can be more advanced.
For example, DemoCommand in shared/Commands/:
- extends
CliCommand - uses
install:demoas its command name - defines the
--yesoption - uses confirmation prompts
- runs multi-step project setup logic
- coordinates other commands such as:
module:generatemigration:migrate- user/post/comment commands
This is important because it shows that Quantum commands are not limited to tiny one-step actions. They can orchestrate real project workflows.
In CliCommand, command arguments and options are declared as arrays.
Argument definitions use values such as:
requiredoptionalarray
Example shape:
protected array $args = [
['module', 'required', 'The module name'],
];Option definitions use values such as:
nonerequiredoptionalarray
Example shape:
protected array $options = [
['template', 't', 'optional', 'The module template', 'DefaultWeb'],
['yes', 'y', 'none', 'Accept confirmation'],
];This array-based approach is part of how Quantum keeps command definitions compact.
One nice detail in the upstream command layer is that commands have small convenience methods for console interaction.
That includes:
info()for success/info outputcomment()for neutral notesquestion()for question-style outputerror()for errorsconfirm()for yes/no confirmation
This makes command code easier to read than manually working with raw Symfony Console output everywhere.
A useful way to look at it is:
- the
qtfile is the project entry point frameworkprovides the command framework and built-in commandsprojectshows how projects add their own commandsCliCommandis the base shape for framework-style console commands
Once that clicks, the console side of Quantum becomes much easier to extend.
The framework provides an integrated scheduler for automating recurring tasks.
Tasks are discovered by scanning PHP files within the configured cron.path directory (defaulting to base_dir()/cron). Each file must return an object implementing CronTaskInterface or an array with the following structure:
- Structure:
['name' => '...', 'expression' => '* * * * *', 'callback' => ...] - Expression: Uses standard crontab-like syntax.
- Callback: A callable function or service method to execute.
When cron:run is invoked, the CronManager:
- Task Discovery: Scans the configured cron directory for task files.
- Locking Mechanism: Utilizes
CronLockto manage task exclusivity.- Acquire/Release: Prevents concurrent execution of the same task.
- Run Statistics: Returns an array of execution statistics including
total,executed,skipped,failed, andlockedtask counts. - Bypass: Use
--forcewithcron:runto bypass lock acquisition and release.
Note: The scheduler requires a system-level crontab entry to trigger php qt cron:run periodically.
This page fits well with: