Port a MySQL query to Doctrine - php

I'm trying to setup a one-to-many database, using Doctrine. One User, can have multiple Roles, and when I get the User, I want to get the associated Roles. I have a raw MySQL query that does that.
SELECT
u.*,
GROUP_CONCAT(r.role) as roles
FROM
users u
INNER JOIN user_roles ur ON ur.user_id = u.id
INNER JOIN roles r ON r.id = ur.role_id
GROUP BY id;
+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+
| id | username | email | password | is_active | GROUP_CONCAT(r.role) |
+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+
| 1 | admin | my#email.address | $2a$08$jHZj/wJfcVKlIwr5AvR78euJxYK7Ku5kURNhNx.7.CSIJ3Pq6LEPC | 1 | ROLE_USER,ROLE_ADMIN |
+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+
Is this something I can actually automatically replicate in Doctrine? And if so, where abouts am I going wrong? Here are my current (broken) classes (apologies for the code dump).
The error this is currently logging is:
[2016-12-20 12:01:35] security.INFO: Authentication request failed. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\Auth
enticationServiceException(code: 0): Notice: Undefined index: user at /var/www/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authe
ntication/Provider/DaoAuthenticationProvider.php:94, Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined in
dex: user at /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:1768)"} []
User.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements UserInterface, \Serializable
{
...
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="UserRoles", mappedBy="user", fetch="EAGER")
*/
private $roles;
public function __construct()
{
$this->isActive = true;
// may not be needed, see section on salt below
// $this->salt = md5(uniqid(null, true));
$this->roles = new ArrayCollection();
}
...
public function getRoles()
{
return $this->roles;
}
/**
* Add role
*
* #param \AppBundle\Entity\UserRoles $role
*
* #return User
*/
public function addRole(\AppBundle\Entity\UserRoles $role)
{
$this->roles[] = $role;
return $this;
}
/**
* Remove role
*
* #param \AppBundle\Entity\UserRoles $role
*/
public function removeRole(\AppBundle\Entity\UserRoles $role)
{
$this->roles->removeElement($role);
}
}
Role.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Role
*
* #ORM\Table(name="roles")
* #ORM\Entity(repositoryClass="AppBundle\Repository\RoleRepository")
*/
class Role
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="role", type="string", length=255, unique=true)
*/
private $role;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set role
*
* #param string $role
*
* #return Role
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return string
*/
public function getRole()
{
return $this->role;
}
}
UserRoles.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* UserRoles
*
* #ORM\Table(name="user_roles")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRolesRepository")
*/
class UserRoles
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="userroles")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $userId;
/**
* #var int
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Role")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
*/
private $roleId;
/**
* Set userId
*
* #param integer $userId
*
* #return UserRoles
*/
public function setUserId($userId)
{
$this->userId = $userId;
return $this;
}
/**
* Get userId
*
* #return int
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set roleId
*
* #param integer $roleId
*
* #return UserRoles
*/
public function setRoleId($roleId)
{
$this->roleId = $roleId;
return $this;
}
/**
* Get roleId
*
* #return int
*/
public function getRoleId()
{
return $this->roleId;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}

In the $roles association inside your User entity you set the mappedBy attribute to user, but your UserRoles entity does not have such a field. Instead it has a field called userId.
Doctrine tries to find the association using your mapping. The user value from your #mappedBy attribute cannot be found in the database, hence the error message:
Undefined index...
Since you are mapping objects you should reconsider the naming convention inside your UserRoles entity. So don't use $userId and $roleId but simply use User and Role and also set dependency injection and return values inside your setters and getters to match User and Role classes.
Since UserRoles is an entity (and not a collection) I would also suggest renaming it to UserRole (singular). It will help you understand what you have.
Start with changing your UserRoles like this:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\User;
use AppBundle\Entity\Role;
/**
* UserRole
*
* #ORM\Table(name="user_roles")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRoleRepository")
*/
class UserRole
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var User
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="userRoles")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #var Role
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Role")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
*/
private $role;
/**
* Set user
*
* #param User $user
* #return UserRole
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return User
*/
public function getUser()
{
return $this->user;
}
/**
* Set role
*
* #param Role $role
* #return UserRole
*/
public function setRole(Role $role)
{
$this->role = $role;
return $this;
}
/**
* Get role
*
* #return Role
*/
public function getRole()
{
return $this->role;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
And change your User entity to match these changes accordingly:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\UserRole;
use Serializable;
/**
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements UserInterface, Serializable
{
...
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="UserRole", mappedBy="user", fetch="EAGER")
*/
private $userRoles;
public function __construct()
{
$this->isActive = true;
// may not be needed, see section on salt below
// $this->salt = md5(uniqid(null, true));
$this->userRoles = new ArrayCollection();
}
...
/**
* #return Collection
*/
public function getUserRoles()
{
return $this->userRoles;
}
/**
* Add user role
*
* #param UserRole $userRole
*
* #return User
*/
public function addUserRole(UserRole $userRole)
{
$this->userRoles[] = $userRole;
return $this;
}
/**
* Remove role
*
* #param UserRole $userRole
*/
public function removeUserRole(UserRole $userRole)
{
$this->userRoles->removeElement($userRole);
}
}
Since your the repository for your User class is called UserRepository I also renamed UserRolesRepository to UserRoleRepository (singular).

Related

I can't get objects of related entity in Symfony3

I use Symfony 3.2. I have two related entities:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* #ORM\Table(name="user", options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"}, indexes={ #Index(name="idx_email", columns={"email"}) })
* #UniqueEntity(fields={"email"}, message="Пользователь с данным email'ом существует.", groups={"Registration"})
* #ORM\HasLifecycleCallbacks()
*/
class User
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\VisitedPage", mappedBy="user")
*/
private $visitedPages;
public function __construct()
{
$this->visitedPages = new ArrayCollection();
}
public function addVisitedPage(VisitedPage $visitedPage)
{
$this->visitedPages[] = $visitedPage;
return $this;
}
/**
* Remove visitedPage
*
* #param \AppBundle\Entity\VisitedPage $visitedPage
*/
public function removeVisitedPage(\AppBundle\Entity\VisitedPage $visitedPage)
{
$this->visitedPages->removeElement($visitedPage);
}
/**
* Get visitedPages
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getVisitedPages()
{
return $this->visitedPages;
}
}
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VisitedPage
*
* #ORM\Table(name="visited_page")
* #ORM\Entity(repositoryClass="AppBundle\Repository\VisitedPageRepository")
*/
class VisitedPage
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="visitedPages")
*/
private $user;
/**
* #var string
* #ORM\Column(name="page", type="text")
*/
private $page;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return VisitedPage
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set page
*
* #param string $page
*
* #return VisitedPage
*/
public function setPage($page)
{
$this->page = $page;
return $this;
}
/**
* Get page
*
* #return string
*/
public function getPage()
{
return $this->page;
}
}
When i try call VisitedPage::getUser() (i mean $visitedPage->getUser()) i get object type of user.
But when i call method User::getVisitedPages() i get null.
Method User::addVisitedPage($page) works and relations are saved.
How can i decide this problem?
//Some text to pass validation
When you add Visited Page from user try this:
class User
{
//......
public function addVisitedPage(VisitedPage $visitedPage)
{
$visitedPage->setUser($this);
$this->visitedPages->add($visitedPage);
return $this;
}
}
also I think you will need to add cascade={"persist"} to your private $visitedPages; inside of User object:
/**
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\VisitedPage", mappedBy="user", cascade={"persist"})
*/
private $visitedPages;
I fixed the issue by running this command - bin/console doctrine:cache:clear-metadata
You should run
php app/console cache:clear --env=prod
or
php app/console cache:clear --env=dev
depending upon env you are working

Embedded forms relations doctrine

in my symfony app, i'm using embedded forms. In my case, an object "CompetenceGroupe" can have multiple objects "CompetenceItem", but an object "CompetenceItem" belongs to only one object "CompetenceGroupe", so the relation is manyToOne.
The form work perfectly, and I have two tables (one for each entity), and it's well saved in the database.
But when I select an CompetenceGroupe object with doctrine in my controller, I have all informations of the object, and he's got an empty "competenceItems" property, so I can't retrieve the childs object (CompetenceItem).
My "CompetenceGroupe" entity :
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="competences_groupes")
*/
class CompetenceGroupe
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id_competence_groupe;
/**
* #var User $user
*
* #ORM\ManyToOne(targetEntity="User", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_user", referencedColumnName="id_user", nullable=false)
*/
private $user;
/**
* #ORM\Column(type="string", length=60, nullable=true)
*/
protected $titre;
protected $competence_items;
public function __construct()
{
$this->competence_items = new ArrayCollection();
}
public function getCompetenceItems()
{
return $this->competence_items;
}
/**
* Get idCompetenceGroupe
*
* #return integer
*/
public function getIdCompetenceGroupe()
{
return $this->id_competence_groupe;
}
/**
* Set titre
*
* #param string $titre
*
* #return CompetenceGroupe
*/
public function setTitre($titre)
{
$this->titre = $titre;
return $this;
}
/**
* Get titre
*
* #return string
*/
public function getTitre()
{
return $this->titre;
}
/**
* Set user
*
* #param \AppBundle\Entity\User $user
*
* #return CompetenceGroupe
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
public function addItem(CompetenceItem $item)
{
$this->competence_items->add($item);
}
public function removeItem(CompetenceItem $item)
{
// ...
}
/**
* Set competenceItems
*
* #param \AppBundle\Entity\CompetenceItem $competenceItems
*
* #return CompetenceGroupe
*/
public function setCompetenceItems(\AppBundle\Entity\CompetenceItem $competenceItems = null)
{
$this->competence_items = $competenceItems;
return $this;
}
}
And my "CompetenceItem" entity :
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="competences_items")
*/
class CompetenceItem
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id_competence_item;
/**
* #ORM\Column(type="string", length=60, nullable=false)
*/
protected $libelle;
/**
* #var CompetenceNiveau $niveau
*
* #ORM\ManyToOne(targetEntity="CompetenceNiveau", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_competence_niveau", referencedColumnName="id_competence_niveau", nullable=true)
*/
private $niveau;
/**
* #var CompetenceGroupe $competence_groupe
*
* #ORM\ManyToOne(targetEntity="CompetenceGroupe", cascade={"persist", "merge"})
* #ORM\JoinColumn(name="id_competence_groupe", referencedColumnName="id_competence_groupe", nullable=false)
*/
private $competence_groupe;
/**
* Get idCompetenceItem
*
* #return integer
*/
public function getIdCompetenceItem()
{
return $this->id_competence_item;
}
/**
* Set libelle
*
* #param string $libelle
*
* #return CompetenceItem
*/
public function setLibelle($libelle)
{
$this->libelle = $libelle;
return $this;
}
/**
* Get libelle
*
* #return string
*/
public function getLibelle()
{
return $this->libelle;
}
/**
* Set niveau
*
* #param \AppBundle\Entity\CompetenceNiveau $niveau
*
* #return CompetenceItem
*/
public function setNiveau(\AppBundle\Entity\CompetenceNiveau $niveau = null)
{
$this->niveau = $niveau;
return $this;
}
/**
* Get niveau
*
* #return \AppBundle\Entity\CompetenceNiveau
*/
public function getNiveau()
{
return $this->niveau;
}
/**
* Set competenceGroupe
*
* #param \AppBundle\Entity\CompetenceGroupe $competenceGroupe
*
* #return CompetenceItem
*/
public function setCompetenceGroupe(\AppBundle\Entity\CompetenceGroupe $competenceGroupe)
{
$this->competence_groupe = $competenceGroupe;
return $this;
}
/**
* Get competenceGroupe
*
* #return \AppBundle\Entity\CompetenceGroupe
*/
public function getCompetenceGroupe()
{
return $this->competence_groupe;
}
}
I think I have a missing annotation of the "competence_items" property in the CompetenceGroupe entity, but i'm really not sure ...
Thanks for your help !
A good practice may be to have a competence form, which would be call inside your competence group form
You may add a CollectionType as parrent and include query to search which competence already exist
There are some good example with post form type in symfony demo blog
Or you can use form events (onSubmit, preSubmit, etc...) to charge your entity with your required competence. This example show a message form which allow to choose friend from preset data, this is a good example.
You have tow choice , even to create a Many-To-One, Unidirectional , in this case , you need clean some code , take a look:
In CompetenceGroupe class :
class CompetenceGroupe
{
/**
* Many competence have One Group.
* #ManyToOne(targetEntity="CompetenceItem")
* #JoinColumn(name="id_competence_item", referencedColumnName="id_competence_item")
*/
protected $competence_items;
public function __construct()
{
// $this->competence_items = new ArrayCollection();
//delete that line
}
In CompetenceItem class :
class CompetenceItem
{
You need to delete private $competence_groupe; attribute with his annotation :
By this way, when you dump a CompetenceGroupe object you gonna find the competence items.
Also, you can do it with One-To-Many, Bidirectional ,if you want to get the data from the inverse side and from the owning side .
EDIT: If one competenceGroupe can have many competenceItems, then that is a OneToMany relationship; this is the inverse side of the relationship as defined by doctrine, but that is ok. Your question asked how to pull a competenceGroupe and retrieve all related competenceItems. You can do this by making the competenceItems an ArrayCollection in your CompetenceGroupe entity, just as you have done. You do have to define that further in the annotation, see (updated) code below.
For an ArrayCollection, you can remove your method setCompetenceItems and instead define a method addCompetenceItem in your CompetenceGroupe entity.
class CompetenceGroupe
{
/**
* #ORM\OneToMany(targetEntity="CompetenceItem", mappedBy="competence_groupe")
*/
protected $competenceItems;
public function __construct()
{
$this->competenceItems= new ArrayCollection();
}
/**
* Add competenceItem
*
* #param CompetenceItem $competenceItem
* #return CompetenceGroupe
*/
public function addCompetenceItem(CompetenceItem $competenceItem)
{
$this->competence_items->add($competenceItem);
return $this;
}
}
You'll also need to define the owning side to make all this work.

Symfony2.7 FOSUser save user and user info into different tables

Ok, so I am trying to save User to users table in my database and User info like name, surname to user_info table, using FosUserBundle what I have now is OneToOne bidirectional relation between these tables, form which save User and User info correctly but user_id in user_info table is always null I am trying to do this since 4 hours and now I have no idea what to do.
Edit:
I've managed it myself, didn't need bidirectional relation, will mark changes in files
Entity Users
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Entity\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Users
* #ORM\Entity(repositoryClass="AppBundle\Entity\UsersRepository")
* #ORM\Table()
* #ORM\Entity
*/
class Users extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
//don't need mappedBy option and that is whole relation statement
/**
* #ORM\OneToOne(targetEntity="UserInfo", //mappedBy="user", cascade={"persist","remove"})
*/
private $profil;
public function __construct(){
parent::__construct();
}
/**
* Set profil
*
* #param \AppBundle\Entity\UserInfo $profil
*
* #return Users
*/
public function setProfil(\AppBundle\Entity\UserInfo $profil = null)
{
$this->profil = $profil;
return $this;
}
/**
* Get profil
*
* #return \AppBundle\Entity\UserInfo
*/
public function getProfil()
{
return $this->profil;
}
}
UserInfo entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* UserInfo
*
* #ORM\Table()
* #ORM\Entity
*/
class UserInfo
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="user_name", type="string", length=255)
*/
private $userName;
/**
* #var string
* #ORM\Column(name="user_surname", type="string", length=255)
*/
private $userSurname;
/**
* #var integer
* #ORM\Column(name="blood_donated")
*/
private $bloodDonated;
/**
* Get id
*
* #return integer
*/
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set userName
*
* #param string $userName
*
* #return UserInfo
*/
public function setUserName($userName)
{
$this->userName = $userName;
return $this;
}
/**
* Get userName
*
* #return string
*/
public function getUserName()
{
return $this->userName;
}
/**
* Set userSurname
*
* #param string $userSurname
*
* #return UserInfo
*/
public function setUserSurname($userSurname)
{
$this->userSurname = $userSurname;
return $this;
}
/**
* Get userSurname
*
* #return string
*/
public function getUserSurname()
{
return $this->userSurname;
}
/**
* Set bloodDonated
*
* #param string $bloodDonated
*
* #return UserInfo
*/
public function setBloodDonated($bloodDonated)
{
$this->bloodDonated = $bloodDonated;
return $this;
}
/**
* Get bloodDonated
*
* #return string
*/
public function getBloodDonated()
{
return $this->bloodDonated;
}
}
And forms:
RegistrationFormType:
namespace UsersBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use AppBundle\Form\UserInfoType as UserInfoType;
class RegistrationFormType extends BaseType{
public function buildForm(FormBuilderInterface $builder, array $options){
parent::buildForm($builder, $options);
//adding profil hidden field to set profil in table, here whole magic happens at $builder -> add('profil','hidden')
$builder ->add('profil','hidden')
->add('profil', new UserInfoType(), array('data_class' => 'AppBundle\Entity\UserInfo'))
;
}
public function getName()
{
return 'my_user_registration';
}
}
and UserInfoType:
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserInfoType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('userName')
->add('userSurname')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\UserInfo'
));
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_userinfo';
}
}
Edit So I needed 2 changes actually add profil input to form and fix my relation between tables, hope it will help someone

Why setUserId method not work in entity symfony2?

Why my methid setUserId not work?
It's my Post entity:
<?php
// src/Acme/UserBundle/Entity/User.php
namespace Acme\PostBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="posts")
*/
class Post
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
*
* #ORM\Column(type="integer", nullable=false)
*/
public $user_id;
/**
* #ORM\ManyToOne(targetEntity="Acme\PostBundle\Entity\User", inversedBy="posts")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank(message="Введите текст")
* )
*/
protected $text;
/**
* #ORM\Column(type="string", length=255)
*/
protected $address;
/**
*
* #ORM\Column(type="datetime")
*/
protected $date;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set user_id
*
* #param integer $userId
* #return Post
*/
public function setUserId($userId)
{
$this->user_id = $userId;
return $this;
}
/**
* Get user_id
*
* #return integer
*/
public function getUserId()
{
return $this->user_id;
}
public function getText()
{
return $this->text;
}
public function __construct() {
$this->date = new \DateTime();
}
//...
}
And my User entity:
<?php
// src/Acme/UserBundle/Entity/User.php
namespace Acme\PostBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
*
* #ORM\Column(type="string")
*/
protected $path;
/**
*
* #ORM\Column(type="string")
*/
protected $username;
/**
* #ORM\OneToMany(targetEntity="Acme\PostBundle\Entity\Post", mappedBy="users")
*/
protected $posts;
public function __construct() {
$this->posts = new ArrayCollection();
}
}
I'm saving in the database via my controller:
public function createAction(Request $request)
{
$post = new Post();
$form = $this->createFormBuilder($post)
->add('text')
->add('address')
->getForm();
$post->setUserId($this->getUser()->getId());
$form->handleRequest($request);
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
}
return $this->redirect($this->generateUrl('home'));
}
And i throw this error:
Integrity constraint violation: 1048 Column 'user_id' cannot be null
Why? My $this->getUser()->getId() is not null, i tried return new Response($this->getUser()->getId()) and get my id
You dont need user_id field because you have user relation on field:
/**
* #ORM\ManyToOne(targetEntity="Acme\PostBundle\Entity\User", inversedBy="posts")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
Look in you database, doctrine already created user_id for you.
As the others stated its not possible to set $userId on its own if you have also defined an $user property as entity using the same database column.
Instead change your setters and keep everything else as it is:
class Post
{
// ...
/**
* Set user_id
*
* #param integer $userId
* #throws \Exception
*/
public function setUserId($userId)
{
throw new \Exception('Post->userId can not be set directly');
}
/**
* Set user
*
* #param User $user
* #return Post
*/
public function setUser($user)
{
$this->user = $user;
$this->user_id = $user->getId();
return $this;
}
// ...
}
Now the $userId is automatically updated when you use setUser(...).
Throwing an exception in setUserId helps you preventing bugs in your code. Of course you could also just delete the setter, but it then would be recreated everytime you run another doctrine:generate:entities for your post entity.

Symfony2\Doctrine - Retrieving User Roles

I'm trying to set up my User entity to use roles, and following the documentation at http://symfony.com/doc/current/cookbook/security/entity_provider.html
Users work fine, and if I hardcode the $roles value everything works as expected, log in/out is good, etc. But, if I try and retrieve the roles through a many-to-many relationship as outlined in the documentation I get back null.
I should also mention that after creating the entities when I ran 'php app/console doctrine:schema:update --force' it created the role table, but not the 'user_role' table as it said it would. I went ahead and created it manually and entered a row for the user I was testing with, but that was my first clue something wasn't working. It's really frustrating because I followed the documentation and it looks like it should work.
The error I get back while trying to log-in is:
FatalErrorException: Error: Call to a member function toArray() on a non-object
Which points to return $this->roles->toArray() in the user entity.
My User Entity (the relevant bits):
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ACME\MyBundle\Entity\UserRepository")
*
*/
class User implements UserInterface, \Serializable
{
...
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*
*/
private $roles;
...
/**
* Constructor
*/
public function __construct()
{
$this->roles = new ArrayCollection();
}
public function getRoles()
{
return $this->roles->toArray();
}
...
}
My Role Entity:
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="role")
* #ORM\Entity()
*/
class Role implements RoleInterface
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=30)
*/
private $name;
/**
* #ORM\Column(name="role", type="string", length=20, unique=true)
*/
private $role;
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="roles")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Role
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
* #return Role
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
}
Does anybody see a problem in my code or have experience with this same issue? I'm stuck at the moment.
In your entity Role you have
* #ORM\Table(name="role")
change it to
* #ORM\Table(name="user_role")
because your table name is user_role not role
I had the same probleme and i removed the toArray methode
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ACME\MyBundle\Entity\UserRepository")
*
*/
class User implements UserInterface, \Serializable
{
...
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*
*/
private $roles;
...
/**
* Constructor
*/
public function __construct()
{
$this->roles = new ArrayCollection();
}
public function getRoles()
{
return $this->roles;//return $this->roles->toArray();
}
...
}

Categories