Console commands
Joomla has a console program — the file cli/joomla.php. It lets you maintain the site without a browser: update it, clean the cache, create users. Your own commands are added with a plugin of the console group — handy for data imports and scheduled jobs.
Built-in commands
Commands are run from the site root folder:
php cli/joomla.php listThe list command prints all available commands with descriptions.
| Command | What it does |
|---|---|
cache:clean | Cleans the cache |
extension:list | Lists installed extensions |
extension:install --path=/tmp/mod_hello.zip | Installs an extension from an archive |
extension:discover:install | Installs extensions found by Discover |
user:add | Creates a user |
core:update | Updates Joomla |
site:down, site:up | Takes the site offline and back online |
Files of your own command
Create a plugin of the console group by hand:
plugins/console/hello/
├── hello.xml
├── services/provider.php
└── src/
├── Command/
│ └── CountCommand.php the command itself
└── Extension/
└── Hello.php the plugin: registers the commandThe manifest and the provider are the same as for the content plugin: the console group, the name plg_console_hello, the namespace My\Plugin\Console\Hello.
The command class
// plugins/console/hello/src/Command/CountCommand.php
namespace My\Plugin\Console\Hello\Command;
defined('_JEXEC') or die;
use Joomla\Console\Command\AbstractCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class CountCommand extends AbstractCommand
{
protected static $defaultName = 'hello:count';
protected function configure(): void
{
$this->setDescription('Shows the number of blog posts');
}
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->success('The command works');
return 0;
}
}$defaultName is the command name. The doExecute() method does the work and returns an exit code: 0 means success.
Registering it in the plugin
// plugins/console/hello/src/Extension/Hello.php
namespace My\Plugin\Console\Hello\Extension;
defined('_JEXEC') or die;
use Joomla\Application\ApplicationEvents;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
use My\Plugin\Console\Hello\Command\CountCommand;
final class Hello extends CMSPlugin implements SubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ApplicationEvents::BEFORE_EXECUTE => 'registerCommands',
];
}
public function registerCommands(): void
{
$this->getApplication()->addCommand(new CountCommand());
}
}The BEFORE_EXECUTE event happens before any console command runs — at that moment the plugin adds its own to the application.
Running it
Install the plugin through Discover, enable it and run:
php cli/joomla.php hello:countThe terminal shows a green line [OK] The command works. The command is also visible in the list output.
Working with the database
Now the command can do real work. Replace the body of doExecute():
// plugins/console/hello/src/Command/CountCommand.php
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$db = Factory::getContainer()->get(DatabaseInterface::class);
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__hello_posts'));
$total = (int) $db->setQuery($query)->loadResult();
(new SymfonyStyle($input, $output))->success('Posts in the blog: ' . $total);
return 0;
}The command prints [OK] Posts in the blog: 2.
Running on a schedule
Any command can be started by the system scheduler, cron. For example, the built-in Joomla task scheduler (System → Scheduled Tasks) is more reliable when called this way instead of waiting for site visitors:
*/5 * * * * php /var/www/site/cli/joomla.php scheduler:runThe line runs pending tasks every five minutes.
Common mistake
The command is run with a different PHP version than the one the site uses: on hosting the php command in the console often points to an old version. Joomla then complains about an unsuitable version or missing modules. Check php -v and, if needed, give the full path to the right PHP executable.