I'm trying to follow the example from this link to do a many to many relationship with an extra field with Doctrine 2 and Zend Framework 1. My code looks like this:
User Entity
class User
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $user_id;
/**
* #OneToMany(targetEntity="UserChannel", mappedBy="user")
*/
private $userChannel;
/**
* Entity constructor
*/
public function __construct()
{
$this->userChannel = new ArrayCollection();
}
--GETTERS AND SETTERS--
}
Channel Entity
class Channel
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $channel_id;
/**
* #OneToMany(targetEntity="Userchannel", mappedBy="channel")
*/
private $userChannel;
/**
* Entity constructor
*/
public function __construct()
{
$this->userChannel = new ArrayCollection();
}
--GETTERS AND SETTERS--
}
Relational UserChannel Entity:
class UserChannel
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/** #Column(name="channel_id", type="integer", length=11)
* #ManyToOne(targetEntity="Channel", inversedBy="userChannel")
* #JoinColumn(name="channel_id", referencedColumnName="channel_id")
*/
private $channel;
/** #Column(name="user_id", type="integer", length=11)
* #ManyToOne(targetEntity="User", inversedBy="userChannel")
* #JoinColumn(name="user_id", referencedColumnName="user_id")
*/
private $user;
/**
* Entity constructor
*/
public function __construct()
{
}
--GETTERS AND SETTERS--
}
Now, in my controller I have the following:
$user = $this->em->getRepository('Entities\User')->find(1);
$userChannel = $user->getUserChannel();
foreach($userChannel as $channel){
print_r($channel->getChannel());
}
I get two errors:
Notice: Undefined index: user in /Doctrine/ORM/Persisters/BasicEntityPersister.php on line 1396
Warning: Invalid argument supplied for foreach() in /Doctrine/ORM/Persisters/BasicEntityPersister.php on line 1401
**205**
But I still get the right channel id (the id in with the stars).
I have tried many things, but I still can't, by getting a User, get the Channel related to that User nor by getting the Channel, get the Users related to that channel. Am I using the relations correctly? Would really appreciate the help! Thanks!
Made same mistake myself when I was starting off with Doctrine.
You cannot mix Column and JoinColumn annotations. Try removing Column annotation from user and channel properties within UserChannel...
Related
I have to entity with manyToMany relation, that i have transform in two OneToMany. So I have create an other Entity called CollanaCollezionista into that i have some attribute.
I want that the couple collana/collezionista is unique, how can i do this on doctrine and symfony?
/**
* Collana
*/
class Collana
{
private $id;
private $titolo;
/**
* #MaxDepth(1)
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collana")
*/
private $collezionisti;
}
/**
* Collezionista
*/
class Collezionista
{
private $id;
private $user;
/**
* #ORM\OneToMany(targetEntity="CollezionistaCollana", mappedBy="collezionista")
*/
private $collane;
}
So I have an other entity, called CollezionistaCollana. How can i set that the couple collezionista-collana is unique?
Answer:
#UniqueConstraint do the stuff.
use Doctrine\ORM\Mapping\UniqueConstraint as UniqueConstraint;
/**
* CollezionistaCollana
*
* #ORM\Table(name="collezionista_collana",uniqueConstraints={#UniqueConstraint(name="unique_hold", columns={"idCollezionista", "idCollana"})})
* #ORM\Entity
*/
class CollezionistaCollana
{
// Class details
}
I got this error from my UserRepository:
[Semantical Error] line 0, col 51 near 'h': Error: Class DokMngr\Entity\User has no association named id
I understand that the error comes from the missing declaration inside my user entity. I can not find a correct syntax when a field is both a generated id and a OneToMany association.
Hope somebody can help me to solve my problem or at least explain why I can't use an id as an association.
class UserRepository extends EntityRepository
{
public function findAllwithHistoryCount() {
$qb = $this->createQueryBuilder('u')
->leftJoin('u.id', 'h');
return $qb->getQuery()->getResult();
}
}
/**
* #Entity(repositoryClass="DokMngr\Repository\UserRepository")
* #Table(name="users")
*/
class User implements UserInterface
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
}
/**
* #Entity(repositoryClass="DokMngr\Repository\HistoryRepository")
* #Table(name="history")
*/
class History
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #ManyToOne(targetEntity="User", inversedBy="id")
* #JoinColumn(name="user", referencedColumnName="id")
*/
protected $user;
}
Thanks to Olibiaz I found my error in reasoning.
I thought the whole time that I have to create an association between User.id and History.user like inside the database.
But instead I have to create a new field histories in my User entity. (which exactly not exist inside the database)
So here's the corrected entities:
User
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity(repositoryClass="DokMngr\Repository\UserRepository")
* #Table(name="users")
*/
class User implements UserInterface
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #OneToMany(targetEntity="History", mappedBy="user")
*/
private $histories;
}
History
/**
* #Entity(repositoryClass="DokMngr\Repository\HistoryRepository")
* #Table(name="history")
*/
class History
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #ManyToOne(targetEntity="User", inversedBy="histories")
* #JoinColumn(name="user", referencedColumnName="id")
*/
protected $user;
}
I am implementing SyliusRbacBundle along with FOSUserBundle, I set a secure area just to test if every thing is working but when I browse to that route I got a the following error:
CRITICAL - Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Warning: Invalid argument supplied for foreach()" at /home/daniel/web/tests/tmootb/vendor/sylius/rbac/Resolver/NestedSetRolesResolver.php line 48
When the user is created via FosUserBundle column 'authorization_roles' is filled with this information:
Doctrine\Common\Collections\ArrayCollection#00000000318556cb000000002fabcd7d
Not a big surprise I got that error, that's not an array or ArrayCollection as expected. So, I am not assigning the roles correctly but I am not sure how to do it upon user creation or user promotion. Here is how my User model looks like:
/**
* Class User
* #package App\AppBundle\Entity
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User extends BaseUser implements IdentityInterface
{
/**
* #var
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var
*
* #ORM\Column(type="string")
*/
private $authorizationRoles;
public function __construct()
{
parent::__construct();
$this->authorizationRoles = new ArrayCollection();
}
/**
* Get roles.
*
* #return RoleInterface[]
*/
public function getAuthorizationRoles()
{
return $this->authorizationRoles;
}
/**
* {#inheritdoc}
*/
public function addAuthorizationRole(RoleInterface $role)
{
if (!$this->hasAuthorizationRole($role)) {
$this->authorizationRoles->add($role);
}
}
/**
* {#inheritdoc}
*/
public function removeAuthorizationRole(RoleInterface $role)
{
if ($this->hasAuthorizationRole($role)) {
$this->authorizationRoles->removeElement($role);
}
}
/**
* {#inheritdoc}
*/
public function hasAuthorizationRole(RoleInterface $role)
{
return $this->authorizationRoles->contains($role);
}
/**
* {#inheritdoc}
*/
public function getRoles()
{
$roles = parent::getRoles();
foreach ($this->getAuthorizationRoles() as $role) {
$roles = array_merge($roles, $role->getSecurityRoles());
}
return $roles;
}
}
I had a look at how they do it here: https://github.com/Sylius/Sylius/blob/master/src/Sylius/Component/Core/Model/User.php
I am stuck there, any insight would be greatly appreciated.
Thanks!
Turn out that I wasn't adding the relationship properly, so I haven't had the intermediate table between users and roles. I added the annotations as follow:
/**
* #var
*
* #ORM\ManyToMany(targetEntity="Sylius\Component\Rbac\Model\RoleInterface")
* #ORM\JoinTable(name="sylius_user_role",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id", unique=true, nullable=false, onDelete="CASCADE")}
* )
*/
private $authorizationRoles;
Then updated the database, override the FOSUserBundle profile edit form, and everything is working now.
Solved by adding a conditional when adding a new entity to the database, it checks if the entity is not null... apparently there was null entities trying to get saved. Now the controller code looks like this:
...
$ciudades_id = explode(';', $this->getRequest()->getParam('ciudades_id'));
foreach($ciudades_id as $ciudad_id){
$ciudad = $this->_em->find("Application_Model_Ciudades", intval($ciudad_id));
if($ciudad!= null){
$carrera->getCiudad()->add($ciudad);
}
}
$instituciones_id = explode(';', $this->getRequest()->getParam('instituciones_id'));
foreach($instituciones_id as $institucion_id){
$institucion = $this->_em->find("Application_Model_Instituciones", intval($institucion_id));
if($institucion != null){
$carrera->getInstituciones()->add($institucion);
}
}
...
Thanks to the guys that helped at #doctrine IRC channel :)
This is my problem... I got an entity called "Carreras" (carreers) that has some associations, and the new carreers are added to the database with a web form. A carreer for me is a test, which has questions and other atttributes, and the user can select the cities and institutions that apply for that test.
So i'm getting this error when i try to save new data on the entity:
An error occurred
Application error
Exception information:
Message: A new entity was found through the relationship
'Application_Model_Carreras#ciudad' that was not configured
to cascade persist operations for entity: Doctrine\ORM\UnitOfWork#.
Explicitly persist the new entity or configure cascading persist
operations on the relationship. If you cannot find out which entity
causes the problem implement 'Application_Model_Ciudades#__toString()'
to get a clue.
This is the model for "Carreras"
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity
* #Table(name="carreras")
*/
class Application_Model_Carreras
{
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
/** #Column(type="string") */
private $nombre;
/**
* #ManyToMany(targetEntity="Application_Model_PruebasCarrera")
* #JoinTable(name="Carreras_PruebasCarrera",
* joinColumns={#JoinColumn(name="carreras_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="pruebascarrera_id", referencedColumnName="id")}
* )
*/
private $pruebas;
/** #Column(type="integer") */
private $valor;
/** #Column(type="date") */
private $fechainicio;
/** #Column(type="date") */
private $fechafin;
/**
* This association causes error
* #ManyToMany(targetEntity="Application_Model_Ciudades")
* #JoinTable(name="carrera_ciudades",
* joinColumns={#JoinColumn(name="carrera_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="ciudad_id", referencedColumnName="id")}
* )
*/
private $ciudad;
/**
* #ManyToMany(targetEntity="Application_Model_Instituciones")
* #JoinTable(name="carrera_instituciones",
* joinColumns={#JoinColumn(name="carrera_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="institucion_id", referencedColumnName="id")}
* )
*/
private $instituciones;
public function __construct()
{
$this->pruebas = new ArrayCollection();
$this->ciudad = new ArrayCollection();
$this->instituciones = new ArrayCollection();
}
public function setNombre($nombre){
$this->nombre = $nombre;
}
public function setValor($valor){
$this->valor = $valor;
}
public function setFechainicio($fechainicio){
$this->fechainicio = $fechainicio;
}
public function setFechafin($fechafin){
$this->fechafin = $fechafin;
}
public function getCiudad(){
return $this->ciudad;
}
public function getPruebas(){
return $this->pruebas;
}
public function getInstituciones(){
return $this->instituciones;
}
}
Now the action at controller:
/*
* This is an action for adding a new career
*/
public function agregarAction()
{
$formtest = new Admin_Form_AgregarCarrera();
$this->view->formtest = $formtest;
if ($this->getRequest()->isPost() && $this->view->formtest->isValid($this->_getAllParams()))
{
/*
* If the form is okay creating new Carreer model object
* This model has some attributes and three associations (for now)
* you can see them later in detail
*/
$carrera = new Application_Model_Carreras();
$carrera->setNombre($this->getRequest()->getParam("nombre"));
$carrera->setValor($this->getRequest()->getParam("valor"));
$carrera->setFechainicio(new \DateTime($this->getRequest()->getParam("fechainicio")));
$carrera->setFechafin(new \DateTime($this->getRequest()->getParam("fechafin")));
/*
* This is the first association. It's working fine (for now)
*/
$pruebas = $this->getRequest()->getParam("pruebas");
foreach($pruebas as $prueba){
if($prueba != '0'){
$tmp = $this->_em->find("Application_Model_PruebasCarrera", $prueba);
$carrera->getPruebas()->add($tmp);
}
}
/*
* This is the second associations, i'm getting the error with this one
*/
$ciudades_id = explode(';', $this->getRequest()->getParam('ciudades_id'));
foreach($ciudades_id as $ciudad_id){
$ciudad = $this->_em->find("Application_Model_Ciudades", intval($ciudad_id));
$carrera->getCiudad()->add($ciudad);
}
/*
* This is the third one. Nothing to say about this.
*/
$instituciones_id = explode(';', $this->getRequest()->getParam('instituciones_id'));
foreach($instituciones_id as $institucion_id){
$institucion = $this->_em->find("Application_Model_Instituciones", intval($institucion_id));
$carrera->getInstituciones()->add($institucion);
}
$this->_em->persist($carrera);
$this->_em->flush();
//$this->redirector->gotoSimpleAndExit('index','Carrera','admin');
}
}
Well i don't know what else to show... please comment if you can help me :)
--edit
I added cascade={"persist"} in the associations of the model "Carreras" and the error changed:
An error occurred
Application error
Exception information:
Message: Class Doctrine\ORM\UnitOfWork is not a
valid entity or mapped super class.
Now this is "Ciudades" model, it stores the cities available for the test and is associated with the institutions that exist on every city.
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity
* #Table(name="ciudades")
*/
class Application_Model_Ciudades {
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
/** #Column(type="string") */
private $ciudad;
/** #Column(type="string") */
private $departamento;
/** #Column(type="string") */
private $pais;
/**
* #ManyToMany(targetEntity="Application_Model_Instituciones")
* #JoinTable(name="Ciudades_Instituciones",
* joinColumns={#JoinColumn(name="ciudades_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="instituciones_id", referencedColumnName="id")}
* )
*/
private $instituciones;
public function __construct()
{
$this->instituciones = new ArrayCollection();
}
public function getCiudad(){
return $this->ciudad;
}
public function getId(){
return $this->id;
}
public function getInstituciones(){
return $this->instituciones;
}
}
Now this is "Instituciones" Model, it stores the institutions available for the tests.
/**
* #Entity
* #Table(name="instituciones")
*/
class Application_Model_Instituciones {
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
/** #Column(type="string") */
private $nombre;
public function getId(){
return $this->id;
}
public function getNombre(){
return $this->nombre;
}
}
Now this is "PruebasCarrera" Model, for me this model entity stores the questions of the tests, and every question can have a partner who supports the question:
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity
* #Table(name="pruebas_carrera")
*/
class Application_Model_PruebasCarrera extends Application_Model_PruebasBase{
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
/**
* #ManyToMany(targetEntity="Application_Model_Patrocinadores")
* #JoinTable(name="pruebascarrera_patrocinadores",
* joinColumns={#JoinColumn(name="pruebas_id", referencedColumnName="id", unique="true")},
* inverseJoinColumns={#JoinColumn(name="patrocinadores_id", referencedColumnName="id", unique=false)}
* )
*/
protected $patrocinadores;
/** #Column(type="string") */
private $respuesta;
public function __construct() {
$this->patrocinadores = new ArrayCollection();
}
public function setRespuesta($respuesta){
$this->respuesta = $respuesta;
}
public function getPatrocinadores(){
return $this->patrocinadores;
}
public function getId(){
return $this->id;
}
public function getRespuesta(){
return $this->respuesta;
}
}
Please show code of related entities:
Application_Model_Ciudades
Application_Model_PruebasCarrera
Application_Model_Instituciones
At this moment look https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associations.html#transitive-persistence-cascade-operations
At this moment i think you should add cascade={"persist"} to the Application_Model_Ciudades entity.
I have two entities one is Role and other is User , I want to build forms and reports to add and show each role with their users , and to create a user with one Role so its User:Role (One-To-Many), I managed to add role to a user via Doctrine 2 but I cannot show users fro each role below is my code
<?php
/**
* Description of Role
* #Entity
* #Table=(name"Roles")
* #author alaaqashou
*/
class Role {
//put your code here
/**
*
* #var integer $id
* #Column(name="id", type="integer",nullable=false)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #Column(length=100,nullable=false,unique=true)
* #var type
*/
private $name;
/**
* #OneToMany(targetEntity="User" ,mappedBy="Role")
* #var type
*/
private $users;
public function __construct() {
$this->users=new \Doctrine\Common\Collections\ArrayCollection();
}
public function getUsers() {
return $this->users;
}
public function setUsers($user) {
$this->users->add($user);
}
}
/**
* Description of User
*#Entity
* #Tabel(name="Users")
* #author alaaqashou
*/
class User {
//put your code here
/**
*
* #var integer $id
* #Column(name="id", type="integer",nullable=false)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
*
* #Column(length=255,nullable=false,unique=true)
*
*
* #var type
*
*/
private $role;
function __construct() {
$this->created=new \DateTime(date("Y-m-d H:i:s"));
}
public function getRole() {
return $this->role;
}
public function setRole($role) {
$this->role = $role;
}
}
I got the Notice: Undefined index: Role error when I try to do the following
my Service
public function listAllRole()
{
return $this->em->getRepository('sihha\Entity\Role')->findAll();
}
$roles=$this->roleService->listAllRole();
$users=$roles[0]->getUsers();
// I even tried $users=$roles[0]->getUsers()->toArray();
$user=$users[0];
Please Help!!!
I think your problem lies in the annotations. Try replacing mappedBy='Role' width mappedBy='role' (i.e. type "role" in lowercase).
I just tried mappedBy="Table" in one of my entities and it gave me the same result you seem to be having.