Buy

Fixtures: For some dumb data

We have the bundle! Plug it in! Open up the AppKernel class and add it there:

// app/AppKernel.php
// ...

$bundles = array(
    // ...
    new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
);

To see if it’s working, try getting help information on a new doctrine:fixtures:load console task that comes from the bundle:

$ php app/console doctrine:fixtures:load --help

We see the help information, so we’re ready to write some fixtures.

Writing Fixtures

A fixture is just a PHP class that puts some stuff into the database.

Create a new file in the DataFixtures\ORM directory of your bundle. Let’s call it LoadEvents.php, though the name doesn’t matter.

Create a src/Yoda/EventBundle/DataFixtures/ORM/LoadEvents.php file.

To breathe life into this, copy and paste the example from the docs. Change the namespace above the class to match our project. Notice that the namespace always follows the directory structure of the file:

// src/Yoda/EventBundle/DataFixtures/ORM/LoadEvents.php
namespace Yoda\EventBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

class LoadEvents implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        // .. todo
    }
}

Now we just use normal Doctrine code to create and save events. This is the play.php file all over again:

use Yoda\EventBundle\Entity\Event;
// ...

public function load(ObjectManager $manager)
{
    $event1 = new Event();
    $event1->setName('Darth\'s Birthday Party!');
    $event1->setLocation('Deathstar');
    $event1->setTime(new \DateTime('tomorrow noon'));
    $event1->setDetails('Ha! Darth HATES surprises!!!');
    $manager->persist($event1);

    $event2 = new Event();
    $event2->setName('Rebellion Fundraiser Bake Sale!');
    $event2->setLocation('Endor');
    $event2->setTime(new \DateTime('Thursday noon'));
    $event2->setDetails('Ewok pies! Support the rebellion!');
    $manager->persist($event2);

    // the queries aren't done until now
    $manager->flush();
}

Notice that we only need to call flush once. Doctrine prepares all of its work and then sends the queries as efficiently as possible all at once.

Loading the Fixtures

Ok, let’s load some fixtures. Go back to the console and try the new doctrine:fixtures:load command:

$ php app/console doctrine:fixtures:load

When we look at the site, we’ve got fresh dummy data to play with. Re-run the command whenever you want to start over: it deletes everything and inserts the fixtures in a fresh state.

Tip

If you’d rather add to the existing data, just pass the --append option.

Leave a comment!

  • 2016-09-15 Victor Bocharsky

    Hey MilanG,

    Well, fixtures do generate content for you. Actually, content is generated by faker library, which has already integrated to the alice package. But, it also allows developers customize content which will be generated, i.e. how big post content should be, how many words generate for post title, which language use for user's dummy name, etc. In other words, each project has different fields with different types and different validation rules, so make something common for all possible cases is difficult, I'd rather say it impossible.

    When you have written some fixtures once - you can reload these fixtures as many times as you want in the future.

    Do you agree with me?

    Cheers!

  • 2016-09-15 MilanG

    Hmm...I expected that fixtures would automatically generate content. I.e. in entity type "book" please generate 15 random peaces of content. Now, when I saw that I have to do it manually I'm disappointed. Why do I need extra bundle at all when I have to do it by hand, writing the code which will generate entity?

  • 2016-08-29 Victor Bocharsky

    Hey Tael,

    Good cross reference, thanks!

  • 2016-08-28 Tael Kim

    DONT PANIC for old version
    and see https://knpuniversity.com/scre...

  • 2016-08-28 Tael Kim

    DONT PANIC for old version
    and see https://knpuniversity.com/scre...
    have fun!

  • 2016-07-12 weaverryan

    Hey Simon!

    Can you explain this with a bit more detail? I'm sorry - I don't understand what all the entities and relationships look like :).

    Cheers!

  • 2016-07-08 simon buerman

    how can i do to make a multiple relashionship ? i explain: i have a modele car table , a marque-car table and a driver table with two fields modele_car and marque. how can i do for that the modele_car generated equal the good marque-car.

  • 2016-06-30 weaverryan

    Your "Edit" sounds right - iirc, the authors of the AliceBundle are working to address some "ordering" problems.

  • 2016-06-30 rddro

    Hello , yes it works with and without quotes but noticed something strange.
    While running the fixtures multiple times, only the id of the place is regenerated everything else stays the same?
    Only way to create something new after the first fixture load is to drop the database and recreate it.
    Edit: Fixed , it seems it's running the fixtures in the order defined in the YML , so you'd have to put the relationship childrens before the parent.

  • 2016-06-30 Victor Bocharsky

    Hey, rddro !

    `hautelook/alice-bundle` is a bundle for standalone `nelmio/alice` library, which ports this lib and another one (fzaninotto/Faker) for the Symfony applications. If you see its dependencies - you will find `nelmio/alice`. So if you're on a Symfony app, you probably want to use this bundle instead of standalone library.

    And yes, it's still possible to use random relationships (using wildcard *) in new version 2.x. Do you have any errors using it? Try to wrap it with quotes like place: '@place_*'.

    Cheers!

  • 2016-06-30 rddro

    hello ? I think I've been using a different thing ? Didn't have a problem with it yet , the nelmio/Alice one ?
    Are they related ??
    Another question I'm having , was looking through the documentation and not sure is it possible to select a random relationship like this ?

    AppBundle\Entity\Conference:
    conference{1..5}:
    startat: <datetimethisdecade()>
    comment: <realtext(420)>
    place: @place_*

    AppBundle\Entity\Place:
    place_{1..10}
    name: <city()>
    address: <streetaddress()>
    website: <domainname()>

  • 2016-06-29 rddro

    😂😂😂

    $this->roles = array($roles); Indeed this was the case all good. Don't remember why I changed this was testing something and forgot to change it back >.<
    Thanks

  • 2016-06-29 weaverryan

    Hmm - yea it definitely looks like we're ending up with an array of arrays - array(array('ROLE_ADMIN')) instead of just array('ROLE_ADMIN').

    I would double-check your setRoles() method - make sure you're not accidentally wrapping the array in another array before setting it. For example, this would be a problem:


    public function setRoles($roles)
    {
    $this->roles = array($roles); // this is bad, you'd end up with 2 arrays
    }

    If this isn't the problem, then I would dump the $roles argument in setRoles() to see what is being passed to you:


    public function setRoles($roles)
    {
    dump($roles);die;
    }

    Cheers!

  • 2016-06-29 rddro

    Hello , seems it doesn't like it if i define it as an array not sure why.
    If i put [] in the fixture for the role it will generate an array of array
    a:1:{i:0;a:1:{i:0;s:10:"ROLE_ADMIN";}} instead of a:1:{i:0;s:10:"ROLE_ADMIN";}
    If I leave it as a string like roles : ROLE_ADMIN it will generate the good array.
    Maybe it had something to do with the setRoles() annotation in the entity. Cheers

  • 2016-06-26 weaverryan

    Hey Simon!

    I think you'll need to write a custom formatter for this (like we built in this chapter), but I'm not exactly sure how - in the formatter - you would retrieve the current "index". In YAML, there is a function called <current()> that you can use to get the current row number (https://github.com/nelmio/alic.... But, you would need to be able to retrieve this from inside of your formatter, and that might be tricky.

    Another possibility is this: *don't* use ranges: simply create 10 separate marque entries. I realize that you will probably now have a lot of duplication - each marquee may have a lot of similar data. But, if you use "inheritance" in Alice, you can remove this duplication: https://github.com/nelmio/alic...

    I hope this helps!

  • 2016-06-26 weaverryan

    Yep, good call! There is a new version of the library - and it's great - but it's *totally* different now :). This tutorial covers 0.1.5.

  • 2016-06-26 Grzegorz Szaliński

    In case someone runs into the same problem...
    Since I'm taking this screencast after 2 years from its release, I had a lot of dependencies errors while loading composer repositories with

    composer require hautelook/alice-bundle

    I updated it with the particular version that was valid at that time (0.1.5), and it worked:

    composer require hautelook/alice-bundle 0.1.5
  • 2016-06-25 simon buerman

    Hello i would like to know to link a array key with an entry. By examble when i write marque{1...10}. I would like that the first equal the first value of my array etc

  • 2016-06-18 weaverryan

    Hey rddro!

    Basically, you want to set an array onto roles (since roles is an array field). To do that in YAML, use this syntax:


    users_{1..10}:
    username: # ...
    # ...
    roles: [ROLE_USER, ROLE_ADMIN]

    # ... or, if you want something random, it should be something like this
    roles: <randomelements(['role_user', 'role_adimn',="" 'role_client'])="">

    Cheers!

  • 2016-06-17 rddro

    Update : it would seem you can echo them like so
    roles:


    $role= ['ROLE_ADMIN', 'ROLE_USER', 'ROLE_SUPER_ADMIN', 'ROLE_CLIENT'];
    echo '['.$names[array_rand($role)].']';

    but I think there might be a better way

  • 2016-06-17 rddro

    Hello o/ Anyone have some clue how to add the user role ? Tried to set it like roles: 'a:1:{i:0;s:10:"ROLE_ADMIN";}' but it didn't work properly.

  • 2016-03-08 weaverryan

    Hey Oscar!

    The bundle looks in the DataFixtures/ORM directory of each of your bundles for fixture classes. If it doesn't find *any*, you'll get this error. So double check that you have the fixture class in DataFixtures/ORM. But also, this tutorial covers an older version of the bundle - so this could be from a difference with the new version! In the next few days, we'll have an updated section about using Alice for fixtures in our Doctrine tutorial: http://knpuniversity.com/scree....

    Cheers!

  • 2016-03-08 weaverryan

    Ah, thank you! It'll be covered in the new Doctrine tutorial (near the end) which will start coming out this week: http://knpuniversity.com/scree.... Here's a preview on the script (https://github.com/knpuniversi... (if that helps) - the actual code blocks will be at the first link soon. Cheers!

  • 2016-03-07 Paweł Montwiłł

    Thanks for a quick reply. Can you please drop a few lines how you use it?

    BTW brilliant tutorials :)

  • 2016-03-06 Oscar

    When i try to load the fixtures i get this error:

    [InvalidArgumentException]
    Could not find any fixtures to load in:
    - /Applications/MAMP/htdocs/starwarsevent/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBund
    .... and more

    Help please

  • 2016-03-06 weaverryan

    Yea, I've been thinking about this! I haven't used it much, but the new version of the bundle looks harder to use. Recently, I used Alice + DoctrineFixturesBundle directly (with no other bundle) and was very happy.

  • 2016-03-06 Paweł Montwiłł

    Great tut!

    It would be nice to update it with the latest changes to Alice (at least in the text below):
    1. Using Hautelook\AliceBundle\Doctrine\DataFixtures\AbstractLoader instead of DataFixtureLoader
    2. Launching update with hautelook_alice:doctrine:fixtures:load (or h:d:f:l) instead of doctrine:fixtures:load.

  • 2016-02-19 Rénald Casagraude
    Anyone know if there's a way to have alice 'override' a primary key?

    @weaverryan is right, Alice _simply_ hydrate entities, so the behaviour is implied by Doctrine. In fact, you probably have a primary key with an id generation handled by Doctrine himself (http://doctrine-orm.readthedoc.... I also play with metadata when I need predictable IDs :


    // Don't forget to add a setter for ID on your entity (eg: Pokemon::setId($id))
    $em = $this->getContainer()->get('manager.pokemon');
    $metadata = $em->getClassMetaData('AppBundle\Entity\Pokemon');
    $generatorType = $metadata->generatorType;
    $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);

    $fixtures = $this->loadFixtureFiles([
    '@AppBundle/Tests/DataFixtures/ORM/Pokemon.yml',
    ]);

    $metadata->setIdGeneratorType($generatorType);
  • 2016-02-16 weaverryan

    Yea, I've never tried it. Strictly speaking, it's fine to do this directly in Doctrine, and my impression of Alice is mostly that it is simply calling the setters on your entity methods and then persisting them - in which case there would be no issue. But I'm guessing there's something complication I'm not seeing :)

  • 2016-02-12 gstanto

    Anyone know if there's a way to have alice 'override' a primary key? I'm using these fixtures along with Behat BDD and it's a lot more convenient to say GET users/500 rather than have to deal with getting the id dynaimically each time. Doing it outside of Alice I am overwriting the metadata to do this.

    I've tried to pass the @self to a custom formatter and set the metadata this way, but it doesn't seem to be working. Alice is real cool, so I'd def. like to use it everywhere I can. Thanks!

  • 2015-12-01 weaverryan

    Yo Nick! It should be something like this: https://github.com/nelmio/alic.... Basically, if Post is ManyToMany with Tag, then you ultimately want to call something like Post->setTags($tags) where $tags is an array of objects. By setting the "tags" property to an array of references (like in the link), I think it should work. And even better, the commenter says that it will find adder methods, which is pretty cool.

    Let me know if it works out :)

  • 2015-12-01 Nick

    How to achieve fixtures for many to many tables where there is no entity?

  • 2015-10-19 weaverryan

    @Daniel - I see the issue: if you open up a clone of the standard edition that shows your code not working, then it might be faster for the maintainer to see what's going wrong. Also, be very detailed about any errors you may or may not be getting :)

  • 2015-10-17 Daniel

    I haven't been able to execute it successfully yet. There is an issue open regarding this very same point. The maintainer pointed out the test case as reference https://github.com/hautelook/A... but is not working for me either

  • 2015-10-12 Daniel

    Thanks a lot!

  • 2015-10-12 weaverryan

    Indeed it is! For loading in tests, you can run the commands directly (http://symfony.com/doc/current..., though I usually try to find the "right" way to call it, which basically means doing the same thing as the command: https://github.com/hautelook/A.... That may or may not be tricky - usually I'm hoping to be able to fetch just one service out and call one method on it - this looks a bit more involved (but it may not be once you look into it).

    Cheers!

  • 2015-10-10 Daniel

    Yeah, it is more in line with symfony's way of doing things. The processors need to be defined as services with arguments and stuff. One question, how would I load alice's fixtures on my tests? I tried this $fixtures = $container->get('hautelook_alice.doctrine.command.load_command'); but didn't work. Thanks

  • 2015-10-09 weaverryan

    It looks like the bundle got a nice new facelift - I'll take a look at what's been updated :).

  • 2015-10-08 Daniel

    Found the solution. I was previously using regular Doctrine Fixtures, so having a look at this excerpt https://github.com/hautelook/A... found that running php app/console h:d:f:l or hautelook_alice:doctrine:fixtures:load will load only alice fixtures. The confusing part is that when running the regular doctrine:fixtures:load I see that the alice fixtures are alse executed. Thanks any way

  • 2015-10-07 Daniel

    Hello Ryan! I just installed the bundle latest version and found out the class you extend doesn't exist any longer, nonetheless in the documentation they extend the class AbstractLoader. I ran the usual command fixutures:load and my class is there but no data added to the data base. How can I debug a command? Because I thing the problem is the route where I placed the yaml file. Tried var_dump to no avail. Thanks

  • 2015-08-27 weaverryan

    :thumbsup: nice work!

  • 2015-08-26 aguidis

    Thanks a lot Ryan you were right. In my last field (a string one) I used a function that returns an array (paragraphs()) Shame on me !

    I'll no longer make this error ^^ Thank you for your advices

  • 2015-08-26 weaverryan

    Hey there!

    Ok coo. So, I *probably* know what your issue is :). Somehow, you probably have some Alice code that is setting an array of data on a field that is mapped as a string on the database. I could be wrong, but Doctrine is probably trying to convert an array (that was set on an entity by Alice) into a string while saving. I would remove the alice lines one-by-one until this error goes away (like you were doing). When you finally don't have an error - or have the above error about a null constraint - it means the saving is happening, and probably the last line you removed is the problem. You could also open the core Doctrine code where the error is being thrown, and do a little var_dump() of the value right before the error. Then you can see what array value is trying to be turned into a string, which might help debugging.

    I hope that helps!

  • 2015-08-26 aguidis

    Hello, thanks for this tutorial I didn't know this cool library !

    I tried to use it in my project but I always have this error in the console :

    [Symfony\Component\Debug\Exception\ContextErrorException]

    Notice: Array to string conversion

    I don't have other information for debugging. I tried to remove some fields in my fixture yml file and when I run the doctrine:fixtures:load I have a SQL error like "SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'registration_details' cannot be null". It means that Alice is trying to insert data right ?

  • 2015-08-25 weaverryan

    Great solution! Nothing is built in to do this, so I think you solved this perfectly!

  • 2015-08-25 toioski

    Hi! Great tutorial!

    I have only one question: is there any way to make a relation with data which already exist in the database?

    E.g.
    I want to generate fixtures for the entity Conversation which as 3 attributes:
    - name
    - creationDate
    - creator -> this is ManyToOne with the entity User

    Is it possible to say to the 'creator' attribute to take a random User from the database and not from another .yml file?

    UPDATE:
    I solved creating a custom function for Alice (like the one created in the screencast for super heroes names) which return a casual user id from the ones present in the database.

  • 2015-01-24 weaverryan

    Hi Sergio!

    Good question! If you want, you can add it to the `require-dev` part of your `composer.json`: https://getcomposer.org/doc/04..., though at best, that simply means that it won't be downloaded to your disk in an environment, and disk space is cheap.

    What you *really* want is to add it to AppKernel in the spot where it's only loaded in the `dev` environment: https://github.com/symfony/sym.... There's no downside to this, and it'll give you a very minor performance boost in the `prod` environment.

    Cheers!

  • 2015-01-23 Sergio

    Hello, great tutorial!

    Is there any way to put this dependency (hautelook/alice-bundle) in my composer.json project file and only load it for development environment ?

  • 2015-01-07 weaverryan

    It's a poorly-publicized fact - I hope to make that more obvious soon :). Thanks again!

  • 2015-01-07 Victor Bocharsky

    Very quickly! :)
    I didn't know that code was available on GitHub, it would be better to create a pull request.
    Thanks for quick fix

  • 2015-01-07 weaverryan

    You're right - good catch! I just updated it :) https://github.com/knpuniversi...

    Tanks!

  • 2015-01-07 Victor Bocharsky

    Hi, thanks for this screencast!
    I also found typo in the text. I think you wanted to write "characters.yml" instead of "test.yml" in second code block (after sentence "Let’s call ours characters.yml and then go ahead and create that file:").

  • 2014-11-21 Nick

    Thanks for reply! Yes VichUploaderBundle is very good for Uploads. Also that's exactly what I mean!

  • 2014-11-21 weaverryan

    Hey Nick!

    I *think* I know what you're asking, and I'm planning on covering it in one upcoming screencast. If I have a field that normally holds a value like "foo.png", and that's populated by uploading a file, then I would use processors: https://github.com/nelmio/alic... to look for that file in some pre-configured directory and move it into some "uploads" directory (wherever your files normally upload to - you could even move to S3).

    As far as the URL to the image, now that you have "foo.png" stored in your database and the file actually lives in the correct upload spot, it's up to you in your template to link to it correctly. Btw, I recommend using VichUploaderBundle to handle uploads and link to them.

    Let me know if I hit on your question!

  • 2014-11-21 Nick

    Is there a way to add image url(s) as well via this bundle? Maybe a field in db points to an image URL.

  • 2014-11-04 Larry Garfield

    11:40... If you want to import your fixtures from scratch, you must first create the test universe.

  • 2014-10-31 isomoar

    Awesome!