La console Symfony et les commandes personnalisées
Comment fonctionne
bin/consoleet comment créer sa propre commande
Notions théoriques
Qu'est-ce que bin/console ?
Depuis le début de ce cours, vous tapez régulièrement des commandes comme :
php bin/console make:controller
php bin/console make:entity
bin/console est le point d'entrée en ligne de commande de Symfony. C'est un simple fichier PHP qui démarre l'application, mais au lieu de répondre à une requête HTTP (comme le fait public/index.php), il exécute une commande demandée dans le terminal.
Chaque commande (make:controller, make:entity, cache:clear, debug:router...) est en réalité une classe PHP. Symfony fournit de nombreuses commandes prêtes à l'emploi, mais vous pouvez aussi créer les vôtres.
Une commande sert à automatiser une tâche technique : générer du code, nettoyer le cache, importer des données, envoyer un rapport par email, etc. C'est un outil pour le développeur ou pour l'administrateur du site, pas pour le visiteur final.
Lister et explorer les commandes disponibles
Pour voir la liste complète des commandes disponibles dans un projet Symfony :
php bin/console list
Les commandes sont regroupées par espace de noms (make:, cache:, doctrine:, debug:...). Ce préfixe indique la famille à laquelle appartient la commande.
Pour obtenir de l'aide détaillée sur une commande précise (ses arguments, ses options) :
php bin/console make:controller --help
--help fonctionne avec toutes les commandes, y compris celles que vous créerez vous-même. C'est le réflexe à avoir avant d'utiliser une commande inconnue.
Créer sa propre commande
Symfony fournit un générateur pour créer le squelette d'une nouvelle commande :
php bin/console make:command app:mission-du-jour
Cette commande génère un nouveau fichier dans src/Command/, par exemple src/Command/MissionDuJourCommand.php, prêt à être complété.
Anatomie d'une classe de commande
Une classe de commande Symfony a toujours la même structure :
- L'attribut
#[AsCommand(name: '...', description: '...')]déclare le nom de la commande (celui tapé dans le terminal) et sa description (affichée dansphp bin/console list). - La méthode
configure()définit les arguments et options attendus par la commande. - La méthode
execute()contient la logique métier de la commande : c'est le code qui s'exécute réellement. - La classe
SymfonyStyle(généralement injectée via$io = new SymfonyStyle($input, $output);) permet un affichage propre dans le terminal :$io->success(...),$io->error(...),$io->title(...),$io->table(...).
execute() doit retourner une constante entière : Command::SUCCESS, Command::FAILURE ou Command::INVALID. C'est ce code de retour que d'autres outils (scripts, tâches planifiées) utilisent pour savoir si la commande s'est bien déroulée.
Exemple de mise en application
Créons une commande app:count-players qui affiche le nombre total de joueurs enregistrés en base de données. Elle réutilise le PlayerRepository déjà utilisé par le GameController.
// src/Command/CountPlayersCommand.php
namespace App\Command;
use App\Repository\PlayerRepository;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'app:count-players',
description: 'Affiche le nombre total de joueurs enregistrés en base de données',
)]
class CountPlayersCommand extends Command
{
public function __construct(
private PlayerRepository $playerRepository
) {
parent::__construct();
}
protected function configure(): void
{
// Aucun argument ni option pour cette commande simple
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$total = count($this->playerRepository->findAll());
$io->success(sprintf('Il y a actuellement %d joueur(s) enregistré(s).', $total));
return Command::SUCCESS;
}
}
Grâce à l'injection de dépendances, Symfony fournit automatiquement une instance de PlayerRepository au constructeur de la commande, exactement comme il le fait pour un contrôleur.
Pour exécuter cette commande :
php bin/console app:count-players
Une commande personnalisée apparaît automatiquement dans php bin/console list, regroupée sous l'espace de noms app: si vous suivez cette convention de nommage.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Votre défi pour aujourd'hui consiste à créer une commande
app:count-charactersqui affiche le nombre total de personnages enregistrés en base de données, en réutilisant leCharacterRepositorydéjà présent dans le projet.
Étape 1 — Générer le squelette de la commande
Ouvrez un terminal à la racine du projet et générez la commande avec le générateur Symfony.
Utiliser le préfixe app: pour toutes les commandes personnalisées du projet permet de les distinguer immédiatement des commandes internes de Symfony (make:, doctrine:, cache:...) lorsqu'on parcourt la liste avec php bin/console list.
Étape 2 — Injecter le CharacterRepository
Pour accéder aux personnages en base de données, la commande a besoin du CharacterRepository, comme un contrôleur en aurait besoin.
Lorsqu'une commande a un constructeur personnalisé, il est impératif d'appeler parent::__construct(). Sans cet appel, la commande ne sera pas correctement enregistrée et Symfony lèvera une erreur au démarrage.
Étape 3 — Écrire la logique dans execute()
Complétez la méthode execute() pour compter les personnages et afficher le résultat avec SymfonyStyle.
Ne jamais oublier return Command::SUCCESS; (ou Command::FAILURE en cas d'erreur) à la fin de execute(). Ce code de retour est utilisé par les scripts d'automatisation ou les tâches planifiées pour savoir si la commande s'est bien terminée.