3
votes

I am currently trying to create a reusable bundle with Symfony2 using model classes but I am not able to register their mappings so Doctrine recognize them.

I read that using compiler pass could be the solution so I followed the guide in the Symfony Cookbook (http://symfony.com/doc/current/cookbook/doctrine/mapping_model_classes.html) and I also looked at the source code in the FOSUserBundle for some inspiration.

And here is what I've done so far :

class GPGoodsBundle extends Bundle{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $this->addRegisterMappingsPass($container);
    }

    /**
     * @param ContainerBuilder $container
     */
    private function addRegisterMappingsPass(ContainerBuilder $container)
    {
        $modelDir = realpath(__DIR__.'/Resources/config/doctrine/model');
        $mappings = array(
            $modelDir => 'GP\Bundle\GoodsBundle\Model',
        );
        $ormCompilerClass = 'Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass';
        if (class_exists($ormCompilerClass)) {
            $container->addCompilerPass(
                DoctrineOrmMappingsPass::createXmlMappingDriver(
                    $mappings,
                array('gp_goods.model_manager_name'),
                'gp_goods.backend_type_orm'
                )
            );
        }
    }
}

But when trying to migrate my entity (just to see if it's working) here is the result :

$php app/console doctrine:migrations:diff
No mapping information to process.

My entities are stored under "GP\Bundle\GoodsBundle\Model" and their mappings under "GP\Bundle\GoodsBundle\Resources\config\doctrine\model"

So my question is : what is the good way to create a reusable bundle and how to register mappings of model classes?

If you need any additional information, do not hesitate to ask!

Thank you for your help!

Here is one of my model classes :

class Good implements GoodInterface{
    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    protected $serial;

    /**
     * @var \DateTime
     */
    protected $manufacturedAt;

    /**
     * @var \DateTime
     */
    protected $deliveredAt;

    /**
     * @var \DateTime
     */
    protected $expiredAt;

    /**
     * @var string
     */
    protected $checkInterval;

    /**
     * @var string
     */
    protected $status;

    /**
     * @var string
     */
    protected $slug;

    /**
     * @var \DateTime
     */

    protected $createdAt;

    /**
     * @var \DateTime
     */

    protected $updatedAt;

    /**
     * @var \DateTime
     */

    protected $deletedAt;

    public function __construct(){
        $this->createdAt = new \DateTime("now");
        $this->status = 'good';
    }

    .... getters/setters .....
}

And the mappings :

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping   xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <entity name="GP\Bundle\GoodsBundle\Model\Good" table="good">

        <id name="id" type="integer" column="id">
            <generator strategy="AUTO"/>
        </id>

        <field name="serial" type="string" column="serial" length="255"/>

        <field name="manufacturedAt" type="date" column="manufactured_at"/>

        <field name="deliveredAt" type="date" column="delivered_at"/>

        <field name="expiredAt" type="date" column="expired_at"/>

        <field name="checkInterval" type="string" column="check_interval" length="255" nullable="true"/>

        <field name="status" type="string" column="status" length="255"/>

        <field name="slug" type="string" column="slug" length="255">
            <gedmo:slug fields="serial" unique="true" />
        </field>

        <field name="createdAt" type="datetime" column="created_at">
            <gedmo:timestampable on="create"/>
        </field>

        <field name="updatedAt" type="datetime" column="updated_at" nullable="true">
            <gedmo:timestampable on="update"/>
        </field>

        <field name="deletedAt" type="datetime" column="removed_at" nullable="true">
            <gedmo:soft-deleteable field-name="deletedAt"/>
        </field>

    </entity>
</doctrine-mapping>
1
Which version of Symfony 2 and doctrine are you using?P. R. Ribeiro
Thank you for your comment. I am using "symfony/symfony" : "~2.4" and "doctrine/orm" : "~2.4.1" If you need more code or anything, just ask. I've also looked at Sylius project (github.com/Sylius/Sylius) but I'm not pretty sure to understand everything on how are registered the mappingsIanlet
Could you post the code of one of your model classes?P. R. Ribeiro
I also tried to define it as an abstract class and a mapped-superclass then create a class in the Entity folder that is extending it. But when performing a migration it says : Class 'GP\Bundle\GoodsBundle\Entity\Good' does not exist which is true because I don't have it under the Entity folder. But I don't understand why it is looking under this folder and not in the Model one... When trying to doctrine:generate:entities : No mapping file found named 'C:\pathToMyProject\src\GP\Bundle\GoodsBundle\Resources\co nfig\doctrine/Good.orm.xml' for class 'GP\Bundle\GoodsBundle\Entity\Good'.Ianlet

1 Answers

3
votes

When you have entities outside of any bundle or that the location is not the usual one, you'll have to change the doctrine section in config.yml from

doctrine:
    # ...
    orm:
        # ...
        auto_mapping: true

to

doctrine:
    # ...
    orm:
        # ...
        mappings:
            model: # replace `model` with whatever you want
                type: annotation # could be xml, yml, ...
                dir: %kernel.root_dir%/../path/to/your/model/directory
                prefix: Prefix\Namespace # replace with your actual namespace
                alias: Model # replace with the desired alias
                is_bundle: false

The dir parameter informs Doctrine where to look for the mapping definitions. If you're using annotations, it will be your model directory. Otherwise, it will be the directory of your xml/yml files.

Entities's names — to access from Doctrine repositories — begin with Model in this case, for example, Model:User. It corresponds to the parameter alias.

When editing a configuration file, do not forget to clear the cache.

Moreover, in my question, I wrote that I changed something in my Bundle class but it was not useful as the bundle won't be reused by another project. So I removed everything.


See this answer for more details : https://stackoverflow.com/a/10001019/2720307

Thanks to Elnur Abdurrakhimov!