Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Custom commands

Not everything on a site happens on a browser request: a mailing, cleaning up old records or a nightly report is started from the terminal or on a schedule. Such tasks are written as custom commands, which are run like the built-in ones: bin/cake name.

Creating

Commands live in the src/Command folder:

bin/cake bake command Stats
// src/Command/StatsCommand.php
namespace App\Command;
 
use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
 
class StatsCommand extends Command
{
    public function execute(Arguments $args, ConsoleIo $io): int
    {
        $io->out('Hello from the command!');
 
        return static::CODE_SUCCESS;
    }
}

The code of a command is in the execute() method. The $io object prints text to the terminal. The method returns an exit code: CODE_SUCCESS means all is well and CODE_ERROR means an error.

Running

bin/cake stats

The command name comes from the class name: StatsCommand gives stats, SendReportCommand gives send_report. The terminal shows "Hello from the command!".

Working with the database

public function execute(Arguments $args, ConsoleIo $io): int
{
    $total = $this->fetchTable('Articles')->find()->count();
 
    $io->out("Articles in the database: $total");
 
    return static::CODE_SUCCESS;
}

A command has no $this->Articles, so the table is obtained with fetchTable(). After that it is used as in a controller.

Arguments and options

An argument is a required value after the command name, and an option is an optional setting with two hyphens. They are described in a separate method:

use Cake\Console\ConsoleOptionParser;
 
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
{
    return $parser
        ->addArgument('email', ['help' => 'Where to send the report', 'required' => true])
        ->addOption('limit', ['help' => 'How many articles', 'default' => '10']);
}
 
public function execute(Arguments $args, ConsoleIo $io): int
{
    $email = $args->getArgument('email');
    $limit = (int) $args->getOption('limit');
 
    $io->success("A report on $limit articles was sent to $email");
 
    return static::CODE_SUCCESS;
}
bin/cake stats admin@example.com --limit=5

The command prints "A report on 5 articles was sent to admin@example.com". The help texts are shown by bin/cake stats --help.

Output

MethodWhat it does
$io->out('…')Prints a line
$io->success('…')A green success message
$io->warning('…')A warning
$io->error('…')An error message
$io->ask('Continue?')Asks a question and returns the answer

Running on a schedule

On a server commands are started by the cron scheduler. A line is added with the crontab -e command:

0 9 * * 1 cd /var/www/blog && bin/cake stats admin@example.com

The report is sent every Monday at nine in the morning.

Common mistake

Cron runs a command outside the project folder and with a different set of environment variables. Without cd /var/www/blog && at the start of the line bin/cake is not found and the task silently does not run. Always include the change to the project folder and check the run by hand with the same line.

Thanks for reading!

Donate to the site — we work hard for you.