Buy

Delightful Dummy Data with Alice

Now things are about to get fun. A few minutes ago, we installed a library called nelmio/alice - search for that and find their GitHub page.

In a nutshell, this library lets us add fixtures data via YAML files. It has an expressive syntax and it ships with a bunch of built-in functions for generating random data. Actually, it uses yet another library behind the scenes called Faker to do that. It's the PHP circle of life!

Creating the Fixture YAML File

Find the ORM directory and create a new file called - how about fixtures.yml. That filename lacks excitement, but at least it's clear.

Start with the class name you want to create - AppBundle\Entity\Genus. Next, each genus needs an internal, unique name - it could be anything. But wait! Finish the name with 1..10:

7 lines src/AppBundle/DataFixtures/ORM/fixtures.yml
AppBundle\Entity\Genus:
genus_{1..10}:
... lines 3 - 7

With this syntax, Alice will loop over and create 10 Genus objects for free. Boom!

To finish things, set values on each of the Genus properties: name: <name()>. You could just put any value here, but when using <>, you're calling a built-in Faker function. Next, use subFamily: <text(20)> to generate 20 characters of random text, speciesCount: <numberBetween(100, 100000)> and funFact: <sentence()>:

7 lines src/AppBundle/DataFixtures/ORM/fixtures.yml
AppBundle\Entity\Genus:
genus_{1..10}:
name: <name()>
subFamily: <text(20)>
speciesCount: <numberBetween(100, 100000)>
funFact: <sentence()>

That's it team! To load this file, open up LoadFixtures and remove all of that boring garbage. Replace it with Fixtures - autocomplete that to get the use statement - then ::load(). Pass this __DIR__.'/fixtures.yml' and then the entity manager:

16 lines src/AppBundle/DataFixtures/ORM/LoadFixtures.php
... lines 1 - 7
use Nelmio\Alice\Fixtures;
class LoadFixtures implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$objects = Fixtures::load(__DIR__.'/fixtures.yml', $manager);
}
}

Now, run the exact command as before:

./bin/console doctrine:fixtures:load

I love when there are no errors. Refresh the list page. Voila: 10 completely random genuses. I love Alice.

All The Faker Functions

Well.... the genus name is actually the name of a person... which is pretty ridiculous. Let's fix that in a second.

But first, Nelmio's documentation has a ton of cool examples of things you can do with this library. But the biggest things you'll want to check out is the Faker library that this integrates. This shows you all of the built-in functions we were just using - like numberBetween, word, sentence and a ton more. There is some great stuff in here.

Now if we can just make the genus name a little more realistic.

Leave a comment!

  • 2017-09-26 weaverryan

    Yep, we're already working on a few video notes so that people will know to use the older version for now :). The 3.0 release was just about a week or two ago... so the problem just started showing up!

  • 2017-09-26 Diego Aguiar

    Hey Danilo Silva

    Yeah, you are right!
    Alice has changed a lot in its newer version and it contains many BC breaks. We will discuss about it, so we can deliver a nice solution :)

    Cheers!

  • 2017-09-26 Danilo Silva

    I got an not found exception when running doctrine:fixture:load. The problem was due to an incompatible Nelmio\Alice version. From the previous video, I needed to install Alice specifying the version: 2.1.4 with

     composer require --dev nelmio/alice:2.1.4

    and them worked. Maybe we need a video update?

  • 2017-09-21 Victor Bocharsky

    Hey Syed,

    Excellent! I'm glad you got it working and thanks for sharing it with others.

    Cheers!

  • 2017-09-20 Syed

    Hi Victor,

    Thanks for the reply. Moving the flush() out of the foreach works great! I also had no idea (until reading the Symfony docs) https://symfony.com/doc/mas... that we had access to the container in our Fixtures class.

    With that I was able to load the nelmio_alice.file_loader service and load the yml file that way. So my load function now becomes


    $fileLoader = $this->container->get('nelmio_alice.file_loader');
    $objectSet = $fileLoader->loadFile(__DIR__.'/fixtures.yml')->getObjects();
    foreach($objectSet as $object) {
    $manager->persist($object);
    }
    $manager->flush();
  • 2017-09-20 Victor Bocharsky

    Hey Syed,

    I think you can move flush() out of the foreach statement, so Doctrine will just persist() all the objects first and then flush() them at once.

    Yes, you can register NelmioAliceBundle in your AppKernel and then configure it in app/config/config_dev.yml, check their docs for more information: https://github.com/nelmio/a... . Service "nelmio_alice.file_loader" has only one public method loadFile() where you need to pass path to the file you want to load. Then it will parse the file and load data by itself.

    Cheers!

  • 2017-09-17 Syed

    Hi,

    Looks like Alice has been updated to 3.0 and the Fixtures class no longer exists. So instead of that I used the NativeLoader class.

    use Nelmio\Alice\Loader\NativeLoader;

    And then in my load() function:


    $loader = new NativeLoader();
    $objectSet = $loader->loadFile(__DIR__.'/fixtures.yml')->getObjects();
    foreach($objectSet as $object) {
    $manager->persist($object);
    $manager->flush();
    }

    Xdebug tells me that the loadFile function returns an array with one of the values being an array of all our objects. The getObjects() function gives us a nice array of all our objects. I wonder if there's a way to persist more than one object at a time but for now the for loop seems to work OK with our small data collection.

    I also noticed that Alice 3.0 now comes with a Symfony Bundle and a service called nelmio_alice.file_loader but I couldn't figure out how to use that.

  • 2017-06-09 Carmen Fabo

    It works ! hallelujah ! ♬ ♬ ♬ hallelujah ! etc.

  • 2017-06-09 Carmen Fabo

    Thank you very much ! that helps me to understand how it works. I get another error, I look for a solution.
    Cheers !

  • 2017-06-07 weaverryan

    Hi Carmen Fabo!

    I think I know the problem :). When you reference @group_*, this references the *keys* you're using in your file - e.g. grab, rotation, etc. You should update the keys under your Groupe entity to all start with the same prefix. For example:


    AppBundle\Entity\Groupe:
    groupe_grab:
    nom: Grab
    groupe_rotation:
    nom: Rotation
    # ...

    I hope that helps! Cheers!

  • 2017-06-04 Carmen Fabo

    Hi,
    I would like to load two types of data fixtures: fake data and "true" data.
    I have written this:


    AppBundle\Entity\Groupe:
    grab:
    nom: Grab
    rotation:
    nom: Rotation
    flip:
    nom: Flip
    slide:
    nom: Slide
    old_school:
    nom: Old school

    AppBundle\Entity\Snowtricks:
    -
    nom: "Spin 180"
    groupe: '@groupe_*'
    contenu: <text(500)>
    photo: "images/figure1.jpg"
    video_url: "https://www.youtube.com/embed/Dlj0nIUvypw?list=PLA19FB9E97B041212"
    is_commented: <boolean(75)>

    When I try to load the fixtures I get an error :
    Instance mask "groupe_*" did not match any existing instance, make sure the object is created after its references
    I think I don't understand the error message. Could you please explain it to me ?
    Thank you.

  • 2017-05-15 Scott

    cool thanks. I was pulling my hair wondering why I kept getting the same data then it clicked, I shouldn't do these things too late at night :p

  • 2017-05-15 Victor Bocharsky

    Hey Fenring,

    I personally don't use AliceBundle in my unit tests, could you look at this thread, maybe this will help to fix your problem: https://knpuniversity.com/s... . But I think a better practice is do not use AliceBundle in tests and instead boot Symfony kernel and set only that data you need before running each test - PHPUnit helps with it well.

    Cheers!

  • 2017-05-15 Victor Bocharsky

    Hey Scott,

    Thanks for sharing it with us! Here's a link to the docs with a bit more description about seeding the Faker's generator: https://github.com/fzaninot...

    Cheers!

  • 2017-05-14 Scott

    if you don't want to always get the same generated data, set the seed to null when loading the fixtures:


    Fixtures::load(
    __DIR__ . '/fixtures.yml',
    $manager,
    [
    'providers' => [$this],
    'seed' => null
    ]
    );
  • 2017-05-11 Diego Aguiar

    So you could run "composer install" after installing PHP 7 and everything ran fine ? or you got that error after PHP installation ?

  • 2017-05-11 Felipe Javier Viñoles

    Hi, I installed php 7 and everything is ok
    .

  • 2017-05-11 Diego Aguiar

    Hey Felipe Javier Viñoles

    It may be related to your PHP version, but I'm not 100% sure, which version are you using ?
    Which version of nelmio-alice are you trying to install ? also make sure that your composer is updated

    Cheers!

  • 2017-05-11 Felipe Javier Viñoles

    Hi, I clone a project where I'm going to start working and when doing a composer install I had this error ...

    PHP Parse error: syntax error, unexpected '.', expecting ',' or ';' in /var/www/html/proyectos/lcdmp-api/vendor/nelmio/alice/src/Nelmio/Alice/Instances/Processor/Methods/Reference.php on line 20

  • 2017-05-10 Fenring

    Hello,

    I'm seeking for best practice advises on using alicebundle for functional tests.
    As long as I don't add new fields to populate, everything is okay. Each generation run produce same data, so tests doesn't break.
    As soon as I add a new field to populate, every subsequent generated datas change. So test break.

    Is there a way to avoid this ?

  • 2017-02-15 Victor Bocharsky

    Hey Stan,

    Probably you could do something similar if you have access to the Symfony service container from your unit tests, but anyway, I do *not* think it's a good idea. Usually, all actual values are hardcoded in tests, which make tests more robust. Actually, if you change your fixtures - it's normal behavior if your tests fails. Because this way you will able to catch this change if you made it unintentionally. But if you do such kind of dependency - you won't be aware about it. So better do hardcode values in your tests ;)

    Cheers!

  • 2017-02-15 Stan

    Hello. I'm interesting if I can retrieve fixture object from TestCase by key like:

    SomeTest.php

    public function testSomeStuff() {
    ...
    $this->assertEquals($user->name, $this->getFixture('user_john')->name);
    }

  • 2016-10-15 weaverryan

    Hey Stephane!

    This type of error is *really* weird - great job on thinking to start from scratch to fix it! Sometimes, you can even get weird things in files like hidden whitespace characters that can cause problems. This is pretty rare, but I can remember a few times when I've had something weird like this and have pulled my hair out debugging it.

    Onward from here! Cheers!

  • 2016-10-15 Stephane

    Good news Ryan and Victor.
    I have started again Course 3 from the beginning, with a clean start code.
    Now, I don't have errors anymore with Nelmio/Alice.
    So now I can continue the course.
    I don't know where the error was.
    Stephane

  • 2016-10-15 Stephane

    Hello Ryan,
    I tried your instructions but still having the error message.
    I also tried to copy the finish version of the two files fixtures.yml and LoadFixtures.php from the source code directory.
    Maybe it's a php version conflict.
    I am using MAMP PRO v4.0.5 on OS X El Capitan. I have setup MAMP Pro and Apache to use PHP 5.6.25. I think I have properly setup PHP Storm to use MAMP Pro PHP version.
    I even tried to manually install PHP 5.6.25 on my Mac to override the former php installation. But when I open a terminal window and type PHP -v, the version is 5.5.36.

  • 2016-10-11 weaverryan

    Hi Stephane!

    Hmm, yes, this is very strange - it almost seems like that line 20 has a syntax error in the PHP file itself, which definitely doesn't make any sense (I've checked on the alice repository, and I don't see any reports of a similar error). Just in case there was some sort of corruption when downloading alice, try this:


    rm -rf vendor/
    composer install

    Also, what version of PHP are you on?

    Cheers!

  • 2016-10-11 Stephane

    Hi Victor,

    I have checked my code, and there is no syntax error like you describe. Maybe the typo in my post above comes from when I paste the code in my message and when trying to indent the code.
    It still does not work.

    This is what I found in Reference.php file :
    private static $regex = '/^[\',\"]?'
    .'(?:(?<multi>\d+)x\ )?'
    .'@(?<reference>[\p{L}\d\_\.\*\/\-]+)'
    .'(?<sequence>\{(?P<from>\d+)\.\.(?P<to>\d+)\})?'
    .'(?:\->(?<property>[\p{L}\d_.*\/-]+))?'
    .'[\',\"]?$'
    .'/xi';

    Line 20 is the line just below private static. So I suspect there is a bug in the regex ?

    Stephane

  • 2016-10-11 Victor Bocharsky

    Hey Stephane,

    As I see you have unexpected ="" symbol in `numberbetween()` function, please, remove it. I bet it's the problem, the right line should be:


    AppBundle\Entity\Genus:
    genus_{1..10}:
    speciesCount: <numberbetween(100, 100000)="">

    and btw, consider a correct letter case: `numberBetween()` not `numberbetween() ` ;)

    P.S. I tweak styles in your message a bit to improve code readability: use pre and code tags for formatting, or take a look at GitHub's Gist service.

    Cheers!

  • 2016-10-10 Stephane

    Hello Victor,
    It's the current tutorial. Here is the YAML file fixtures.yml :


    AppBundle\Entity\Genus:
    genus_{1..10}:
    name: <name()>
    subFamily: <text(20)>
    speciesCount: <numberbetween(100, 100000)="">
    funFact: <sentence()>

    And the LoadFixtures.php file :


    namespace AppBundle\DataFixtures\ORM;

    use AppBundle\Entity\Genus;
    use Doctrine\Common\DataFixtures\FixtureInterface;
    use Doctrine\Common\Persistence\ObjectManager;
    use Nelmio\Alice\Fixtures;

    class LoadFixtures implements FixtureInterface
    {
    public function load(ObjectManager $manager)
    {
    Fixtures::load(__DIR__.'/fixtures.yml', $manager);
    }
    }

    Sorry, the indentation does not display.

    Stephane

  • 2016-10-10 Victor Bocharsky

    Hey Stephane,

    It seems you have syntax error in your fixtures: you missed `,` or `;` somewhere, but it difficult to say where - I don't see your code. Please, double check code of your fixtures. With PHP files PhpStorm helps well, but with YAML most probably you should do it manually. Btw, is it a public project? Could you show me content of your fixture?

    Cheers!

  • 2016-10-09 Stephane

    Hello, I am trying to use the fixtures with Alice, and I got the following message in the Terminal :

    php bin/console doctrine:fixtures:load
    Careful, database will be purged. Do you want to continue y/N ?y
    > purging database
    > loading AppBundle\DataFixtures\ORM\LoadFixtures
    Parse error: parse error, expecting `','' or `';'' in /Users/me/vendor/nelmio/alice/src/Nelmio/Alice/Instances/Processor/Methods/Reference.php on line 20
    [Symfony\Component\Debug\Exception\FatalErrorException]
    Parse Error: parse error, expecting `','' or `';''
    doctrine:fixtures:load [--fixtures [FIXTURES]] [--append] [--em EM] [--shard SHARD] [--purge-with-truncate] [--multiple-transactions] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command>

  • 2016-09-28 Maksym Minenko

    Yes, just ru_RU helped! Thank you.

  • 2016-09-27 Victor Bocharsky

    Hey Maksym,

    Thanks for sharing your steps!

    What about locale: first of all, try to use `ru_RU` instead of `ru` on `hautelook_alice.locale` key because this locale uses by Faker. Then, I think you should activate translator in your app/config.yml:

    framework:
    translator: { fallback: en }

    Also double check that the Faker's features you use is properly localized here: https://github.com/fzaninot... - otherwise there's no any effect, it'll fallback to EN.

    Cheers!

  • 2016-09-27 Maksym Minenko

    OMG, a couple of hours of frustration and now I've found the solution myself... I just had to use hautelook_alice:doctrine:fixtures:load

    Ok, maybe this will be helpful to somebody, so the steps are:
    1) composer require --dev hautelook/alice-bundle doctrine/data-fixtures
    2) activate it in the AppKernel:
    $bundles[] = new Hautelook\AliceBundle\HautelookAliceBundle();
    3) create an yml file in the src/AppBundle/DataFixtures/ORM folder (we don't need any additional classes there)
    4) ./bin/console hautelook_alice:doctrine:fixtures:load

    Additionally, configure the bundle in the config_dev.yml

    P.S. And locale setting doesn't work for me for some reason. I set
    hautelook_alice:
    locale: ru

    but to no effect.

  • 2016-09-27 Maksym Minenko

    I just can't get Alice to work! :(
    I'm not even sure which package to install now: nelmio/alice or hautelook/alice-bundle

    The way shown in the video doesn't work for me -- the class Nelmio\Alice\Fixtures seems like doesn't exist anymore.

    And I can't get hautelook/alice-bundle to work either... Seems like they don't support Symfony 3... For example, their documentation suggests using "php app/console fixtures:load"

    Well, I did get to work nelmio/alice 3.0.dev and (after that) hautelook/alice-bundle (via AbstractLoader::getFixtures() method).
    But after running doctrine:fixtures:load the database remained empty...

  • 2016-08-22 Chmlls

    No, it did not work, also I tried with nelmio_alice:
    Error: [Symfony\Component\DependencyInjection\Exception\InvalidArgumentException] There is no extension able to load the configuration for hautelook_alice etc

    The fix I found was passing an array as configuration in LoadFixtures.php

    code class="php">
    class LoadFixtures implements FixtureInterface
    {
    public function Load(ObjectManager $manager)
    {
    $config = array('locale' => 'es_ES');
    $objects = Fixtures::load(__DIR__.'/fixtures.yml', $manager, $config);
    }
    }

    Thanks anyway Victor

  • 2016-08-22 Victor Bocharsky

    Hey Chmlls,

    I suppose you didn't set the correct locale in Alice bundle config. Set the alice locale to "es_ES" in your config file:

    # app/config/config_dev.yml
    hautelook_alice:
    locale: es_ES

    Let me know if it helped.

    Cheers!

  • 2016-08-20 Chmlls

    Nice tutorial as always!

    How do I implement this example that I found in https://github.com/fzaninot...
    Search for: $faker->dni
    I tried with dni: <dni()> but I got this: [InvalidArgumentException] Unknown formatter "dni"

  • 2016-07-26 0x90

    Of course I had to encounter the weird bug. :P Thanks, that fixed it.

  • 2016-07-26 weaverryan

    I think I've seen this before actually - it's a bug in PhpStorm itself. Sometimes, for some reason, it suddenly thinks that a namespace has a syntax error in it. I copy the entire namepace line, delete it, wait a moment, then paste it back. For me, PhpStorm is happy once I do this.

    Let me know if this works!

  • 2016-07-25 0x90

    Certainly.

    - I have the 2016.1 (most recently patched) version of PhpStorm and IntelliJ IDEA on two different machines
    - Both have PHP Annotations and Symfony

    Here's the screenshot with ORM in the namespace:

    http://imgur.com/App8un7

    Here's the screenshot without ORM in the namespace:

    http://imgur.com/wcNLEqw

    $ pwd;ls
    /[...]/src/AppBundle/DataFixtures/ORM
    LoadFixtures.php fixtures_blog.yml fixtures_projects.yml

  • 2016-07-25 Victor Bocharsky

    Hey 0x90 ,

    Could you provide a bit more information? What version of PhpStorm do you use? Do you have the "PHP Annotations" plugin installed for PhpStorm? And please, show the part of your entity when you get this error (Show us how you use this namespace and some property where you try to use it and get error). We would be happy to help you with it. Thanks!

    Cheers!

  • 2016-07-23 0x90

    When I namespace with ORM, PhpStorm yells at me with the error message "Undefined constant ORM" and "Expected identifier". And it'll refuse to recognize the use statements, causing the implements FixtureInterface to be unrecognized. Once I remove the ORM from the namespace, PhpStorm is happy and I get my autocomplete. My question is why and what can I do to fix it?

  • 2016-06-29 JLChafardet

    im really loving alice for my dev environment! fixtures rule!

  • 2016-04-19 weaverryan

    Hey Hans!

    Wow, you should totally submit this as a pull request to Alice - it's a great bug fix! Either way, thanks for posting here!

  • 2016-04-18 Hans Nieuwenhuis

    Hi,

    Just in case someone else is running into this issue :

    I am running symfony and the database in two separate Docker containers.
    I created those containers myself and they are based on alpine linux.
    Since Alpine does not support GLOB_BRACE
    (The thing is that Alpine Linux uses musl-libc instead of the Linux standard GNU libc. It seems that musl does not implement GLOB_BRACE because this is not a POSIX defined option.)

    I got an error when executing the bin/console doctrine:fixtures:load

    [Symfony\Component\Debug\Exception\ContextErrorException]
    Notice: Use of undefined constant GLOB_BRACE - assumed 'GLOB_BRACE'

    As long as Alpine has this limitation, the following workaround can be used :
    Edit vendor/nelmio/alice/src/Nelmio/Alice/Fixtures.php

    and replace the line
    $matches = glob($files, GLOB_BRACE);
    with
    $matches = glob($files, (defined('GLOB_BRACE') ? GLOB_BRACE : 0));

    After this change the fixtures run smoothly