Symfony2 how to join on many-to-many relations using querybuilder? - php

Being new to symfony2 and querybuilder, I am trying to select all my containers but limiting the result to only those for which the logged-in user has access.
With the current code I get this error:
Notice: Undefined index: Container in /var/www/biztv_symfony/vendor/doctrine/lib/Doctrine/ORM/Query/SqlWalker.php line 746
Here is my attempt at the query (I have tried a couple of options from this and other forum sites and still can't seem to understand it right...)
public function indexAction()
{
//Get the requisits
$companyId = $this->container->get('security.context')->getToken()->getUser()->getCompany()->getId();
$em = $this->getDoctrine()->getEntityManager();
//Fetch the containers
$repository = $this->getDoctrine()->getRepository('BizTVContainerManagementBundle:Container');
$query = $repository->createQueryBuilder('c')
->innerJoin('c.users','u')
->where('c.company = :company')
->setParameter('company', $companyId)
->orderBy('c.name', 'ASC')
->getQuery();
$containers = $query->getResult();
I keep track of access with a many-to-many relation, this is my user entity...
<?php
// src/BizTV/UserBundle/Entity/User.php
namespace BizTV\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use BizTV\BackendBundle\Entity\company as company;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var object BizTV\BackendBundle\Entity\company
*
* #ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* #ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* #ORM\ManyToMany(targetEntity="BizTV\ContainerManagementBundle\Entity\Container", inversedBy="User")
* #ORM\JoinTable(name="access")
*/
private $access;
public function __construct()
{
parent::__construct();
$this->access = new \Doctrine\Common\Collections\ArrayCollection();
}
//getters and setters...
This is my container entity:
<?php
namespace BizTV\ContainerManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use BizTV\UserBundle\Entity\User as user;
/**
* BizTV\ContainerManagementBundle\Entity\Container
*
* #ORM\Table(name="container")
* #ORM\Entity
*/
class Container
{
/**
* #var integer $id
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $name
* #Assert\NotBlank(message = "Du måste ange ett namn för området")
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
//TODO: form handler assuring no name is used twice in same company
/**
* #var object BizTV\BackendBundle\Entity\company
*
* #ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* #ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* #ORM\ManyToMany(targetEntity="BizTV\UserBundle\Entity\User", mappedBy="Container")
*/
private $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}

In the Container entity, when you specify the $users property mapping, the value of mappedBy is important: you need to specify the name of the inverse property in the User class.
Here, we have, Container::$users <-> User::$access.
Change your annotations to:
class User
{
/**
* #ORM\ManyToMany(targetEntity="BizTV\ContainerManagementBundle\Entity\Container", inversedBy="users")
* #ORM\JoinTable(name="access")
*/
private $access;
}
class Container
{
/**
* #ORM\ManyToMany(targetEntity="BizTV\UserBundle\Entity\User", mappedBy="access")
*/
private $users;
}
I encourage you to read the doctrine orm documentation part about associations, and verify and fix this in all your associations.

Related

Class "App\Entities\Test" is not a valid entity or mapped super class. PHP, Doctrine

I catch this error
Class "App\Entities\Test" is not a valid entity or mapped super class
Path to entities is correct
Database's name is too correct. I have checked its about million times.
My entity:
namespace App\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Test
* #package App\Entities
* #ORM\Entity
* #ORM\Table(name="test")
*/
class Test
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer", name="id")
*/
protected int $id;
/**
* #ORM\Column(type="string", name="name")
*/
protected string $name;
/**
* #ORM\Column(type="string", name="pass")
*/
protected string $password;
//Getters and setters
}
Initialization:
$test = new Test();
$test->setName('name');
$test->setPassword('123');
$entityManager = $this->container->get(EntityManager::class);
$entityManager->persist($test);
$entityManager->flush();
Where is my mistake? I re-readed documentations many times, googled it

I'm struggling about a not working ManyToMany relationship in Symfony 2 with doctrine as ORM

Hi there and thanks ahead to anybody who will try to help.
I'm pretty new to Symfony and doctrine and I cannot figure out, why my ticket entity is stored without the ManyToMany Realtionship.
I tried very hard, did anything I found for some days but finally I need help.
Here we are
Ticket
<pre>
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use AppBundle\Entity\Computer;
/**
* #ORM\Entity
* #ORM\Table(name="tickets")
*/
class Ticket {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer")
*/
protected $creator;
/**
* #ORM\Column(type="integer")
*/
protected $owner;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="tickets")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="tickets")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
*/
protected $type;
/**
* #ORM\Column(type="string")
*/
protected $subject;
/**
* #ORM\ManyToMany(targetEntity="Computer", inversedBy="tickets", cascade={"persist"})
* #ORM\JoinTable(name="inventory_computer_join",
* joinColumns={#ORM\JoinColumn(name="ticket_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="computer_id", referencedColumnName="id")}
*)
*/
protected $computer;
[...]
/**
* Add computer
*
* #param \AppBundle\Entity\Computer $computer
*
* #return Ticket
*/
public function addComputer(\AppBundle\Entity\Computer $computer)
{
$this->computers[] = $computer;
return $this;
}
/**
* Remove computer
* #param \AppBundle\Entity\Computer $computer
*/
public function removeComputer(\AppBundle\Entity\Computer $computer)
{
$this->computers->removeElement($computer);
}
/**
* Get computers
* #return \Doctrine\Common\Collections\Collection
*/
public function getComputers()
{
return $this->computers;
}
}
</pre>
Computer
<pre>
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use AppBundle\Entity\Ticket;
/**
* #ORM\Entity
* #ORM\Table(name="inventory_computer")
*/
class Computer
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="Ticket", mappedBy="computer")
*/
protected $tickets;
[...]
/**
* Add ticket
*
* #param \AppBundle\Entity\Ticket $ticket
*
* #return Computer
*/
public function addTicket(\AppBundle\Entity\Ticket $ticket)
{
$this->tickets[] = $ticket;
return $this;
}
</pre>
Controller
<pre>
/**
* #Route("admint/createTicket", name="AdminTicketErstellen")
*/
public function AdminCreateTicketAction(Request $request) {
$ticket = new Ticket;
$form = $this->createForm(TicketType::class, $ticket, array(
'method' => 'GET'
));
$form->handleRequest($request);
if ($form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$em->persist($ticket);
$em->flush();
return $this->redirectToRoute('measure_servers');
}
return $this->render( 'sysadmin/pages/AdminCreateTicket.html.twig', array(
'ticket' => $form->createView(),
)
);
}
</pre>
If you want storage ManyToMany try it;
First:
Change protected $commputer; to protected $computers at Ticket.php entity.
Because, you using $this->computers at addComputer() or removeComputer() .
Second: * #ORM\ManyToMany(targetEntity="Ticket", mappedBy="computer") to mappedBy="computers" at Computer.php entity.
You can storage ticket with computer, try it at Controller:
$ticket = new Ticket();
$computer = new Computer();
$ticket->setCreator(4);
$ticket->setOwner(3);
$computer->addTicket($ticket);
$ticket->addComputer($computer);
$em = $this->getDoctrine()->getManager();
$em->persist($computer);
$em->persist($ticket);
$em->flush();

Call to undefined method, ArrayCollection

I'm new of Symfony, I made a web-application with it, in witch a User is in relation ManyToMany with an Entity "Mission". It doesn't work, because I get the error
FatalErrorException: Error: Call to undefined method
Acme\ManagementBundle\Entity\UserGroundStation::getMission()
Te getMission is defined in the MissionEntity, and called in the construct. Do I have to define it again? I don't understand.
My User is:
<?php
namespace Acme\ManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="user")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"user_one" = "UserGroundStation", "user_two" = "UserOperator"})
* #ORM\MappedSuperclass()
*
*/
abstract class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", mappedBy="users")
*/
protected $missions;
public function __construct(){
parent::__construct();
$this -> missions = new ArrayCollection();
}
public function setMissions(Collection $missions){
$this -> missions = $missions;
return $this;
}
public function addMission($mission){
$this -> missions -> add($mission);
return $this;
}
public function getMissions(){
return $this -> missions;
}
}
And the Mission Entity is:
/**
* #ORM\Entity
*/
class Mission {
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #var integer
*/
protected $id;
/**
* #ORM\Column(type="string", length=60)
* #var String
*/
protected $name;
/**
* #ORM\Column(type="string", length=600)
* #var String
*/
protected $description;
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\User", inversedBy="users")
*/
protected $users;
public function __construct(){
$this -> users = new ArrayCollection();
}
public function setUsers(Collection $users){
$this -> users = $users;
return $this;
}
public function addUser($user){
$this -> users -> add($user);
return $this;
}
public function getUsers(){
return $this -> users;
}
//setters and getters for id, name and description
}
How to solve this? Thank you
Either you have a typo:
getMission
instead of:
getMissions
Or you surely do not have that method declared in Mission entity, also the class you are calling the method from is not on the listing. Ensure it inherits from User.

Issue creating database tables using Symfony console

I'm trying to create the database tables using Symfony command's using the following line :
php app/console doctrine:schema:create
I obtain the following error :
[Doctrine\ORM\Mapping\MappingException]
No identifier/primary key specified for Entity "Cupon\CiudadBundle\Entity\Ciudad". Every Entity must have an identifier/primary key.
And it's the above class :
namespace Cupon\TiendaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class Tienda
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/** #ORM\ManyToOne(targetEntity="Cupon\CiudadBundle\Entity\Ciudad") */
protected $ciudad;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set ciudad
*
* #param \Cupon\CiudadBundle\Entity\Ciudad $ciudad
* #return Tienda
*/
public function setCiudad(\Cupon\CiudadBundle\Entity\Ciudad $ciudad = null)
{
$this->ciudad = $ciudad;
return $this;
}
/**
* Get ciudad
*
* #return \Cupon\CiudadBundle\Entity\Ciudad
*/
public function getCiudad()
{
return $this->ciudad;
}
public function __toString()
{
return $this->getNombre();
}
}
I don't understand whats really happen, because I put the ID for the class. Any help is appreciated.
Just check if the Ciudad Entity has an id
You should include the following annotations for example:
namespace Cupon\TiendaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity */
class Ciudad
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
//..

Different behaviour with slightly similar entity

I made a web application with Symfony2. There are 2 kind of user, a UserOperator and a UserGroundStation. Both of them extend User.
USER GROUND STATION
namespace Acme\ManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use PUGX\MultiUserBundle\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="user_GroundStation")
* #UniqueEntity(fields = "username", targetClass = "Acme\ManagementBundle\Entity\User",
message="Username already_used")
* #UniqueEntity(fields = "email", targetClass = "Acme\ManagementBundle\Entity\User",
message="Email already_used")
*/
class UserGroundStation extends User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=60)
* #var String
*/
protected $name;
/**
* #var float
*
* #ORM\Column(name="latitude", type="float")
*/
private $latitude;
/**
* #var float
*
* #ORM\Column(name="longitude", type="float")
*/
private $longitude;
/**
* Set latitude
*
* #param string $latitude
* #return UserGroundStation
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* Get latitude
*
* #return string
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* Set longitude
*
* #param float $longitude
* #return UserGroundStation
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* Get longitude
*
* #return float
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* #ORM\PrePersist
*/
public function setCreatedAtValue()
{
$this->addRole('ROLE_GS');
}
}
USER OPERATOR
namespace Acme\ManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use PUGX\MultiUserBundle\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="user_Operator")
* #UniqueEntity(fields = "username", targetClass = "Acme\ManagementBundle\Entity\User",
message="Username already_used")
* #UniqueEntity(fields = "email", targetClass = "Acme\ManagementBundle\Entity\User",
message="Email already_used")
*/
class UserOperator extends User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=60)
* #var String
*/
protected $name;
/**
* #ORM\PrePersist
*/
public function setCreatedAtValue()
{
$this->addRole('ROLE_OPERATOR');
}
}
They extend User.
When I call the registration page for UserOperator, it works, when I call registration page for UserGroundStation, Symfony alerts me:
Neither the property "mission" nor one of the methods "getMission()", "isMission()", "hasMission()", "__get()" exist and have public access in class "Acme\ManagementBundle\Entity\UserGroundStation".
How is it possible? Where can I find the error?
USER
namespace Acme\ManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* #ORM\Entity
* #ORM\Table(name="user")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"user_one" = "UserGroundStation", "user_two" = "UserOperator"})
* #ORM\MappedSuperclass()
*
*/
abstract class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="Acme\ManagementBundle\Entity\Mission", mappedBy="users")
*/
protected $missions;
public function __construct(){
$this -> missions = new ArrayCollection();
}
public function setMissions(Collection $missions){
$this -> missions = $missions;
return $this;
}
public function addMission($mission){
$this -> missions -> add($mission);
return $this;
}
public function getMissions(){
return $this -> missions;
}
It was really a dummy problem.
They have different FormType:
RegistrationUserOperatorFormType is different to RegistrationUserGroundStationFormType and
ProfileUserGroundStationFormType is different to ProfileUserOperatorFormType.

Categories