Symfony ExpressionLanguage : Comment utiliser ce composant ?
Le composant Symfony ExpressionLanguage : qu'est-ce que c'est ? Quand et comment l'utiliser ? Comment créer des expressions lors de cas plus complexes ?
Sommaire
La console est un composant essentiel pour beaucoup d’applications web. Nous avons pas mal de nouveautés dans cette nouvelle version de Symfony. Je vous présente dans cet article mes préférées et vous mettrai les liens de celles que je ne détaille pas ici à la fin (on est comme ça chez Eleven).
On l’attendait, ils l’ont fait : nous pouvons désormais créer une liste d’alias à nos commandes. Pour cela, rien de plus simple : ajoutez “setAliases” avec en paramètre un tableau de string comportant tous les alias.
Voici un exemple :
ElevenLabsAliasCommand.php :
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ElevenLabsAliasCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('eleven-labs:alias-command')
->setDescription('Test alias command')
->setAliases(['space', 'moon'])
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Alias command done');
}
}
Voici une petite vidéo pour voir ce que ça rend :
Tester des commandes, on sait faire. Mais lorsque dans les commandes nous devons répondre à des questions par des étapes intermédiaires, ça devient plus difficile. Terminé les complications, il suffit de rajouter dans vos tests la méthode "setInputs", avec en paramètre un tableau contenant les réponses à vos étapes. Voici rien que pour vous un exemple très simple :
ElevenLabsTestCommand.php :
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Input\Input;
class ElevenLabsTestCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('eleven-labs:test-command')
->setDescription('...')
->setAliases(['test']);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$firstname = $io->ask('What is your firstname ?');
$lastname = $io->ask('Your last name ?');
$text = $firstname.' '.$lastname.', welcome on board !';
$output->writeln($text);
}
}
ElevenLabsTestCommandTest.php :
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class ElevenLabsTestCommandTest extends KernelTestCase
{
public function testCommand()
{
$kernel = $this->createKernel();
$kernel->boot();
$application = new Application($kernel);
$application->add(new ElevenLabsTestCommand());
$command = $application->find('eleven-labs:test-command');
$commandTester = new CommandTester($command);
// Ajouter tous les inputs dans l'ordre, ici nous devons mettre un nom et un prénom
$commandTester->setInputs(['Niel', 'Armstrong']);
$commandTester->execute([
'command' => $command->getName(),
]);
$output = $commandTester->getDisplay();
// Nous verifions ici que nous avons bien les mêmes input
$this->assertContains('Niel Armstrong, welcome on board !', $output);
}
}
Les “Single Command Application” sont possibles sur Symfony, comme vous pouvez le voir dans la documentation. Cette feature améliorée dans la version 3.2 nous permet d’ajouter un booléen à la méthode setDefaultCommand(). C’est grâce à ce booléen que nous pouvons désormais basculer l’application en une SCA.
Mieux vaut un exemple qu’un long discours, commençons par créer deux simples commandes :
Command/EspaceCommand.php :
<?php
namespace Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
class EspaceCommand extends Command
{
protected function configure()
{
$this
->setName('espace')
->setDescription('Aller dans l\'espace')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Je suis dans l\'espace');
}
}
Command/TerreCommand.php :
<?php
namespace Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
class TerreCommand extends Command
{
protected function configure()
{
$this
->setName('terre')
->setDescription('Redescendre sur terre')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Je retourne sur terre');
}
}
SingleCommand.php :
#!/usr/bin/env php <?php require __DIR__.'/vendor/autoload.php'; use Command\EspaceCommand; use Command\TerreCommand; use Symfony\Component\Console\Application; // On initialise les deux commandes $espaceCommand = new EspaceCommand(); $terreCommand = new TerreCommand(); // On créer une nouvelle application, et on lui ajoute nos 2 commandes $application = new Application(); $application->add($espaceCommand); $application->add($terreCommand); // On met la commande EspaceCommand en par défaut et on ajout un booléen à TRUE $application->setDefaultCommand($espaceCommand->getName(), true); $application->run();
Dans le fichier SingleCommand, nous avons rajouté un booléen à true, pour indiquer que nous souhaitons avoir une SCA.
Depuis la version 2.6, il est possible de bloquer une commande si la commande est déjà en train de tourner. Voici un petit exemple de comment nous devions faire :
class LockableCommand extends Command
{
protected function configure()
{
// ...
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$lock = new LockHandler('update:contents');
if (!$lock->lock()) {
$output->writeln('The command is already running in another process.');
return 0;
}
$lock->release();
}
}
Avec la version 3.2, vous pouvez ajouter le trait directement dans votre commande :
class LockableCommand extends Command
{
use LockableTrait;
protected function execute(InputInterface $input, OutputInterface $output)
{
if (!$this->lock()) {
$output->writeln('The command is already running in another process.');
return 0;
}
$this->release();
}
}
Une petite nouveauté qui vous permettra de cacher une commande très simplement. Une fois la commande cachée, vous pourrez toujours la lancer, mais elle n’apparaîtra plus dans la liste de vos commandes :
class HiddenCommand extends Command
{
protected function configure()
{
$this
->setName('hidden')
->hidden(true)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// your code here
}
}
Enfin, il est désormais possible de combiner plusieurs options de texte sur le même input, voici un exemple :
$output->writeln('<fg=green;options=italic,underscore>Texte vert italic et souligné</>');
Voilà, je vous ai montré les nouveautés que je préfère, mais ce ne sont pas les seules, pour voir toute la liste des nouveautés pour le composant console, je vous conseille de suivre ce lien : http://symfony.com/blog/symfony-3-2-0-released
Auteur(s)
Jérémy GRÉAUX
Développeur PHP.
Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !
Notre équipe d'experts répond à toutes vos questions.
Nous contacterDécouvrez nos autres contenus dans le même thème
Le composant Symfony ExpressionLanguage : qu'est-ce que c'est ? Quand et comment l'utiliser ? Comment créer des expressions lors de cas plus complexes ?
Découvrez comment réaliser du typage générique en PHP : introduction et définition du concept, conseils et explications pas-à-pas de cas pratique.
Découvrez un cas d'usage d'intégration d'un CRM avec une application e-commerce, en asynchrone, avec Hubspot et RabbitMQ