juanmf / UserBundle

FOS User Bundle Extension with Roles/RoleHierarchy Implemented in Database.
5 stars 0 forks source link

[Doctrine\ORM\Mapping\MappingException] Property "roles" in "St\UserBundle\Entity\User" was already declared, but it must be declared only once #1

Closed vishalmelmatti closed 9 years ago

vishalmelmatti commented 10 years ago

Hi,

I am trying to use roles field as many to many association between user and role entities. I tried exact same steps you mentioned but I am getting this exception

[Doctrine\ORM\Mapping\MappingException]
Property "roles" in "St\UserBundle\Entity\User" was already declared, but it must be declared only once.

This is my bundle file,

class StUserBundle extends Bundle
{

    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $mappings = array(
            realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model',
        );

        $container->addCompilerPass(
            DoctrineOrmMappingsPass::createXmlMappingDriver(
                $mappings, array('fos_user.model_manager_name'), 'fos_user.backend_type_orm')
        );
    }    

    public function getParent()
    {
        return 'FOSUserBundle';
    }
}

The only different I can see it the getParent method? Souldn't I declare FOSUserBundle as a parent ?

or in this line

realpath(DIR . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model',

should there be path St\UserBundle\Model instead of FOS\UserBundle\Model ? I have commented roles in user.orm.xml but still same issue.

I have added this in my User entity

/**
 * @ORM\ManyToMany(targetEntity="St\UserBundle\Entity\Roles", cascade={"all"})
 * @ORM\JoinTable(name="roles_users",
 *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *   inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
 * )
 */
protected $roles;

It this because I am extending my User entity from FOS\UserBundle\Model\User class ?

https://github.com/juanmf/UserBundle/blob/master/Entity/User.php

You also are extending it but does it work for you ?

vishalmelmatti commented 10 years ago

I could fix above by removing $roles field from my User entity. and added mapping in my User.orm.xml

     <many-to-many field="roles" target-entity="St\UserBundle\Entity\Roles">
        <join-table name="roles_users">
            <join-columns>
                <join-column id="user_id" referenced-column-name="id" />
            </join-columns>
            <inverse-join-columns>
                <join-column id="role_id" referenced-column-name="id" />
            </inverse-join-columns>
        </join-table>
    </many-to-many>

But it leads to some other error now. If I try to login, I get mysql error as it still tries to find roles field in users table. "Unknown column roles". Any idea why it still looks for roles column even if I overriden roles mapping ?

juanmf commented 10 years ago

Hi,

It works for me without xml mappings for the new definition of $roles.

Next line is ok, it points to FOS User class.

realpath(DIR . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model',

You can use, AFAIK, only one config format in each Bundle. I don't see why you are making queries with roles field in User. have you checked that the roles_user table actually exists?

vishalmelmatti commented 10 years ago

Yes, roles_user table exist and everything works perfectly if I directly remove roles file configuration in FOSUserBundle and write this

/**

in my user entity. But it doesn't work if I copy the User.orm.xml in my bundle and remove roles configuration from copied xml. It seems it still loads roles config from FOSUSerBundle User.orm.xml

juanmf commented 10 years ago

Can you make a gist with your appKernel.php and your composer.json ?

aistis- commented 10 years ago

I had the same error. My solution was to make a full copy User.orm.xml of FosUserBundle, modify it for my needs and place it in my UserBundle/Resources/config/doctrine. I have also removed build method from my UserBundle.php and added this to config.yml:

doctrine:
    dbal:
        ...
    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        default_entity_manager: default
        entity_managers:
            default:
                mappings:
                    FOSUserBundle:
                        mapping: false

Note that all doctrine mapping must be in the same format in the same bundle. Including and Role.orm.xml

juanmf commented 10 years ago

In that case you are deactivating mappings (then there is nothing to override...) I don't know why people are having troubles with the override, the build method in the UserBundle calss is key for that, and it depends on the new version of doctrineBundle "doctrine/doctrine-bundle": "~1.3@dev" I'm making a guess but I think it might be related with the order in which Bundles are loaded in appKernel. I recall having solved an issue changing the order of Bundles in it.

buffcode commented 10 years ago
DoctrineOrmMappingsPass::createXmlMappingDriver(
    $mappings, array('fos_user.model_manager_name'), 'fos_user.backend_type_orm'
)

Third parameter fos_user.backend_type_orm means "Service container parameter that must be present to enable the mapping." (see class docs)

This service seems to be missing, as grepping for it did not yield any results. Even googling only returns matches regarding your posts.

composer.json:

{
    "name": "symfony/framework-standard-edition",
    "license": "MIT",
    "type": "project",
    "description": "The \"Symfony Standard Edition\" distribution",
    "autoload": {
        "psr-0": { "": "src/", "SymfonyStandard": "app/" }
    },
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "2.5.*",
        "doctrine/orm": "~2.2,>=2.2.3",
        "doctrine/doctrine-bundle": "~1.3@dev",
        "twig/extensions": "~1.0",
        "symfony/assetic-bundle": "~2.3",
        "symfony/swiftmailer-bundle": "~2.3",
        "symfony/monolog-bundle": "~2.4",
        "sensio/distribution-bundle": "~3.0",
        "sensio/framework-extra-bundle": "~3.0",
        "incenteev/composer-parameter-handler": "~2.0",
        "hwi/oauth-bundle": "0.4.*@dev",
        "friendsofsymfony/user-bundle": "~1.3"
    },
    "require-dev": {
        "sensio/generator-bundle": "~2.3"
    },
    "scripts": {
        "post-root-package-install": [
            "SymfonyStandard\\Composer::hookRootPackageInstall"
        ],
        "post-install-cmd": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles"
        ],
        "post-update-cmd": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles"
        ]
    },
    "config": {
        "bin-dir": "bin"
    },
    "extra": {
        "symfony-app-dir": "app",
        "symfony-web-dir": "web",
        "incenteev-parameters": {
            "file": "app/config/parameters.yml"
        },
        "branch-alias": {
            "dev-master": "2.5-dev"
        }
    }
}
buffcode commented 10 years ago

Okay this fixed it for me: Mapping for the User entity was missing and the service definition for the third parameter (see above) was wrong.

<?php

namespace LaserTag\UserBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;

class LaserTagUserBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $mappings = array(
            realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Model',
            realpath(__DIR__ . '/Resources/config/doctrine/model') => 'FOS\UserBundle\Entity',
        );

        $container->addCompilerPass(
            DoctrineOrmMappingsPass::createXmlMappingDriver(
                $mappings, array('fos_user.model_manager_name'), false
            )
        );
    }

    public function getParent()
    {
        return 'FOSUserBundle';
    }
}
matheo commented 10 years ago

Checkout the UserBundle I built with recent stuff: https://github.com/matheo/UserBundle

juanmf commented 9 years ago

Thanks a lot @buffcode I can't tell then how it worked for me, but I didn't realize that.