I use symfony2 and the mongoDb ODM. Today I have installed FosUserBundle.
My User class is like that :
use FOS\UserBundle\Document\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* #MongoDB\Document
*/
class User extends BaseUser
{
/**
* #MongoDB\Id(strategy="auto")
*/
protected $id;
public function __construct()
{
parent::__construct();
}
}
My problem is after created a User with FosUserBundle create command, only the id of user is persisted in mongodb document.
If I add the following in my User class :
/**
* #MongoDB\String
*/
protected $username;
The create command persist Id and the good username.
Of course, it's the same with all the initial fields of FOS\UserBundle\Document\User (BaseUser).
It looks like the inheritance mapping is not working properly.
Check that your Doctrine configuration in config.yml is set to:
auto_mapping: true
To work around this another way you would need to add the complete mapping information to your User entity extending the one from the FOSUserBundle.
With Doctrine\ORM it is normally the #ORM\MappedSuperClass annotation which provides the mapping for the extending class. In FOSUserBundle's mongodb xml mapping it is this line:
...
<mapped-superclass name="FOS\UserBundle\Document\User" collection="fos_user_user">
...
Solution 1:
Try this:
copy the mapping xml from FOSUserBundle over to your UserBundle into Resources/config/doctrine/User.mongogb.xml
change it to fit your own Entity Class
remove mapped-superclass node
add the id field as Id with auto strategy
You can then ommit the #MongoDB annotations on your entity completely.
To save somebody's time.
I also came across the issue of non-working mapping for ODM User entity and could not understand why it doesn't work. The reason was I must have extended my user entity from FOS\UserBundle\Document\User and not from FOS\UserBundle\Model\User
Related
In Symfony2, I just try recently to think in terms of traits, to create some sort of behaviors.
Let's say I have an address attribute in an entity. I externalized attributes, getters and setters related to this in an AddressableTrait.
But what if address become an entity? I started to try to define my OneToMany relation in my trait, as if it was in a regular entity :
use Doctrine\ORM\Mapping as ORM;
class AddressableTrait {
/**
* #var
* #ORM\OneToMany(targetEntity="XXXX\GlobalBundle\Entity\Address", inversedBy="What to put here" )
*/
protected $addresses;
/**
* #return ArrayCollection
*/
public function getAddresses()
{
return $this->addresses;
}
/**
* #param ArrayCollection $addresses
*/
public function setAddresses($addresses)
{
$this->addresses = $addresses;
}
}
What to put in the inversedBy? The purpose of the trait if precisely to embed all the behavior feature, so I think that at least using traditionnal annotation/YML/XML,it's not possible to achieve.
I digged a bit into it and found this very interesting link that seems to allow you to defines relation via events, but there is still logic to add to "finish" relations.
UPDATE :
Using the above link, I managed to created dynamic ManyToMany relation. the schema update works when creating, but if I comment the dynamic relation, a schema:update --dump-sql doesn't remove it. It seems to work add-only. Any clue to force the dynamic mapping to stick to the real relations addition/removal?
Thanks a lot for your answers !
Nicolas
I encountered a problem using traits in entities. For regular database values (scalar, DateTime) traits worked fine, but when I tried to define entity relations in traits the doctrine migrations bundle would convert the property to a varchar field.
The only way I could find to fix creating proper entity relation properties was by moving them out of the trait and into the entity class itself.
I have an entity with a custom id (i.e. UUID) generated on __construct function.
namespace AppBundle\Entity;
use Rhumsaa\Uuid\Uuid;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Person
{
/**
* #ORM\Id
* #ORM\Column(type="string")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
public function __construct()
{
$this->id = Uuid::uuid4()->toString();
}
This entity is used in sonata and also in other part of the project. I need this entity to have id before persisting and flushing it, so I can not use a an auto-increment.
So, the problem is sonata don't let me create entities because it takes the create option as and edit on executing because that entity already has an id, but this entity does not exists at this moment, so it fails.
The problem isn't the library for generating UUID, any value for 'id' fails.
Anyone know how to solve it? Another similar approach to solve the problem?
You shouldn't set your id in the constructor, but rather use the prePersist Doctrine event to alter your entity before persisting it for the first time.
You may use annotations to do so, see the Doctrine Documentation on prePersist.
The issue with setting the id in the constructor is that you may override it when you're retrieving it from the database, in which case it will be incorrect.
I have installed the FOSUserBundle and installed it as per its detailed installation guide (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md).
When i run php console doctrine:schema:update --force for the first time, it populates the users table with all of the default fields that the FOSUserBundle has defined.
Unfortunately it appears to be completely missing the fields which i have added to my user entity and i am wondering if its utilising the configuration file which is specified in the installation guide instead of using the annotations which are in the entity.
It also appears to be ignoring the other entities within the same Bundle.
namespace Acme\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer")
* #ORM\ManyToOne(targetEntity="Bureau", mappedBy="id")
*/
protected $bureau;
public function __construct() {
parent::__construct();
}
}
This is my user entity, of which bureau is being completely ignored regardless if it has a relationship or not.
Edit
As per requested, please find below the orm config file. It's the default file as per the configuration.
I have suspected this to be the problem, but i wasnt sure if annotations and the config file could work together.
Acme\UserBundle\Entity\User:
type: entity
table: users
id:
id:
type: integer
generator:
strategy: AUTO
Edit 2
I have found that if i remove the orm configuration file that it all magically works again!!
So i would adjust my question for clarity.
Updated question
If an orm configuration file exists, are annotations ignored?
When you generate entities with the console, you are asked on the format, which is:
xml
yaml
annotations
Regardless of what you choose, there are no signifiers telling Doctrine which to use besides the fact one exists. In order, YAML takes priority over annotations, and so it should.
So I'm trying to follow symfony2's tutorial on doctrine for my own website and modeling my User entity after their Product one.
Also, before anyone marks this a duplicate, I have already tried the solutions given in numerous other questions with no luck:
Not a valid entity or mapped super class
Doctrine class is not a valid entity or mapped super class
Symfony/Doctrine: Class is not a valid entity or mapped super class
symfony2 is not a valid entity or mapped super class
Symfony/Doctrine: Class is not a valid entity or mapped super class
"Class XXX is not a valid entity or mapped super class" after moving the class in the filesystem
and the list goes on
I have my entity class:
<?php
namespace MySite\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=100)
*/
protected $name;
/**
* #ORM\Column(type="string", length=64)
*/
protected $password;
}
?>
Now, I'm running the command:
$ php app/console doctrine:generate:entities MySite/MyBundle/Entity/User
to generate the accessor methods. However, when I do this, I get the error:
[Doctrine\ORM\Mapping\MappingException]
Class "MySite\MyBundle\Entity\User" is not a valid entity or mapped super class.
Ok, I figured it out myself. My problem is that my config.yml was wrong. I was missing the auto_mapping: true line in my config.yml.
doctrine:
# (dbal stuff here)
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
After adding that, everything auto-generates fine with the php app/console doctrine:generate:entities MySite/MyBundle/Entity/User line
I had a similar issue and I found at the end the problem in my case was I missed the class that extends Bundle
namespace Acme\TagBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeTagBundle extends Bundle
{
}
and declaring that class in AppKernel.php under the bundles array.
My problem was that I named the folder entity instead of Entity. When I fixed that it worked like a charm.
We're writing a custom CMS based on Symfony2 and are currently working on the user system. Our bundle has defined a BaseSiteUser that contains all the most common properties that a site may need for it's user data, and a SiteUser that extends BaseSiteUser and defines a table for the entity.
The idea was that for each individual project we'd overwrite the SiteUser entity by creating a more specific one in the new project's namespace, or use the default one if we don't specify a new one.
Our bundle architecture looks somewhat like this:
OurCompany
CMSBundle
Entities
BaseSiteUser.php
SiteUser.php
CustomerName
CustomerProjectBundle
CMSBundle
Entities
SiteUser.php
Our problem is that we can't build the model so that the SiteUser defined in CustomerName\CMSBundle is used instead of the one in OurCompany\CMSBundle. Instead, we get this error:
[Doctrine\DBAL\Schema\SchemaException]
The table with name 'siteuser' already exists.
We tried consulting the documentation, but that part has not been covered yet. Searching the web did not provide a solution, either.
We are using the annotation method for defining the model.
I have deleted my previous answer as it as wrong :). Just checked implementation of FOSUserBundle. They are using inheritance mapping. So in your core CMSBundle define BaseSiteUser as #MappedSuperclass and in your overridden bundle just extend BaseSiteUser.
I think this solution should work (pseudocode):
OurCompany
CMSBundle
Entities
/**
* BaseSiteUser
*
* #ORM\Entity(repositoryClass="OurCompany\CMSBundle\Repository\SiteUserRepository")
* #ORM\Table(name="siteuser")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="discr", type="string")
*
* DON'T USE EXPLICIT DISCRIMINATOR MAP (it will be generated automatically) !!!
* # ORM\DiscriminatorMap({"basesiteuser" = "BaseSiteUser", "siteuser" = "SiteUser"})
*/
BaseSiteUser.php
/**
* SiteUser
*
* #ORM\Table(name="siteuser")
*/
SiteUser.php => class SiteUser extends CustomerName\CMSBundle\Entities\SiteUserCustom
CustomerName
CustomerProjectBundle
CMSBundle
Entities
/**
* SiteUserCustom
*
* #ORM\Table(name="siteuser")
*/
SiteUserCustom.php => class SiteUserCustom extends OurCompany\CMSBundle\Entities\BaseSiteUser
Don't forget to register your bundles in AppKernel.php.
If you want to be able to define new fields in SiteUserCustom add your CustomerNameCMSbundle to the entity-manager configuration:
orm:
entity_managers:
default:
mappings:
OurCompanyCMSbundle: ~
CustomerNameCMSbundle: ~