Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Delightful Dummy Data with Alice

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

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:

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()>:

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:

... 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!

53
Login or Register to join the conversation
Default user avatar
Default user avatar Danilo Silva | posted 5 years ago | edited

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?

4 Reply

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!

Reply

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!

Reply
Default user avatar
Default user avatar Scott | posted 5 years ago | edited

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
	]
);
1 Reply

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!

1 Reply
Default user avatar

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

Reply
Default user avatar
Default user avatar Syed | posted 5 years ago | edited

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.
1 Reply

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!

Reply
Default user avatar
Default user avatar Syed | Victor | posted 5 years ago | edited

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/master/bundles/DoctrineFixturesBundle/index.html#using-the-container-in-the-fixtures 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();```

1 Reply

Hey Syed,

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

Cheers!

Reply
Default user avatar
Default user avatar Tom | posted 5 years ago | edited

Hi!

So, there are a lot of problems with the ./bin/console doctrine:fixtures:load command due to the Alice update. A programmer friend of mine found a solution that worked for me, and I'd like to share it for those who are still stuck on this.

Using composer in your terminal, make sure to install the nelmio/alice "2.1.4" version, and the doctrine-fixtures-bundle "2.3" version.


composer require --dev nelmio/alice "2.1.4"
composer require --dev doctrine/doctrine-fixtures-bundle "2.3"

If you already have nelmio/alice installed on a wrong version, you can go to composer.json and change the version to "2.1.4".


"nelmio/alice": "2.1.4",

In LoadFixtures.php, add these use statements and change your class LoadFixtures:


use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Faker;

class LoadFixtures extends Fixture
{

    public function load(ObjectManager $manager) {

        $objects = Fixtures::load(
            __DIR__.'/Fixtures.yml',
            $manager,
            [ 'providers' => [$this] ]
        );

        // $manager->persist($institution);
        // $manager->flush();
    }
}

In AppKernel.php, keep the Doctrine $bundle but remove the Nelmio $bundle in the if statement:



            $bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle();
            <strike>$bundles[] = new Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle();</strike>

Now, for me at least, ./bin/console doctrine:fixtures:load finally works.
Hopefully that helps someone else like it helped me!

Oh and by the way, great tutorial so far. Thanks for the energetic and fun teaching.

1 Reply

Hey Tom!

Bah, yea. First, thank you for sharing this! Second, I currently only recommend Alice if you use the *old* version. The setup for the new version looks crazy to me... and YAML fixtures should be fun and easy, not a technical challenge :).

Thanks again for sharing - very happy you're enjoying the tuts!

Reply
Andrei V. Avatar
Andrei V. Avatar Andrei V. | weaverryan | posted 4 years ago | edited

Hello, weaverryan!
What would you recommend for Alice replacement? I've just updated from 3.2 to 4.2 and does it mean that the fixtures system needs the complete rework?

Reply

Hey Andrei V. ,

For Symfony 4 we recommend using DoctrineFixturesBundle along with Faker library, we even have a related screencasts for it in our Symfony 4 series, you can check it here: https://symfonycasts.com/sc... .

Cheers!

Reply
Andrei V. Avatar
Andrei V. Avatar Andrei V. | Victor | posted 4 years ago | edited

victor, thanks, Victor! I've already seen that and it looks awesome but not as awesome as Alice was. It was just an attempt to find something yml-like)

Reply

Hey Andrei V. ,

Ah, I see... Then just use the same hautelook/AliceBundle but follow the docs for the 2nd version of it. That's still the best probably with active support :)

Cheers!

Reply
Andrei V. Avatar
Andrei V. Avatar Andrei V. | Victor | posted 4 years ago | edited

victor, I've already rewritten my fixtures for standard Doctrine Fixtures. It wasn't as hard as I thought it would) Thanks for your help!

Reply

Hey Andrei V. ,

Ah, OK! :) Fairly speaking, doing fixtures in PHP is even more fun, at least for me, since I can get IDE autocompletion, etc and these fixtures are more flexible than Yaml one :p You can easily complicate them, not always possible that easy with Alice.

Cheers!

Reply
Default user avatar
Default user avatar Fenring | posted 5 years ago

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 ?

Reply

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!

Reply
Default user avatar
Default user avatar Felipe Javier Viñoles | posted 5 years ago

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

Reply

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!

Reply
Default user avatar
Default user avatar Felipe Javier Viñoles | Felipe Javier Viñoles | posted 5 years ago

Hi, I installed php 7 and everything is ok
.

Reply

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

Reply
Default user avatar
Default user avatar Hans Nieuwenhuis | posted 5 years ago

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

Reply

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!

Reply

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!

Reply
Default user avatar
Default user avatar Carmen Fabo | posted 5 years ago | edited

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.

Reply

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!

Reply
Default user avatar

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

Reply
Default user avatar

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

Reply
Default user avatar
Default user avatar Stephane | posted 5 years ago

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>

Reply

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!

Reply
Default user avatar
Default user avatar Stephane | Victor | posted 5 years ago | edited

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

Reply

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!

Reply
Default user avatar

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

Reply

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!

Reply
Default user avatar

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.

Reply
Default user avatar

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

Reply

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!

Reply
Default user avatar
Default user avatar Jack Strube | posted 5 years ago | edited

In order to get this to work I had to add:


AppBundle\DataFixtures\ORM\LoadFixtures:
    tags: [doctrine.fixture.orm]

In services.yml

Reply

Hey Jack,

Thanks for sharing your solution! Yes, looks like it's required for DoctrineFixturesBundle. But If you're using the default service configuration, any class that implements ORMFixtureInterface will automatically be registered with this tag, see https://symfony.com/doc/mas... for more information.

Cheers!

1 Reply
Default user avatar

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?

Reply
Victor Avatar Victor | SFCASTS | 0x90 | posted 5 years ago | edited

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!

Reply
Default user avatar

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

Reply

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!

Reply
Default user avatar

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

Reply
Victor Avatar Victor | SFCASTS | posted 5 years ago | edited

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!

Reply
Default user avatar
Default user avatar Maksym Minenko | posted 5 years ago

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...

Reply
Default user avatar

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.

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
        "doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0", // v3.1.3
        "nelmio/alice": "^2.1", // 2.1.4
        "doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
    }
}
userVoice