Lancer un script Symfony en ligne de commande

Il arrive souvent que l’on préfère lancer un script PHP en ligne de commande plutôt que l’appeler depuis un navigateur via un serveur. Pour ma part, cela m’arrive souvent lorsque je dois traiter de nombreuses données en base de données. Lorsqu’on travaille avec Symfony on est ravi d’utiliser les Entity pour des insertions/modifications de data en base de données, mais ces Entity ne sont pas utilisables avec un simple script PHP en ligne de commande.

Symfony c’est chouette

Symfony permet la création de commande, et ainsi profiter de la puissance du Framework avec PHP CLI. Je vais présenter ci-dessous une manière d’insérer en base de données de nombreuses valeurs d’un fichier CSV en base de données en utilisant les Entity.

Imaginons que l’on ait des fichiers CSV contenant le nom et le prénom d’utilisateurs (et d’autres valeurs mais gardons un exemple simple). Dans notre Symfony, ces utilisateurs sont des Users.

On commence donc par créer un fichier ImportuserCommand.php dans

                src/Command/ImportuserCommand.php              

On initialise le namespace, et on importe les éléments nécessaires.

                namespace App\Command;

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




use App\Entity\Users;

use App\Entity\Group;

use Doctrine\ORM\EntityManagerInterface;

class ImportuserCommand extends Command{              

Notre but, vous l’aurez compris, sera de lire le CSV et de l’importer proprement en base de données.

Créer un nom de commande

Ci-dessous on déclare un attribut dans notre objet, cet attribut est le nom de la commande que nous sommes en train de créer, ainsi (mais ça c’est moi qui aime bien faire comme ça), l’attribut destiné à être notre Entity Manager.

                protected static $defaultName = 'app:import-vocabulary';
protected $em;              
Le constructeur

On y ajoute notre constructeur, qui initialise l’Entity Manager

                      public function __construct(EntityManagerInterface $em){
          parent::__construct();
          $this->em = $em;
      }              
Configurer la commande

Nous devons créer une méthode « configure » afin de définir les paramètres de notre commande. Est-ce qu’elle prend des arguments ? Sa description, une aide à l’exécution.

Ici, je mets un argument « group », j’imagine que les utilisateurs appartiennent à plusieurs groupes distincts, que je précise lors de l’import. Je précise bien entendu le chemin absolu du fichier à importer, dans l’argument ‘path_file’.

                      protected function configure(){
        $this
            // la description est affichée quand on execute php bin/console list"
             ->addArgument('group', InputArgument::REQUIRED, 'The group of Users.')
             ->addArgument('path_file', InputArgument::REQUIRED, 'The  path of file.')
            ->setDescription('Import Users from CSV file.')
            ->setHelp('Import Users');
      }              

Enfin je  créé une méthode « execute », (nous notons que cette méthode prend en argument les interfaces Ouput, Input, nécessaires pour communiquer via le CLI). Ma méthode, simplissime va lire le fichier CSV, et insérer en base, en utilisant l’Entity Manager les utilisateurs. Cette méthode va appeler une méthode privée nommée insertUsersList(), qui se chargera du travail.

Cette méthode prend en argument, le chemin du fichier, entity manager (on aurait pu l’appeler via l’objet, $this->em ), et le groupe des utilisateurs.

 

                private function insertCardListToDataBase($directory, $em, $group){
    $csvText   = fopen($directory, "r");
    if ($csvText) {
        while (($line = fgets($csvText)) !== false) {
          $User = new Users();
          $arrayLine = explode(";", $line);
          if(array_key_exists(1, $arrayLine)){
            $name       = $arrayLine[0];
            $firstname  = $arrayLine[1];
            $User->setName($name);
            $User->setFirstname($group);
            $User->setGroup($UserListObject);
            $em->persist($User);
          }
        }
        $em->flush();
        fclose($csvText);
    }else {
      die('erreur de lecture du fichier CSV uploadé');
    }
}              

Et voilà, j’ai une commande Symfony pour l’import d’utilisateur via le CLI