L'agence
WanadevStudio
Grâce à Faker, générez des données aléatoires dans votre base de données
Lorsque l'on développe un site avec Symfony, il est souvent pratique d'utiliser les fixtures pour remplir sa BDD de valeurs bidons. Le problème c'est qu'il faut écrire chacune de ces fausses données à la mano, une par une. C'est là qu'utiliser le petit framework Faker peut nous être utile, en nous permettant de créer beaucoup de fausses données lisibles par un humain.
Faker : le générateur de fixtures
Faker est un framework php créé par l'excellent François Zaninotto permettant de générer facilement tout type de données. Il est utilisable comme une bibliothèque indépendante mais nous allons voir ici comment l'intégrer dans un projet Symfony3 pour remplir la BDD de son site.
@ Concrètement Faker génère facilement des données compréhensibles par un humain, et pas des valeurs aléatoires type "Lorem ispum" !
C'est-à-dire que le code suivant :
$faker = Faker\Factory::create('fr_FR');
$populator = new Faker\ORM\Doctrine\Populator($faker, $em);
$populator->addEntity(User::class, 10);
$insertedPKs = $populator->execute();
permet d'obtenir ces utilisateurs en base de données :
Ce qui est également intéressant c'est qu'en changeant le deuxième paramètre de la méthode addEntity (10 dans cet exemple) je peux facilement me retrouver avec des centaines voire des milliers d'utilisateurs initialisés dans mon site !
Initialisation pour générer de la donnée
Dans un premier temps il faut installer Faker en utilisant composer :
composer require fzaninotto/faker
Ensuite vous devez créer un fichier de fixtures, par exemple src/AppBundle/DataFixtures/ORM/LoadUsers.php
dont voilà un exemple :
<?php
// src/AppBundle/DataFixtures/ORM/LoadUsers.php
namespace AppBundle\DataFixtures\ORM;
use AppBundle\Entity\User;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Faker;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadUsers extends AbstractFixture implements ContainerAwareInterface, FixtureInterface, OrderedFixtureInterface
{
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $em)
{
// initialisation de l'objet Faker
// on peut préciser en paramètre la localisation,
// pour avoir des données qui semblent "françaises"
$faker = Faker\Factory::create('fr_FR');
$populator = new Faker\ORM\Doctrine\Populator($faker, $em);
$populator->addEntity(User::class, 10);
// le deuxième paramètre (10) correspond au nombre d'objets qui vont être créés
$insertedPKs = $populator->execute();
}
public function getOrder()
{
return 1;
}
}
que vous pouvez lancer en utilisant la commande
bin/console doctrine:fixtures:load
@ Pour plus d'info sur le Populator, qui permet de générer automatiquement les données d'une entité je vous renvoie vers la doc.
^ Par contre attention à ne pas utiliser cette manière de faire pour alimenter en données des entités possédant des relations avec d'autres entités, cette fonctionnalité n'est plus supportée.
Génération de données avec Faker et Symfony : exemple complexe
Dans le cas où l'on possède des entités avec des relations entre elles, il est préférable de générer les entités une par une dans des boucles. En faisant cela, on peut facilement assigner telle entité à une autre ou en rajouter une à la collection d'une autre.
Par exemple, si j'ai des Customers qui peuvent être liés à plusieurs Shops :
<?php
// src/AppBundle/DataFixtures/ORM/LoadData.php
namespace AppBundle\DataFixtures\ORM;
use AppBundle\Entity\Customer;
use AppBundle\Entity\Shop;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
// import de la classe Faker
use Faker;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadData extends AbstractFixture implements ContainerAwareInterface, FixtureInterface, OrderedFixtureInterface
{
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $em)
{
// initialisation de l'objet Faker
$faker = Faker\Factory::create('fr_FR');
// créations des shops
$shops = [];
for ($i=0; $i < 10; $i++) {
$shops[$i] = new Shop();
$shops[$i]->setName($faker->company)
->setSiret($faker->siret)
->setReference($faker->numberBetween(111111, 999999))
->setContactName($faker->name)
->setAddress($faker->address)
;
$em->persist($shops[$i]);
}
// créations des customers
$customers = [];
for ($k=0; $k < 50; $k++) {
$customers[$k] = new Customer();
$customers[$k]->setFirstName($faker->firstName)
->setLastName($faker->lastName)
->setEmail($faker->mail)
->setPhone($faker->phone)
->setAddress($faker->address)
;
// on récupère un nombre aléatoire de Shops dans un tableau
$randomShops = (array) array_rand($shops, rand(1, count($shops)));
// puis on les ajoute au Customer
foreach ($randomShops as $key => $value) {
$customers[$k]->addShop($shops[$key]);
}
$em->persist($customers[$k]);
}
$em->flush();
}
public function getOrder()
{
return 1;
}
}
Fixtures et Faker : astuces
Choisir son type de donnée
Comme vous avez pu le voir dans l'exemple précédent, on peut choir le type de donnée qui nous intéresse en accédant à la propriété de l'objet $faker qui correspond.
@ Par exemple si on veut générer des emails on pourra faire $faker->email
, ou si on veut le code hexadécimal d'une couleur $faker->hexcolor
Ces propriétés sont appelées Formatters et sont très nombreuses, et pour ne rien gâcher elles sont extensibles par vous (voir ci-dessous).
Avoir des données identiques à chaque génération
Vous pouvez avoir besoin de garder les mêmes données à chaque initialisation des fixtures. Il est possible de générer le même jeu de données à chaque fois en utilisant la méthode seed() :
$faker = Faker\Factory::create('fr_FR');
$faker->seed(1337);
// votre code
Le nombre fourni en paramètre peut être ce que vous voulez, mais si vous laissez le même d'un lancement des fixtures à l'autre les données seront identiques. Par contre cela ne fonctionne que pour la même machine. D'un ordinateur à l'autre le jeu de données sera différent.
Rajouter ses propres méthodes Faker
Si vous avez besoin de générer un type de donnée qui n'est pas pris en compte par Faker, il peut être intéressant de créer son Faker Provider.
Pour cela il faut créer une class qui étend \Faker\Provider\Base
dans laquelle vous pouvez ajouter vos méthodes personnelles.
Pour plus d'informations je vous invite à RTFM comme on dit !
GitHub - fzaninotto/Faker: Faker is a PHP library that generates fake data for you.
Théo Catherinet
Commentaires
Il n'y a actuellement aucun commentaire. Soyez le premier !