Reputation: 59
I’m currently discovering symfony 2 and training myself on this wonderful framework. So I have newbie questions...
I followed this tutorial in order to manage relations with doctrine : http://symfony.com/doc/current/book/doctrine.html
Well, during my tests I had a question and a problem.
First the question: Symphony best practices says that it’s better to use annotations for doctrine mapping instead of yaml in an other .orm.yml file. Good, I totally agree with that. "Using annotations is convenient and allows you to define everything in the same file". So if we choose to use annotations, I guess we do not need an .orm.yml mapping file anymore? Suppose I have a table named userType. I have created an entity class userType.php and added mapping information with annotations directly in this class. Anything I try, adding the statement:
use Doctrine\ORM\Mapping as ORM;
or not in my userType.php class, symfony display this error:
No mapping file found named 'UserType.orm.yml' for class 'AppBundle\Entity\UserType
if I don‘t create the UserType.orm.yml file.
So this my question: If we choose to use only annotations, do we still need an .orm.yml mapping file? If yes, what are the minimum information that we must put in this file?
Second point my problem: I have my users roles in a different table (userType) than the user table.
+-------------------------------------------+-------------------------------------------+
|user | userType |
|id username password userType_id | userType_id label role |
|1 testuser something 1 | 1 Administrator ROLE_ADMIN |
+-------------------------------------------+-------------------------------------------+
So I suppose I need to add a manyToOne relation in my user.php entity class (many users can have the only same one role).
So I added thoses lines in my User.orm.yml mapping file
(…)
manyToOne:
userType:
targetEntity: UserType
joinColumn:
name: userType_id
referencedColumnName: userType_id
lifecycleCallbacks: { }
(…)
And declared the var userType in my user.php entity class like this
/**
*
*/
private $userType;
This is my userType.php entity class file:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class UserType
{
/**
* @ORM\Id
* @ORM\Column(type="integer", name="userType_id")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string", name="label")
*/
private $label;
/**
* @ORM\Column(type="simple_array", name="role")
*/
private $role;
public function getId()
{
return $this->id;
}
/**
*
*/
public function getLabel()
{
return $this->label;
}
public function setLabel($label)
{
$this->label = $label;
}
/**
*
*/
public function getRole()
{
return $this->role;
}
public function setRole($role)
{
$this->role = $role;
}
}
And my UserType.orm.yml file:
AppBundle\Entity\UserType:
type: entity
table: userType
id:
id:
type: integer
id: true
column: userType_id
generator:
strategy: AUTO
fields:
label:
type: string
length: '150'
column: label
role:
type: simple_array
length: '100'
column: role
lifecycleCallbacks: { }
Ok it seems the $userType var of my user.php entity is an object containing the userType data. But if I do a
var_export($this->userType, true);
of the $userType object I got this :
Proxies\__CG__\AppBundle\Entity\UserType::
__set_state(array( '__initializer__' => Closure::
__set_state(array( )), '__cloner__' =>
Closure::__set_state(array( )), '__isInitialized__' =>
false, 'id' => 1, 'label' => NULL, 'role' => NULL, ))
Only the field id is filled others are NULL. How can I also get the label and role field values in the object $userType? What is my mistake?
Many thanks for your help.
Upvotes: 2
Views: 1266
Reputation: 59
Thanks for your advices. They helped me a lot.
I solved my 2 troubles.
For my .orm files problem : indeed as @chalasr advised, after deleting the Resources/config/doctrine folder, Symphony stopped showing me error regarding missing .orm files. By following @chalasr other tips I managed to stop using orm files. Thanks.
But I still had my other problem (only the "id "field was filled in the $userType object others where NULL). I notice that the $userType object was not initialized and that it was in fact a doctrine “lazy-loading-issue ».
These 2 posts helped me to solve my problem:
Get entities from a unidirectional many to many relation with Doctrine2 and Symfony2
doctrine2 association is not initialized
I added the option fetch="EAGER" to my ManyToOne relation and now all $userType object fields are perfectly filled.
This my actual ManyToOne relation (made with annotations ;-))
/**
* @ORM\ManyToOne(targetEntity="UserType", fetch="EAGER")
* @ORM\JoinColumn(name="users_types_id", referencedColumnName="users_types_id")
*/
private $userType;
And this how I get the role field value
/**
* Returns the roles or permissions granted to the user for security.
*/
public function getRoles()
{
$accessor_user_role = PropertyAccess::createPropertyAccessor();
$roles = $accessor_user_role->getValue($this->userType, 'role');
// guarantees that a user always has at least one role for security
if (empty($roles)) {
$roles[] = 'ROLE_USER';
}
return $roles;
}
I hope that I respect Symfony good practices by proceeding in this way.
Many thanks for your help.
Upvotes: 1
Reputation: 13167
No, you have to do a choice between this two formats.
There are many problems in your entity.
You have omitted the @ORM\Table
statement, use :
/**
* @ORM\Entity
* @ORM\Table(name="user_types")
*/
class UserType
{
//...
}
Then, you must rename your file corresponding to the name of the class it contains.
Your class is called UserType
but the file that contains it is named userType.php
.
You must use UserType.php
instead, according to the PSR-0 standards
Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.
[...]
The fully-qualified namespace and class is suffixed with .php when loading from the file system.
Example : App\AcmeBundle\Entity\User
will become src/App/AcmeBundle/Entity/User.php
Also, I think you are omitting a part of your namespace in the declaration of your entity, add the missing first part of your bundle namespace (as stated by PSR, it should be the name of the first folder between src
and your AppBundle
directories).
If you have begin to work with YAML before use annotations, do the following process :
Resources/config/doctrine
directory of your bundle (or just the mapping file corresponding to the entity).php app/console doctrine:cache:clear-metadata
php app/console cache:clear
After doing this, update your database schema with the correct mapping by doing :
php app/console doctrine:schema:update --force
Upvotes: 0