Symfony Annotations are not parsed - php

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.

Related

Symfony2: Custom identifier in Sonata entities

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.

Symfony/Doctrine class table inheritance and foreign key as primary key

I am currently designing a web application with Symfony 2.5 (and Doctrine 2.4.2) that has to be flexible to easily plug in new modules/bundles.
So I have an entity (let say A) that has two one-to-one associations with abstract classes (B and C). The future modules will implement one of the two abstract classes. Since the associations are one-to-one, I made them the ID of the abstract classes to ease the access to them when we know the ID of an instance of A
So here is what the code looks like:
class A:
<?php
namespace Me\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table()
* #ORM\Entity
*/
class A
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="B", cascade={"all"}, mappedBy="a")
* #ORM\JoinColumn(name="id", referencedColumnName="a_id")
*/
private $b;
/**
* #ORM\OneToOne(targetEntity="C", cascade={"all"}, mappedBy="a")
* #ORM\JoinColumn(name="id", referencedColumnName="a_id")
*/
private $c;
}
class B:
<?php
namespace Me\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table()
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
*/
abstract class B
{
/**
* #ORM\Id
* #ORM\OneToOne(targetEntity="A", inversedBy="b")
* #ORM\JoinColumn(name="a_id", referencedColumnName="id")
*/
private $a;
}
I will not post the code of the class C since it is the same as class B.
In my point of view, it seems all good. Even for the mapping verification command.
Indeed, when I execute php app/console doctrine:schema:validate, it tells me my schema is valid. However, this command then try to compare my schema to the schema in the database and it just fails at that point. php app/console doctrine:schema:update --dump-sql fails in the exact same way. So it is pretty embarrassing since it tells me my schema is valid but it cannot use it properly.
The error:
[ErrorException]
Warning: array_keys() expects parameter 1 to be array, null given in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php line 95
The error appears as soon as I add the InheritanceType and DiscriminatorColumn annotation to the classes B and C. Thing is that it tells me my schema is valid.
So does anyone have any clue if I am doing something wrong? Or is it definitely a bug in Doctrine? Do you have any other idea that would bring at least as much flexibility as my current solution?
Elioty
EDIT: I changed the owning side to be the abstract classes B and C since, accordingly to the doc, the owning side is the one with the foreign key and must use inversedBy attribute. Even with these changes, my schema is still valid and the same error still occurs.
EDIT2: If I create another field in B (and C) to hold the identity of the entity instead of the one-to-one association, the error disappears but it is no more like my valid schema.
EDIT3: I had a chat with a member of Doctrine's development team and (s)he told me it definitely looks like a bug. Bug report here.
First of all, the command php app/console doctrine:schema:validate checks the validity of the current schema. The current schema is the one generated by your last called to the command php app/console doctrine:schema:update --force
On the other hand the command php app/console doctrine:schema:update --dump-sql does not execute an actual update to the schema, though it may find some errors some others will not be come up...
I dont understand class B. The identity of this (abstract) class is a OneToOne relationship? Anyway, the thing is that Doctine will ignore the #ORD\Id if you don't add inheritanceType definitions. When you add this inheritanceType definition Doctrine will make attribute 'a' the primary key of B. Also it will create another attribute named 'a_id' which will serve as a foreign key for future subclasses (extends of B). But...relationships are not inherited.
Hope this helps...

FosUserBundle don't persist data in mongodb database

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

Overwriting entities from another bundle in Symfony2

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: ~

How to install the gedmo-extensions in Doctrine2?

i'm trying to install the "gedmo" behaviourial extensions (version 2.1.0-DEV) in Doctrine2 (version 2.1.3).
Without the extensions everything works fine. However, when I add the annotationdriver to read the #gedmo-annotations errors such as "Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class User2 is not a valid entity or mapped super class" are thrown.
This is de User2-entity:
<?php
use \Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class User2 {
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
private $id;
/** #ORM\Column(length=255) */
private $username;
}
Because these errors occur even in the Entities where #gemdo is not used i suspect it has something to do with the way the annotationdrivers are configured. In my bootstrap-file the annotation driver is added (i'm only going to use the tree-extension):
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$annotationDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader);
$chain = new \Doctrine\ORM\Mapping\Driver\DriverChain;
$chain->addDriver($annotationDriver, 'Gedmo\Tree\Entity');
$config->setMetadataDriverImpl($chain);
A few questions:
Should I add a driver for the ORM-annotation?
Is there something wrong with the User2-class?
How can I get a more specific user-error enabling me to find the exact cause of the problem?
In short: how can I make the #orm and #gedmo annotations work?
there was recently an example added in order to show how to configure bare entity manager with extensions whithout any framework used.
You can follow the readme at the bottom on how to setup it initially

Categories