Command Line Console Plugins in Joomla
De meeste mensen leren Joomla kennen via de webinterface: de voorkant die bezoekers zien en het beheergedeelte waar je op inlogt. Maar er is een tweede, stillere ingang naar precies dezelfde site, een die helemaal geen browser nodig heeft: de command line.
Dit artikel legt uit hoe de CLI (Command Line Interface) van Joomla en de bijbehorende console-plugins echt werken. Het begint met de basis voor site-eigenaren en beheerders die gewoon een commando willen geven, en gaat daarna verder met de technische details voor ontwikkelaars die hun eigen commando's willen bouwen en als plugin willen uitleveren.
Een PHP-ingang waarmee het hele CMS wordt opgestart zonder ook maar een enkel HTTP-verzoek.
Het doel is simpel: dat je de Joomla CLI goed genoeg leert begrijpen om hem veilig te gebruiken. En daarmee je onderhoud te automatiseren en het uit te breiden met je eigen commando's.
1. De Basis
1.1 Wat is de Joomla CLI?
De CLI is een manier om Joomla vanuit een terminal te draaien in plaats van vanuit een browser. Je typt een commando, Joomla voert het uit, drukt het resultaat als tekst af en stopt. Er is geen pagina, geen template en geen bezoeker.
De enige ingang is een bestand in je site:
cli/joomla.php
Je start het met PHP op de server:
php cli/joomla.php list
Dat commando start de hele Joomla-applicatie op de achtergrond op en drukt vervolgens een lijst af van elk commando dat het kent. De website en de CLI delen dezelfde code, dezelfde database en dezelfde configuratie. Het enige verschil is, hoe je ze bereikt.
1.2 Waarom uberhaupt een command line?
Sommige klussen zijn simpelweg makkelijker, sneller of veiliger zonder browser:
- Automatisering. Een geplande taak (cron) kan elke nacht een commando draaien zonder dat er iemand bij is.
- Onderhoud. Leeg de cache, voer databasereparaties uit of zet de site offline in een regel.
- Bulkwerk. Voeg veel gebruikers toe, installeer extensies of bouw de zoekindex opnieuw op zonder door schermen te klikken.
- Herstel. Als de beheerkant op slot zit of stuk is, kun je via de CLI vaak nog een wachtwoord resetten of de site weer online brengen.
- Snelheid. Een commando gebruikt niet je Joomla template, geen modules en slaat daarm het renderen van de pagina over, dus het start en eindigt snel.
Zie de CLI als de personeelsingang van je Joomla-site: hetzelfde gebouw, dezelfde kamers, maar een ingang bedoeld voor personeel en machines in plaats van het publiek.
1.3 De vorm van een commando
Elk Joomla-commando volgt hetzelfde leesbare patroon. De naam gebruikt dubbele punten om verwante acties te groeperen:
php cli/joomla.php extension:install --path=/tmp/mod_hello.zip
| |
| └─ opties (beginnen met --)
└─ de commandonaam (groep:actie)
- De commandonaam vertelt Joomla wat het moet doen, bijvoorbeeld
cache:cleanofuser:add. - Argumenten zijn waarden die het commando op een vaste plek verwacht.
- Opties beginnen met
--en mogen in elke volgorde staan, bijvoorbeeld--path=....
Deze naamgeving is geen versiering. Het deel voor de dubbele punt is een namespace, dus alle extension:*-commando's horen bij elkaar en kunnen als groep worden getoond.
2. Je eerste commando's draaien
2.1 list en help
Twee ingebouwde commando's vertellen je al het andere. Begin hier op elke site:
php cli/joomla.php list # toon elk beschikbaar commando
php cli/joomla.php list extension # toon alleen de extension:*-commando's
php cli/joomla.php help user:add # toon hoe een commando werkt
Het commando help drukt de beschrijving, de argumenten en de opties van een enkel commando af. Als je niet zeker weet wat een commando nodig heeft, vraag het dan eerst met help voordat je het draait.
2.2 De globale opties
Een set opties werkt op elk commando, omdat de applicatie ze een keer voor allemaal definieert:
| Optie | Kort | Wat het doet |
|---|---|---|
--help |
-h |
Toon de help voor het commando |
--quiet |
-q |
Onderdruk alle uitvoer |
--verbose |
-v, -vv, -vvv |
Toon meer detail (meer letters, meer detail) |
--version |
-V |
Druk de applicatieversie af |
--no-interaction |
-n |
Stel nooit vragen; gebruik standaardwaarden of faal |
--ansi / --no-ansi |
- | Forceer of schakel gekleurde uitvoer uit |
De optie --no-interaction is belangrijk voor automatisering. Een commando dat normaal "Weet je het zeker?" vraagt, blijft eeuwig hangen in een cronjob, tenzij je het vertelt om niet te vragen.
2.3 Het resultaat lezen: de exit-code
Een commando drukt tekst af voor mensen, maar geeft ook een getal terug voor machines. Deze exit-code is hoe een script weet of het commando is gelukt:
| Exit-code | Betekenis |
|---|---|
0 |
Geslaagd |
1 |
Mislukt (het commando draaide, maar de klus slaagde niet) |
2 |
Ongeldig (verkeerde argumenten of opties) |
In een shell kun je het direct na het commando controleren met echo $?. Cron- en deploytools gebruiken dit getal om te bepalen of ze doorgaan of stoppen.
3. Een rondleiding langs de Joomla core commando's
Joomla 6 wordt geleverd met een handige set commando's, kant-en-klaar. Je installeert niets; ze horen bij de core. Hier zijn de families die je het meest zult gebruiken.
3.1 Cache, configuratie en sitestatus
| Commando | Wat het doet |
|---|---|
cache:clean |
Leeg de systeemcache (voeg expired toe om alleen verlopen items te verwijderen) |
config:get / config:set |
Lees of wijzig een waarde in configuration.php |
site:down / site:up |
Zet de site in of uit de offline-modus |
maintenance:database |
Voer databasereparaties en structuurcontroles uit |
3.2 Gebruikers
| Commando | Wat het doet |
|---|---|
user:add |
Maak een gebruiker aan (vraagt om de details, of geef ze als opties) |
user:list |
Toon de bestaande gebruikers |
user:reset-password |
Stel een nieuw wachtwoord in voor een gebruiker |
user:addtogroup / user:removefromgroup |
Beheer groepslidmaatschap |
user:delete |
Verwijder een gebruiker |
Alleen al het commando user:reset-password is het waard om te kennen: het is de standaardmanier om weer binnen te komen als je buitengesloten bent van de beheerlogin.
3.3 Extensies en updates
| Commando | Wat het doet |
|---|---|
extension:install --path=... |
Installeer een extensie vanuit een zip of map |
extension:list |
Toon geinstalleerde extensies |
extension:enable / extension:disable |
Zet een extensie aan of uit |
extension:remove |
Verwijder een extensie |
extension:discover / extension:discover:install |
Vind en installeer bestanden die handmatig op de server zijn gezet |
update:extensions:check |
Controleer op beschikbare extensie-updates |
core:update |
Update Joomla zelf |
3.4 Scheduler, zoeken en sessies
| Commando | Wat het doet |
|---|---|
scheduler:run |
Draai geplande taken die aan de beurt zijn (de cron-ingang) |
scheduler:list / scheduler:state |
Toon taken en zet ze aan of uit |
finder:index |
Bouw de Smart Search-index opnieuw op |
session:gc / session:metadata:gc |
Ruim oude sessies op |
Je hoeft deze lijst niet uit je hoofd te leren. Draai php cli/joomla.php list op je eigen site en de actuele, exacte set wordt voor je afgedrukt.
4. De anatomie van de CLI-applicatie
Voor ontwikkelaars helpt het om te zien hoe weinig er tussen de terminal en het draaiende CMS staat. De CLI is een kleine, heldere stack.
4.1 De ingang
Alles begint in cli/joomla.php. Dat bestand doet een paar zorgvuldige controles, start vervolgens Joomla op en draait de applicatie:
Verzoek vanuit de terminal
│
v
Controleer de PHP-versie (Joomla 6 vereist PHP 8.3+)
│
v
Laad defines + framework (includes/framework.php)
│
v
Start de DI-container op (Factory::getContainer())
│
v
Haal de Console-applicatie op en roep execute() aan
De relevante regels zijn kort en het waard om een keer te lezen:
$container = \Joomla\CMS\Factory::getContainer();
$app = $container->get(\Joomla\Console\Application::class);
\Joomla\CMS\Factory::$application = $app;
$app->execute();
Vanaf hier is Joomla volledig opgestart. Je commando heeft de database, het gebruikerssysteem, de taalbestanden en de event-dispatcher, precies zoals een webverzoek, maar dan zonder de HTTP-laag en het template.
4.2 Gebouwd op Symfony Console
Joomla vindt het wiel hier niet opnieuw uit. De CLI is gebouwd op de bekende bibliotheek Symfony Console, ingepakt door het framework-pakket Joomla Console. Daarom voelen de helpschermen, het verwerken van opties en de gekleurde uitvoer vertrouwd aan, als je andere moderne PHP-tools hebt gebruikt.
De klasse die je in cli/joomla.php bereikt is de framework-klasse \Joomla\Console\Application. Het CMS breidt die uit met \Joomla\CMS\Application\ConsoleApplication, die de Joomla-specifieke bedrading toevoegt: de database, de taal en het pluginsysteem.
4.3 De CLI-sessie
Een browserverzoek heeft een sessie op basis van cookies. De command line heeft die niet, dus Joomla wisselt naar een speciale CLI-sessie-backend. In cli/joomla.php zie je dat de applicatie de normale session-service koppelt aan session.cli. Daarom kan CLI-code nog steeds gebruikers- en sessie-API's aanroepen zonder dat er ooit een browser bij betrokken is.
5. Hoe commando's worden geregistreerd
Een commando is een kleine klasse die Joomla weet te vinden en uit te voeren. Er zijn twee manieren waarop een commando de applicatie bereikt, en als je beide begrijpt, snap je hoe het hele systeem netjes uitbreidt.
5.1 Standaardcommando's
De CMS-applicatie noemt zijn eigen ingebouwde commando's in een methode genaamd getDefaultCommands(). Elk ervan is een klasse die wordt aangemaakt als de applicatie start:
protected function getDefaultCommands(): array
{
return array_merge(parent::getDefaultCommands(), [
new Console\CleanCacheCommand(),
new Console\AddUserCommand($this->getDatabase()),
// ... en meer
]);
}
De eigen commando's list en help van het framework komen uit parent::getDefaultCommands(). Het CMS voegt de Joomla-specifieke daar bovenop toe.
5.2 "Luie" commando's via de DI-container
Bij elke afzonderlijke CLI-aanroep tientallen commando-objecten aanmaken zou verspilling zijn, omdat je er altijd maar een draait. Daarom worden de meeste core commando's lazy geregistreerd: Joomla houdt een simpele koppeling bij van commandonaam naar klassenaam en bouwt het object pas als je dat commando daadwerkelijk aanroept.
// Vereenvoudigd: een naam -> klasse-koppeling die aan een command loader wordt gegeven
$mapping = [
'cache:clean' => CleanCacheCommand::class,
'extension:install' => ExtensionInstallCommand::class,
'scheduler:run' => TasksRunCommand::class,
// ...
];
$app->setCommandLoader(new WritableContainerLoader($container, $mapping));
De command loader vraagt de klasse pas op bij de DI-container als de naam ervan wordt opgevraagd. Dit houdt de CLI snel: er wordt niets zwaars gebouwd totdat het nodig is.
5.3 De twee paden in een plaatje
Console-applicatie
├─ getDefaultCommands() → meteen aangemaakt (list, help, een paar core commando's)
├─ command loader (DI-map) → lui aangemaakt, alleen bij aanroep
└─ console-plugins → voegen commando's toe tijdens runtime (zie volgende sectie)
Het derde pad, console-plugins, is hoe jouw extensie de lijst binnenkomt zonder ook maar een core bestand aan te raken.
Naar boven6. Console-plugins: de CLI uitbreiden
Dit is het hart van het artikel voor ontwikkelaars. Een console-plugin is een gewone Joomla-plugin met als taak om een of meer commando's aan de CLI toe te voegen. Hij hoort bij de plugingroep console.
6.1 De plugingroep console
Als de CLI-applicatie draait, importeert hij een paar plugingroepen zodat ze naar events kunnen luisteren. Een ervan is console:
// Binnen ConsoleApplication::execute()
PluginHelper::importPlugin('behaviour', null, true, $this->getDispatcher());
PluginHelper::importPlugin('system', null, true, $this->getDispatcher());
PluginHelper::importPlugin('console', null, true, $this->getDispatcher());
Net zoals content-plugins reageren op artikelen en system-plugins reageren op de levenscyclus van een verzoek, reageren console-plugins op het opstarten van de CLI. (Let op: system-plugins laden ook op de CLI, dus een system-plugin kan ook een commando registreren. Een speciale console-plugin is simpelweg de duidelijkste plek voor commando-code.)
6.2 Het event: voeg commando's toe voor Execute
De applicatie vuurt een event af vlak voordat het gevraagde commando draait: ApplicationEvents::BEFORE_EXECUTE. Een console-plugin abonneert zich op dat event en gebruikt het om zijn commando's aan de applicatie toe te voegen:
use Joomla\Application\ApplicationEvents;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
final class MyCli extends CMSPlugin implements SubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [ApplicationEvents::BEFORE_EXECUTE => 'registerCommands'];
}
public function registerCommands(): void
{
$this->getApplication()->addCommand(new HelloCommand());
}
}
Dat is de hele truc. De plugin draait het commando niet zelf; hij geeft het commando-object simpelweg door aan de applicatie. Joomla toont het vervolgens in list, laat het zien in help en draait het wanneer de naam ervan wordt getypt.
6.3 Waarom een plugin en niet gewoon een script?
Je zou een losstaand PHP-script kunnen schrijven, maar een console-plugin geeft je alles wat het CMS al biedt:
- Een consistente naam in
php cli/joomla.php list, naast de core commando's. - Ingebouwde help, verwerking van argumenten en gekleurde uitvoer.
- Volledige toegang tot het opgestarte CMS: database, gebruikers, componenten, taal.
- Een nette installatie en verwijdering via de normale extensie-installer.
Het meegeleverde commando scheduler:run is een goed voorbeeld van dit ontwerp in de core: het commando zit in het CMS, en het systeem voor geplande taken van Joomla loopt erdoorheen. Daarom kan een enkele cron-regel elke geplande taak op de site triggeren.
7. Je eigen commando bouwen
Een commando is een enkele klasse die AbstractCommand uitbreidt. Het heeft een naam nodig, een optionele configuratie van argumenten en opties, en de code om te draaien.
7.1 Het minimale commando
use Joomla\Console\Command\AbstractCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;
final class HelloCommand extends AbstractCommand
{
// De commandonaam, zoals getypt in de terminal:
protected static $defaultName = 'hello:world';
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('Hallo vanuit de Joomla CLI');
$io->success('Het werkt.');
return Command::SUCCESS; // exit-code 0
}
}
Draai het met php cli/joomla.php hello:world zodra de plugin die het toevoegt is ingeschakeld.
7.2 Argumenten en opties configureren
Overschrijf configure() om te bepalen wat je commando accepteert en om de helptekst te schrijven:
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
protected function configure(): void
{
$this->setDescription('Begroet iemand vanaf de command line');
$this->addArgument('name', InputArgument::OPTIONAL, 'Wie te begroeten', 'world');
$this->addOption('shout', null, InputOption::VALUE_NONE, 'Gebruik hoofdletters');
$this->setHelp('Dit commando drukt een vriendelijke begroeting af.');
}
| Idee | Argument | Optie |
|---|---|---|
| Geschreven als | hello:world Peter |
hello:world --shout |
| Positie | Vaste volgorde | Elke volgorde |
| Goed voor | Het hoofdonderwerp van het commando | Vlaggen en benoemde instellingen |
7.3 Invoer lezen en een resultaat teruggeven
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$name = $input->getArgument('name');
if ($input->getOption('shout')) {
$name = strtoupper($name);
}
$io->writeln('Hallo, ' . $name . '!');
return Command::SUCCESS;
}
Geef altijd een van de benoemde exit-codes terug - Command::SUCCESS, Command::FAILURE of Command::INVALID - zodat scripts en cronjobs op de uitkomst kunnen reageren.
7.4 Praten met het CMS
Omdat het CMS volledig is opgestart, kan je commando dezelfde moderne API's gebruiken als een controller of model. Om met een component te werken, start je het op en vraag je de factory om een model:
$model = $this->getApplication()
->bootComponent('com_content')
->getMVCFactory()
->createModel('Articles', 'Administrator', ['ignore_request' => true]);
$count = \count($model->getItems());
$io->info($count . ' artikelen gevonden.');
Zo werken core commando's als cache:clean precies: ze starten een component op en roepen het model aan, en rapporteren daarna het resultaat aan de terminal.
7.5 Services injecteren via de constructor
Naar globale status grijpen binnen een commando werkt, maar de nettere manier is om de DI-container je de services te laten aanreiken die je nodig hebt. Geef je commando een constructor en vraag erom op type:
use Joomla\Database\DatabaseInterface;
final class CountUsersCommand extends AbstractCommand
{
protected static $defaultName = 'users:count';
public function __construct(private DatabaseInterface $db)
{
parent::__construct(); // roep altijd de constructor van de ouder aan
}
protected function doExecute(InputInterface $input, OutputInterface $output): int
{
$query = $this->db->getQuery(true)
->select('COUNT(*)')
->from($this->db->quoteName('#__users'));
$total = (int) $this->db->setQuery($query)->loadResult();
(new SymfonyStyle($input, $output))->info($total . ' gebruikers.');
return Command::SUCCESS;
}
}
Core commando's doen dit ook: user:add krijgt de database via de constructor in plaats van hem zelf op te halen. Je console-plugin maakt het commando dan met zijn afhankelijkheid aan bij het registreren - $this->getApplication()->addCommand(new CountUsersCommand($db)). Het resultaat is code die los gekoppeld en makkelijk te testen is, omdat je in een unittest een neppe database kunt meegeven.
8. Een console-plugin inpakken
Een console-plugin gebruikt dezelfde moderne, genamespacede indeling als elke Joomla 6-plugin. Slechts twee dingen markeren hem als console-plugin: de groep in het manifest en het event waarop hij zich abonneert.
8.1 De mappenindeling
plugins/console/mycli/
├─ mycli.xml ─ manifest (group="console")
├─ services/
│ └─ provider.php ─ DI-registratie (ingang)
├─ src/
│ ├─ Extension/
│ │ └─ MyCli.php ─ de pluginklasse (abonneert op BEFORE_EXECUTE)
│ └─ Command/
│ └─ HelloCommand.php ─ je commandoklasse
└─ language/ ─ vertaal-ini-bestanden
8.2 Het manifest
De ene regel die dit een console-plugin maakt is group="console":
<extension type="plugin" group="console" method="upgrade">
<name>plg_console_mycli</name>
<version>1.0.0</version>
<namespace path="src">Joomla\Plugin\Console\MyCli</namespace>
<files>
<folder plugin="mycli">services</folder>
<folder>src</folder>
</files>
</extension>
8.3 De service provider
De ingang is services/provider.php, hetzelfde patroon dat elke moderne plugin gebruikt. Het registreert de pluginklasse bij de DI-container:
return new class () implements ServiceProviderInterface {
public function register(Container $container): void
{
$container->set(PluginInterface::class, function (Container $container) {
$plugin = new MyCli(
$container->get(DispatcherInterface::class),
(array) PluginHelper::getPlugin('console', 'mycli')
);
$plugin->setApplication(Factory::getApplication());
return $plugin;
});
}
};
Zip de map, installeer hem via Systeem → Installeren → Extensies, schakel hem in in de pluginlijst, en je commando verschijnt in php cli/joomla.php list. Er wordt geen core bestand aangeraakt.
8.4 Waar de plugin wordt vastgelegd
Een console-plugin is een gewone plugin, dus hij woont als een rij in de tabel #__extensions, precies zoals een content- of system-plugin. De CLI leest die tabel bij het opstarten om te bepalen welke plugins geladen worden:
| Kolom | Voor een console-plugin |
|---|---|
type |
plugin |
folder |
console (de groep) |
element |
mycli (de pluginnaam) |
enabled |
1 = geladen, 0 = genegeerd |
Als een commando ontbreekt in de lijst, is dit de eerste plek om te controleren. Je ziet elke console-plugin en zijn status met een query:
SELECT element, enabled
FROM #__extensions
WHERE type = 'plugin' AND folder = 'console';
Een rij met enabled = 0 laadt nooit, dus zijn commando's bereiken de CLI nooit. Dat is de reden op databaseniveau achter het meest voorkomende probleem "mijn commando verschijnt niet".
9. Invoer, uitvoer en interactie
Een goed commando is prettig om met de hand te gebruiken en betrouwbaar binnen een script. De Joomla CLI geeft je de gereedschappen voor beide.
9.1 SymfonyStyle: nette uitvoer
De helper SymfonyStyle verpakt de ruwe uitvoer in nette, consistente opmaak. Core commando's gebruiken hem overal:
$io = new SymfonyStyle($input, $output);
$io->title('Systeemcache legen'); // een kop
$io->success('Cache geleegd'); // groen succesblok
$io->error('Cache niet geleegd'); // rood foutblok
$io->warning('Niets te doen'); // gele waarschuwing
$io->table(['Id', 'Naam'], $rows); // een opgemaakte tabel
9.2 De gebruiker vragen stellen
Wanneer een mens het draait, kan een commando om ontbrekende details vragen. Het commando user:add doet precies dit als je niet elke optie meegeeft:
$username = $io->ask('Gebruikersnaam');
$password = $io->askHidden('Wachtwoord'); // invoer wordt niet op het scherm getoond
$confirm = $io->confirm('Deze gebruiker aanmaken?', true);
Dit is vriendelijk voor mensen, maar denk aan automatisering. In een cronjob is er niemand om te antwoorden, dus geef ofwel elke waarde als optie mee, of voeg --no-interaction toe en zorg dat je commando met zijn standaardwaarden kan draaien.
9.3 Niveaus van uitgebreidheid
Laat de gebruiker kiezen hoeveel detail hij wil door de uitgebreidheid te controleren, in plaats van altijd alles af te drukken:
if ($output->isVerbose()) { // getoond met -v
$io->writeln('Extra detail voor de nieuwsgierige.');
}
Normale uitvoer blijft netjes, en -v, -vv of -vvv onthullen stapsgewijs meer voor het debuggen.
9.4 Vastleggen wat een commando doet
Uitvoer op het scherm verdwijnt op het moment dat een cronjob eindigt. Voor alles wat onbeheerd draait, leg je een blijvend verslag vast met het logging-framework van Joomla, in plaats van of naast de schermuitvoer:
use Joomla\CMS\Log\Log;
Log::add('Nachtelijke import gestart', Log::INFO, 'cli');
// ... doe het werk ...
Log::add('Nachtelijke import klaar: ' . $count . ' items', Log::INFO, 'cli');
Het derde argument is een categorie. Door je commando een eigen categorie te geven (hier cli) kun je die regels naar hun eigen logbestand sturen en ze later teruglezen onder Systeem → Onderhoud → Logs beheren, los van de rest van de site. Standaard staan de bestanden in het ingestelde logpad, meestal administrator/logs/.
Log de start, het einde en elke fout. Als een geplande taak om drie uur 's nachts mislukt, is het log de enige getuige die je hebt.
9.5 Een commando debuggen dat niet wil draaien
Als een commando zich misdraagt of weigert te verschijnen, werk dan deze korte checklist op volgorde af:
- Is de plugin ingeschakeld? Controleer de pluginlijst, of draai de
#__extensions-query uit sectie 8.4. - Verschijnt hij uberhaupt? Draai
php cli/joomla.php list. Als hij ontbreekt, laadt de plugin niet of roept hijaddCommand()niet aan. - Klopt de namespace? Het manifest
<namespace>en de mappen ondersrc/moeten exact overeenkomen, anders faalt het autoloaden stilletjes. - Draai het uitgebreid. Voeg
-vvvtoe om de volledige stacktrace te zien in plaats van een korte melding:php cli/joomla.php mycli:hello -vvv. - Lees de help.
php cli/joomla.php help mycli:hellobevestigt de naam, argumenten en opties die Joomla daadwerkelijk heeft geregistreerd.
De meeste meldingen van "er gebeurt niets" komen neer op een van deze vijf: uitgeschakelde plugin, ontbrekende addCommand(), of een typefout in de namespace die het autoloaden breekt.
10. De CLI en geplande taken (Cron)
De meest voorkomende reden waarom site-eigenaren de CLI tegenkomen is automatisering. De functie Geplande taken van Joomla is ontworpen om vanaf de command line te worden getriggerd.
10.1 Een commando, elke taak
Het commando scheduler:run draait elke geplande taak die aan de beurt is. Een enkele cron-regel op je server is genoeg om ze allemaal aan te drijven:
# Draai elke 15 minuten de geplande taken van Joomla die aan de beurt zijn
*/15 * * * * /usr/bin/php /pad/naar/site/cli/joomla.php scheduler:run --no-interaction
Elke "taak" is zelf een plugin (in de groep task), dus het ontwerp is consistent: het scheduler-component toont de taken, en de CLI levert de betrouwbare, browserloze trigger om ze te draaien.
10.2 Waarom de CLI beter is dan de web-trigger
Joomla kan geplande taken ook triggeren tijdens gewone paginabezoeken ("lazy" scheduling), maar de CLI-trigger is betrouwbaarder:
| Aandachtspunt | Web-trigger (lazy) | CLI-cron-trigger |
|---|---|---|
| Vereist een bezoeker | Ja - geen verkeer, geen run | Nee - de serverklok vuurt het af |
| Timing | Bij benadering, hangt af van verkeer | Exact, volgens schema |
| Tijdslimiet | Begrensd door de timeout van het webverzoek | Langlopende klussen zijn prima |
| Vertraagt de pagina van een bezoeker | Mogelijk | Nooit |
Voor elke serieuze site is een echte cronjob die scheduler:run aanroept de aanbevolen opzet.
10.3 De tabellen achter de scheduler
Als scheduler:run werkt, leest en schrijft het twee databasetabellen. Ze kennen helpt als je wilt zien waarom een taak niet is afgevuurd:
| Tabel | Wat het bevat |
|---|---|
#__scheduler_tasks |
De taakdefinities: type, parameters, status, volgende runtijd en de laatste exit-code |
#__scheduler_logs |
De uitvoeringsgeschiedenis: wanneer elke taak draaide, hoe lang het duurde en of het slaagde |
Een snelle blik op de taaktabel vertelt je wat er gepland staat en wanneer elk item weer aan de beurt is:
SELECT title, state, next_execution, last_exit_code
FROM #__scheduler_tasks
ORDER BY next_execution;
Als een taak nooit lijkt te draaien, controleer dan of de state ingeschakeld is (1) en of next_execution in het verleden ligt. Het commando draait alleen taken die zowel ingeschakeld als aan de beurt zijn.
11. CLI versus web versus Web Services
Joomla is op drie manieren bereikbaar. Ze delen dezelfde code en data, maar passen bij verschillende klussen.
| Aspect | CLI | Web (browser) | Web Services API |
|---|---|---|---|
| Ingang | cli/joomla.php |
index.php |
api/index.php |
| Aanroeper | Jij of een cronjob | Een bezoeker in een browser | Een externe app of script |
| Uitvoer | Platte tekst | Een volledige HTML-pagina | JSON |
| Authenticatie | Servertoegang (de shell-gebruiker) | Inlogsessie + cookies | API-token in een header |
| Beste voor | Onderhoud, automatisering, bulkklussen | Mensen die browsen en bewerken | Integraties, mobiele apps |
Een REST-aanroep naar de Web Services API draagt zijn token in een header, zo:
curl -H "X-Joomla-Token: <token>" \
https://example.test/api/index.php/v1/content/articles
Vuistregel: gebruik de CLI voor klussen die je op de server draait, het web voor mensen, en de Web Services API voor andere programma's die met je site praten.
Naar boven12. Beveiliging en serverinrichting
De CLI is juist krachtig omdat hij met volledige rechten draait en het inlogscherm overslaat. Die kracht is alleen veilig als de command line zelf beschermd is.
12.1 Draai als de juiste gebruiker
Draai commando's als dezelfde besturingssysteemgebruiker die de webbestanden bezit (vaak iets als www-data of je hostingaccount), niet als root. Als root draaien kan bestanden maken die de webserver niet kan beheren, wat later "permission denied"-fouten veroorzaakt.
12.2 Laat de PHP-versie overeenkomen
De PHP die je commando draait kan verschillen van de PHP die je webserver gebruikt. Joomla 6 vereist PHP 8.3 of nieuwer, en cli/joomla.php controleert dit bij de start. Als een commando zich vreemd gedraagt, bevestig de versie dan met php -v en gebruik dezelfde hoofdversie als de website.
12.3 Houd de CLI weg van het publieke web
De map cli/ is bedoeld voor de shell, niet voor browsers. Er is geen reden waarom een bezoeker hem ooit over HTTP zou moeten laden. De standaard Joomla-hostingindeling houdt deze scripts uit de gevarenzone, en het kleine bestand cli/index.html voorkomt het tonen van de mapinhoud. Stel een commando-runner nooit beschikbaar als publieke URL.
12.4 Ga zorgvuldig om met invoer
Valideer ook op de command line wat je binnenkrijgt. Gebruik de getypte getters op argumenten en opties, controleer de rechten van de gebruiker als een commando namens hem handelt, en bouw nooit een databasequery door ruwe invoer in een string te plakken.
Naar boven13. CLI en SEO: houd het onzichtbaar voor zoekmachines
De CLI heeft niets te zoeken in zoekresultaten, en dat goed doen draait vooral om niet de verkeerde dingen doen.
- CLI-commando's produceren geen webpagina's, geen URL's en geen metadata. Er is niets voor een zoekmachine om te indexeren, en dat is precies goed.
- Maak van een commando geen publiek web-endpoint alleen om het vanuit een browser te triggeren. Dat zou krachtige acties blootstellen aan iedereen die de URL vindt.
- Houd de map
cli/buiten de publieke documentroot waar de indeling van je host dat toelaat, zodat de scripts nooit over HTTP bereikbaar zijn. - Gebruik de CLI om SEO indirect te verbeteren:
finder:indexhoudt Smart Search vers, en geplande taken viascheduler:runkunnen op tijd sitemaps opnieuw opbouwen of redirects opschonen.
Kortom, de CLI werkt achter de schermen. Hij helpt je publieke pagina's snel en actueel te blijven, terwijl hij zelf volledig onzichtbaar blijft voor crawlers.
Naar boven14. Veelgemaakte fouten en valkuilen
14.1 Draaien vanuit de verkeerde map
Symptoom: "Could not open input file: cli/joomla.php" of "Install Joomla to run cli commands".
Oplossing: draai het commando vanuit de Joomla-root (de map met configuration.php), of geef het volledige pad: php /volledig/pad/naar/cli/joomla.php list.
14.2 De verkeerde PHP-binary
Symptoom: "your PHP version is not supported", of extensies gedragen zich anders dan op de website.
Oplossing: de shell-php kan ouder zijn dan de PHP van de webserver. Controleer met php -v en roep de juiste binary aan, bijvoorbeeld /usr/bin/php8.3, in je cron-regel.
14.3 Een cronjob die blijft hangen
Symptoom: een gepland commando is nooit klaar of draait nooit.
Oplossing: een interactieve vraag wacht op een antwoord dat nooit komt. Voeg --no-interaction toe en geef elke vereiste waarde als optie mee.
14.4 Je nieuwe commando verschijnt niet
Symptoom: je hebt een commando geschreven, maar het ontbreekt in list.
Oplossing: controleer drie dingen - de plugin is ingeschakeld, hij abonneert op ApplicationEvents::BEFORE_EXECUTE, en die handler roept daadwerkelijk $this->getApplication()->addCommand(...) aan.
14.5 Problemen met bestandseigenaarschap
Symptoom: de website kan later geen bestanden schrijven die de CLI heeft gemaakt, of andersom.
Oplossing: draai CLI-commando's als de webgebruiker, niet als root, zodat het eigenaarschap consistent blijft.
14.6 De exit-code vergeten
Symptoom: een deployscript behandelt een mislukt commando als geslaagd.
Oplossing: geef altijd Command::SUCCESS of Command::FAILURE terug uit doExecute(), zodat de aanroeper weet wat er is gebeurd.
15. Best practices
Als je maar een paar dingen uit dit artikel onthoudt, onthoud dan deze:
- Begin met
php cli/joomla.php listenhelp- ze documenteren elke site voor je. - Draai commando's vanuit de Joomla-root, als de webgebruiker, met de PHP-versie die bij de website past.
- Gebruik voor automatisering volledige paden en voeg
--no-interactiontoe zodat niets op een mens wacht. - Trigger geplande taken met een echte cronjob die
scheduler:runaanroept, niet de web-trigger. - Bouw nieuwe commando's als een
console-plugin die ze toevoegt opBEFORE_EXECUTE- bewerk nooit de core. - Houd de handler dun, gebruik
SymfonyStylevoor uitvoer, en geef een duidelijke exit-code terug. - Houd de
cli/-scripts weg van het publieke web.
16. In het kort
WAT HET IS Draai Joomla vanuit een terminal, geen browser nodig
INGANG php cli/joomla.php <commando> [argumenten] [--opties]
ONTDEKKEN php cli/joomla.php list (alle commando's)
php cli/joomla.php help <commando> (een commando)
VEREIST PHP 8.3+ ; draai vanuit de Joomla-root, als de webgebruiker
VOORBEELD cache:clean | config:get | site:down / site:up
user:add | user:reset-password | extension:install --path=...
core:update | finder:index | scheduler:run
GLOBALE OPTS --help -h | --quiet -q | --verbose -v/-vv/-vvv
--no-interaction -n | --version -V
EXIT-CODES 0 = geslaagd | 1 = mislukt | 2 = ongeldige invoer
UITBREIDEN console-plugin, group="console"
abonneer ApplicationEvents::BEFORE_EXECUTE
dan $this->getApplication()->addCommand(new MyCommand())
COMMANDO extends AbstractCommand
$defaultName = 'groep:actie'
configure(): addArgument / addOption / setDescription
doExecute(InputInterface, OutputInterface): int
INJECTEER __construct(DatabaseInterface $db) + parent::__construct()
VASTGELEGD IN #__extensions (type=plugin, folder=console, enabled=1)
DB-TABELLEN #__scheduler_tasks + #__scheduler_logs (de scheduler)
LOGGEN Log::add('msg', Log::INFO, 'cli') (schrijft naar administrator/logs/)
DEBUGGEN in list? plugin ingeschakeld? namespace ok? draai met -vvv
CRON */15 * * * * php /pad/cli/joomla.php scheduler:run --no-interaction
Naar boven17. Samenvatting
De Joomla CLI is dezelfde site die je kent, maar dan via een andere ingang. Een ingang, cli/joomla.php, start het volledige CMS op en geeft de controle aan een commando, dat tekst afdrukt en een exit-code teruggeeft. Er is geen template, geen bezoeker en geen HTTP - alleen Joomla die snel een klus doet.
De belangrijkste punten kort samengevat:
- Draai
php cli/joomla.php listom elk commando op een site te zien, enhelpom er een te leren. - De Joomla core levert tientallen commando's voor cache, config, gebruikers, extensies, updates, zoeken en de scheduler.
- De applicatie is gebouwd op Symfony Console en registreert commando's meteen, lui via de DI-container, en tijdens runtime via console-plugins.
- Een console-plugin woont in de groep
consoleen voegt commando's toe op het eventBEFORE_EXECUTE, zodat je de CLI uitbreidt zonder de Joomla core aan te raken. - Een commando is een kleine klasse: een naam, een
configure()voor de argumenten en opties, en eendoExecute()die een exit-code teruggeeft.
Zodra je je hier op je gemak voelt, wordt veel Joomla-onderhoud een enkele betrouwbare regel: de cache legen, opnieuw indexeren, de nachtelijke taken draaien of een buitengesloten site herstellen.
Wil je hulp bij het automatiseren van je Joomla-onderhoud, het opzetten van een betrouwbare, cron-gestuurde scheduler, of het bouwen van eigen CLI-commando's en console-plugins voor je eigen workflows, dan is dat precies het soort geavanceerde Joomla-werk dat ik dagelijks doe.
Naar boven

Peter is Joomla specialist en Linux admin voor snelle, veilige en schaalbare websites.


