Utiliser la console directement depuis le navigateur

La console est un outil bien pratique de Symfony2. Mais parfois, devoir ouvrir le terminal de Linux ou l'invite de commandes de Windows n'est pas très agréable. Et je ne parle pas des hébergements mutualisés, qui n'offrent pas d'accès SSH pour utiliser la console !

Comment continuer d'utiliser la console dans ces conditions ? Ce chapitre est là pour vous expliquer cela !

Théorie : le composant Console de Symfony2

Les commandes sont en PHP

Nous l'avons déjà évoqué au cours de ce tutoriel, les commandes Symfony2 sont bien de simples codes PHP ! Effectivement on les exécute depuis une console, mais cela ne les empêche en rien d'être en PHP.

Et comme elles sont en PHP… elle peuvent tout à fait être exécutées depuis un autre script PHP. C'est en fait ce qui est déjà fait par le script PHP de la console, celui que l'on exécute à chaque fois : le fichier app/console. Voici son contenu :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env php
<?php

require_once __DIR__.'/bootstrap.php.cache';
require_once __DIR__.'/AppKernel.php';

use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;

$input = new ArgvInput();
$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
$debug = !$input->hasParameterOption(array('--no-debug', ''));

$kernel = new AppKernel($env, $debug);
$application = new Application($kernel);
$application->run();

Comme vous pouvez le voir, ce fichier ressemble beaucoup au contrôleur frontal, app.php. Il charge également le Kernel. La seule chose qu'il fait de différent, c'est d'utiliser le composant Console de Symfony2, en instanciant la classe Application (ligne 15). C'est cet objet qui va ensuite exécuter les différentes commandes définies en PHP dans les bundles.

Exemple d'une commande

Chaque commande est définie dans une classe PHP distincte, que l'on place dans le répertoire Command des bundles. Ces classes comprennent entres autres deux méthodes :

  • configure() qui définit le nom, les arguments et la description de la commande ;
  • execute() qui exécute la commande à proprement parler.

Prenons l'exemple de la commande list, qui liste toutes les commandes disponibles dans l'application. Elle est définie dans le fichier vendor/symfony/src/Component/Console/Command/ListCommand.php, dont voici le contenu :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command;

/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
  /**
   * {@inheritdoc}
   */
  protected function configure()
  {
    $this
      ->setDefinition(array(
        new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
        new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
      ))
      ->setName('list')
      ->setDescription('Lists commands')
      ->setHelp(<<<EOF
The <info>list</info> command lists all commands:

  <info>php app/console list</info>

You can also display the commands for a specific namespace:

  <info>php app/console list test</info>

You can also output the information as XML by using the <comment>--xml</comment> option:

  <info>php app/console list --xml</info>
EOF
      );
  }

  /**
   * {@inheritdoc}
   */
  protected function execute(InputInterface $input, OutputInterface $output)
  {
    if ($input->getOption('xml')) {
      $output->writeln($this->getApplication()->asXml($input->getArgument('namespace')), OutputInterface::OUTPUT_RAW);
    } else {
      $output->writeln($this->getApplication()->asText($input->getArgument('namespace')));
    }
  }
}

Vous distinguez bien ici les deux méthodes qui composent la commande list. En vous basant sur cet exemple, vous êtes d'ailleurs capables d'écrire votre propre commande : ce n'est vraiment pas compliqué !

Mais revenons au but de ce chapitre, qui est de pouvoir utiliser ces commandes depuis le navigateur.

Pratique : utiliser un ConsoleBundle

ConsoleBundle ?

Vous le savez sûrement, la communauté de Symfony2 est très active, et un nombre impressionnant de bundles a vu le jour depuis la sortie de Symfony2. Vous pouvez les retrouver presque tous sur le site http://knpbundles.com/ qui les recense.

Il doit sûrement y avoir plusieurs bundles qui fournissent une console dans le navigateur, mais je vous propose d'en installer un en particulier : CoreSphereConsoleBundle. C'est un bundle simple qui remplit parfaitement sa tâche, et dont l'interface est très pratique, comme le montre la figure suivante.

Interface de CoreSphereConsoleBundle

Installer CoreSphereConsoleBundle

L'installation d'un tel bundle est vraiment simple, attaquons-la dès maintenant.

Télécharger CoreSphereConsoleBundle

Pour installer ce bundle, je vous propose de télécharger une version que j'ai modifiée. J'ai entre autres résolu quelques petits bugs et traduit les messages en français. L'adresse du bundle est donc la suivante : https://github.com/winzou/ConsoleBundle.

Pour l'installer avec Composer, rajoutez la ligne suivante dans vos dépendances :

1
2
3
4
5
6
// composer.json

"require": {
        // …
        "winzou/console-bundle": "dev-master"
    }

Puis mettez à jour vos dépendances grâce à la commande suivante :

1
php ../composer.phar update

Si jamais vous n'avez pas Composer, ce que je déconseille, vous pouvez le télécharger à la main depuis GitHub. Cliquez sur Download et téléchargez l'archive (le format zip est recommandé pour les utilisateurs de Windows). Décompressez ensuite l'archive dans le répertoire vendor/bundles/CoreSphere/ConsoleBundle. Ensuite, enregistrez le namespace dans votre autoload comme ceci :

1
2
3
4
5
6
7
8
<?php
// app/autoload.php

// …

$loader->add('CoreSphere', __DIR__.'/../vendor/bundles');

return $loader;

Enregistrement du bundle dans le Kernel

Puis il faut enregistrer le bundle CoreSphereConsoleBundle dans app/AppKernel.php (ligne 33) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
  public function registerBundles()
  {
    $bundles = array(
      new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
      new Symfony\Bundle\SecurityBundle\SecurityBundle(),
      new Symfony\Bundle\TwigBundle\TwigBundle(),
      new Symfony\Bundle\MonologBundle\MonologBundle(),
      new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
      new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
      new Symfony\Bundle\AsseticBundle\AsseticBundle(),
      new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
      new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),

      // D'autres bundles que vous auriez déjà pu ajouter
    );

    if (in_array($this->getEnvironment(), array('dev', 'test'))) {
      $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
      $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
      $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
      $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();

      // D'autres bundles que vous auriez déjà pu ajouter

      // On enregistre ce bundle uniquement pour l'environnement de développement évidemment
      $bundles[] = new CoreSphere\ConsoleBundle\CoreSphereConsoleBundle();
    }

    return $bundles;
  }

// …

}

Enregistrement des routes

Pour paramétrer un bundle, on fait comme toujours : on lit sa documentation. La documentation se trouve soit dans le readme, soit dans le répertoire Resources/doc, cela dépend des bundles. Dans notre cas, elle se trouve dans le readme.

Pour les routes, il faut donc enregistrer le fichier dans notre routing_dev.yml. On ne les met pas dans routing.yml, car la console ne doit être accessible qu'en mode dev, on a enregistré le bundle que pour ce mode. Ajoutez donc à la fin de app/config/routing_dev.yml :

1
2
console:
    resource: "@CoreSphereConsoleBundle/Resources/config/routing.yml"

Publier les assets

L'installation touche à sa fin, il ne reste plus qu'à rendre disponibles les fichiers JS et CSS du bundle, ce qui se fait comme vous le savez grâce à la commande suivante :

1
php app/console assets:install --symlink web

C'est fini ! Il ne reste plus qu'à utiliser notre nouvelle console.

Bien sûr, lorsque je vous dit d'exécuter cette commande, c'est en local ! Exécutez-la sur votre PC, puis envoyez tous les fichiers par FTP sur votre serveur, vous aurez ainsi accès à la console sur votre serveur. ;)

Utilisation de la console dans son navigateur

Par défaut, le bundle définit la route /console pour afficher la console. Allez donc à l'adresse http://localhost/Symfony/web/app_dev.php/console et profitez !

Bien entendu, pour exécuter des commandes Symfony2 depuis cette interface, il ne faut pas faire php app/console la_commande, mais uniquement la_commande ! Le script PHP du bundle n'utilise pas le script app/console, il utilise directement le composant Console.

Pour les utilisateurs de Windows, vous pouvez remarquer que le résultat des commandes est en couleurs. Eh oui, Symfony2 est plus fort que l'invite de commandes de Windows, il gère les couleurs !

En plus de l'adresse /console dédiée, j'ai rajouté un petit bouton console, regardez en bas à droite dans la barre d'outils de Symfony. Cliquez dessus, et une petite console s'ouvre par-dessus votre page. Pratique pour exécuter une commande rapidement ! Pour enlever la console, cliquez de nouveau sur le bouton.

Prêts pour l'hébergement mutualisé

Vous êtes prêts pour utiliser la console de votre application sur les hébergements mutualisés, qui n'offrent généralement pas d'accès SSH !


En résumé

  • Les commandes Symfony2 sont en PHP pur, il est ainsi tout à fait possible de « simuler » une console via le navigateur.
  • Vous disposez maintenant d'une console accessible depuis votre navigateur : cela va vous simplifier la vie, croyez-moi ! ;)
  • N'hésitez pas à faire vos retours sur le bundle directement via les issues sur GitHub : https://github.com/winzou/ConsoleBundle/issues.