8

I'm using the DoctrineFixtures bundle to create example entities during development. In my ORM fixtures load() method, I define the data as associative arrays and create the entity object in a loop.

<?php
// ...
public function load($manager) {
    $roleDefs = array(
        'role-1' => array(
             'role' => 'administrator'
        ),
        'role-2' => array(
             'role' => 'user'
        ),
    );

    foreach($roleDefs as $key => $roleDef) {
        $role = new Role();
        $role->setRole($roleDef['role']);
        $manager->persist($role);

        $this->addReference($key, $role);
    }

    $manager->flush();
}

I always use the same array schema. Every array element uses the property name (in underscore notation) of the entity as index. If the entity structure becomes more complex, there are a lot of $entity->setMyProperty($def['my_property']); lines.

I think the problem of mapping propertynames to setter methods is a very common problem in Symfony and Doctrine as this type of mapping is found in many situations (e.g. mapping forms to entities).

Now I'm wondering if there is a built-in method that can be used for mapping. It would be nice to have a solution like

foreach($defs as $key => $def) {
   $entity = $magicMapper->getEntity('MyBundle:MyEntity', $def);
   // ...
}

Has someone an idea how this can be achieved?

Thanks a lot, Hacksteak

1 Answer 1

13

I sometimes use loops when creating fixtures. I'm not sure if this solution fits your requirements, but I find that the most flexible way to build fixtures and quickly add new properties over time if you need is to do the following... Assuming the creation of a bunch of blog posts:

// an array of blog post fixture values
$posts = array(
    array(
        'title' => 'Foo',
        'text'  => 'lorem'
        'date'  => new \DateTime('2011-12-01'),
    ),
    array(
        'title' => 'Bar',
        'text'  => 'lorem'
        'date'  => new \DateTime('2011-12-02'),
    ),
    // more data...
);

// loop over the posts
foreach ($posts as $post) {
    // new entity
    $post = new Post();

    // now loop over the properties of each post array...
    foreach ($post as $property => $value) {
        // create a setter
        $method = sprintf('set%s', ucwords($property)); // or you can cheat and omit ucwords() because PHP method calls are case insensitive
        // use the method as a variable variable to set your value
        $post->$method($value);
    }

    // persist the entity
    $em->persist($post);
}

This way you can add more properties by just adding the new values to your array.

Sign up to request clarification or add additional context in comments.

4 Comments

I'm now using your solution with some modifications (support for underscores and add-methods) in en external class.
I saw this resolution before, but I think could resolve this issue more flexibly. How about internal hydrators?
I'd definitely be interested in hearing a more flexible solution, so I'm all ears!
Good to see it, I was wondering if my method was right, I do the same things. When get some value from an array, and the array is not precise as the entity I'm use to do also a check for the method if exists with "method_exists()".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.