I'm pretty new to symfony/Doctrine and having some problems with querybuilder:
Given this ER:
And following declaration:
namespace xxx\SeoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* xxx\SeoBundle\Entity\Session
*
* #ORM\Table(name="session")
* #ORM\Entity
*/
class Session
{
const repositoryName = "InternetSmSeoBundle:Session";
/**
* #var string $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
*/
private $id;
......
/**
* #var Gsite
*
* #ORM\ManyToOne(targetEntity="Gsite")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="gsite_id", referencedColumnName="id")
* })
*/
private $site;
......
}
I need to find sessions which filtering them by site.
I've tried following approach:
$rep = $this->em->getRepository(Session::repositoryName);
$qb = $rep->createQueryBuilder("s");
$qb->setMaxResults(200);
$qb->where("1=1");
$qb->orderBy("time", "desc");
//site
if ($params->site != null){
/** #var Gsite **/
$site = $params->site;
$qb->where($qb->expr()->eq("gsite_id",$site->getId()));
}
Or even
$qb->where($qb->expr()->eq("site",$site));
But it doesn't work. What is correct way to filter data in presence of Many To One foreign keys? Do I need to create declaration of gsite_id column in my Model?
Thanks.
Set the parameter, Doctrine will be able to infer the type (no need to use the foreign key id):
$qb
->where($qb->expr()->eq('site', ':site'))
->setParameter('site', $site);
;
Related
I have project that is migrate to Symfony, that project have multiple tables,and also some tables are migrated to ORM, but now i need to incert/update from Symfony to table that have Entity but not managed by ORM. Problem consist in not null columns that require some value and in Entity I cannot define that value because of table relations.
It posible to edit MySql query before they submited to Database.
For example i have Entity:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="p_user")
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User
{
/**
* #var int
*
* #ORM\Column(name="user_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string|null
*
* #ORM\Column(name="name", type="string", length=55, nullable=true)
*/
private $name;
/**
* #var Permission
*
* #ORM\ManyToOne(targetEntity="Permission", inversedBy="user", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="permission_id", referencedColumnName="permission_id", onDelete="CASCADE")
*/
private $permission;
}
permission_id can be null but in database is not null with default value 0, same for name but with default value ''.
That mean when I make flush, ORM execute INSERT INTO p_user (name, permission_id) VALUES ('name', null), but I want also to execute INSERT INTO p_user (name) VALUES ('name').
It's possible to do that I wanted.
To achieve this you can provide default values.
private $permission = 0;
private $name = '';
I have a database with 3 tables, Equipment, transaction and transactionReceive. In the future there will be multiple transactionXYZ, one for each type of transaction. I used a joined inheritance to link transactionReceive with transaction. I also use a Many to one association between Equipment and transaction, since a piece of equipment can have multiple transactions.
I am currently working on adding a piece of equipment. This is a two step process. It should:
1: Create the piece of equipment
2: Create the transaction/transactionReceive
My issue is that when I try to set the equipmentId to persist the transaction, it throws an exception saying it is null.
My code is as follow:
$em->persist($equipmentData);
$em->flush();
$trans = new TransactionReceive();
$trans->setEquipmentId($equipmentData->getId());
//Here I set all transactions info
$em->persist($trans);
$em->flush();
Thanks
EDIT:
Apparently my issue would be related to the insert with the ManyToOne association. I noticed it because I get the same error even if I hardcode a value for the equipmentId in the transaction.
EDIT 2:
Transaction entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Transaction
*
* #ORM\Table(name="transaction")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TransactionRepository")
*
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="transactionType", type="string")
* ORM\#DiscriminatorMap({
* "receive" = "TransactionReceive",
* "changeout" = "TransactionChangeoutWheelset",
* })
*/
class Transaction
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
* #ORM\ManyToOne(targetEntity="Equipment")
* #ORM\Column(name="equipmentId", type="integer")
*/
private $equipmentId;
/**
* #return int
*/
public function getequipmentId()
{
return $this->equipmentId;
}
/**
* #param int $equipmentId
*
* #return self
*/
public function setEquipmentId($equipmentId)
{
$this->equipmentId= $equipmentId;
return $this;
}
// Other attributes, getters and setters
TransactionReceive entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\Transaction;
/**
* TransactionReceive
*
* #ORM\Table(name="transaction_receive")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TransactionReceiveRepository")
*/
class TransactionReceive extends Transaction
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
*
* #ORM\Column(name="gsThickness", type="integer")
*/
private $gsThickness;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set gsThickness
*
* #param integer $gsThickness
*
* #return TransactionReceive
*/
public function setGsThickness($gsThickness)
{
$this->gsThickness = $gsThickness;
return $this;
}
/**
* Get gsThickness
*
* #return int
*/
public function getGsThickness()
{
return $this->gsThickness;
}
}
Since your equipementId proprety is a foreign key, you need to set it to an object equipement, not only it's Id.
Replacing the line $trans->setEquipmentId($equipmentData->getId()); by
$trans->setEquipmentId($equipmentData);
should do the trick for you.
I updated my entity file to include relationship mapping.
Persist worked before the update now it doesn't.
Maybe it's something I forgot to do.
namespace classes\classBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* advisersplans
*
* #ORM\Table()
* #ORM\Entity
*/
class advisersPlans
{
/**
*
* #ORM\ManyToOne(targetEntity="plans", inversedBy="adviserPlans")
* #ORM\JoinColumn(name="planid", referencedColumnName="id")
*/
public $plan;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #var integer
*
* #ORM\Column(name="userid", type="integer")
*
*
*/
public $userid;
/**
* #var integer
*
* #ORM\Column(name="adviserid", type="integer")
*
*
*/
public $adviserid;
/**
* #var integer
*
* #ORM\Column(name="planid", type="integer")
*
*
*/
public $planid;
/**
* #var string
*
* #ORM\Column(name="participantLoginWebsiteAddress", type="string", length=255)
*/
public $participantLoginWebsiteAddress;
public function __construct()
{
$class_vars = get_class_vars(get_class($this));
foreach ($class_vars as $key => $value)
{
if ($key != "plan")
$this->$key = "";
}
}
}
Perist returns error saying planid is null. If I remove the following it works.
/**
*
* #ORM\ManyToOne(targetEntity="plans", inversedBy="adviserPlans")
* #ORM\JoinColumn(name="planid", referencedColumnName="id")
*/
Here is my code while persisting.
$adviserPlan = new advisersPlans();
$adviserPlan->planid = $planid;
$adviserPlan->userid = $this->userid();
$adviserPlan->adviserid = $session->get("editadviserid");
$em->persist($adviserPlan);
Am I supposed to populate the plan field and not the planid field or is my entity file coded wrong.
You shouldn't set ids. You should set entities:
$adviserPlan = new advisersPlans();
// You should retrieve the plan before doing this, of course.
$adviserPlan->setPlan($plan);
$plans->addAdviserPlan(§adviserPlan);
$em->persist($adviserPlan);
The methods for adding an entity to a collection should be generated by doctrine when you run:
php app/console doctrine:generate:entities YourBundle
I'm new to Symfony2 + Doctrine and I´m looking for a way to validate the uniqueness in an Arraycollection. May be it is already answered question but I can´t figure how resolve it.
I`ve a Relevamientosserviciosprestador class with a Callback:
namespace Prestadores\PrincipalBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\ExecutionContext;
/**
* Prestadores\PrincipalBundle\Entity\Relevamientosserviciosprestador
*
* #ORM\Table(name="relevServiciosPrestador")
* #ORM\Entity(repositoryClass="Prestadores\PrincipalBundle\Repository\RelevamientosserviciosprestadorRepository")*
* #Assert\Callback(methods={"sonUnicosLosTiposDeReclamoq"})
*/
class Relevamientosserviciosprestador
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
....
....
/**
* #ORM\OneToMany(targetEntity="Atencionusuarioreclamo", mappedBy="relevamiento_id", cascade={"persist"})
* #Assert\Valid
*/
private $reclamos;
....
....
public function __construct()
{
$this->personal = new ArrayCollection();
$this->reclamos = new ArrayCollection();
}
....
....
/*Acá intentaremos validar si los tipos de reclamo que se están cargando son únicos para ese relevamiento*/
public function sonUnicosLosTiposDeReclamoq(ExecutionContext $context)
{
foreach ($this->reclamos as $reclamo){
/*Here, I get all entities, not only those related to a Relevamientosserviciosprestador*/
var_dump($reclamo->gettiporeclamo()->getnombre());
}
}
}
And the Atencionusuarioreclamo entity:
namespace Prestadores\PrincipalBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Prestadores\PrincipalBundle\Entity\Atencionusuarioreclamo
*
* #ORM\Table(name="atencionUsuarioReclamo")
* #ORM\Entity
*/
class Atencionusuarioreclamo
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var Atencionusuariosede
*
* #ORM\ManyToOne(targetEntity="Atencionusuariosede")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="nroSede", referencedColumnName="id")
* })
*/
private $nrosede;
/**
* #var relevamiento_id
*
* #ORM\ManyToOne(targetEntity="Relevamientosserviciosprestador")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="relevamiento_id", referencedColumnName="id")
* })
*/
private $relevamiento_id;
/**
* #var Prmreclamotipo
*
* #ORM\ManyToOne(targetEntity="Prmreclamotipo")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="tipoReclamo", referencedColumnName="id")
* })
* #Assert\NotBlank()
*/
private $tiporeclamo;
....
....
....
....
}
I want to chek uniqueness of tiporeclamo in a given sede and relevamiento_id
I create or edit a Relevamientosserviciosprestador using a Form which has a sub form collection for "Atencionusuarioreclamo" entities. On submit, the callback for Relevamientosserviciosprestador executes but $this->reclamos has all saved entities not only those related to the Relevamientosserviciosprestador what I´m editing.
Is this the expected behauvoir or I`m missing something?
I´ve also tested the approach mentioned in How to validate unique entities in an entity collection in symfony2
but, again, it checks all entities.
I´ve also read Doctrine2 ArrayCollection but I cant´t understand if it resolve the problem.
Please, can you tell me how do you manage uniqueness in your ArrayCollection before persist it?
I´m sorry for my poor english
Thanks in advance
Ivan
php's array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
combined with ArrayCollection->toArray() and ArrayCollection->__construct()
In your case:
$Atencionusuarioreclamo =
new ArrayCollection(array_unique($Atencionusuarioreclamo->toArray());
I have a system that took form information detailing a project, added it to a project table and is meant to add an entry into an assigned projects table to associate user with project (point of this is allowing multiple users for each project). Anyway I got this working without foreign keys, struggled to add them but eventually got them.
Unfortunately this additional has caused this error 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'projectId' cannot be null' whenever something is added to the assignedProjects table.
So my question is, have I missed something in my codes?
The code to add a new row to assignedProjects:
$assignedProject = new AssignedProjects();
$assignedProject->setProjectId($project->getId());
$assignedProject->setUserId($user[0]['id']);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
The code for the assignProjects entity:
class AssignedProjects
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer $projectId
*
* #ORM\Column(name="projectId", type="integer")
*/
private $projectId;
/**
* #ORM\ManyToOne(targetEntity="Projects", inversedBy="assignment")
* #ORM\JoinColumn(name="projectId", referencedColumnName="id")
*/
private $project;
/**
* #var integer $UserId
*
* #ORM\Column(name="userId", type="integer")
*/
private $userId;
/**
* #ORM\ManyToOne(targetEntity="Dev\UserBundle\Entity\User", inversedBy="assignment")
* #ORM\JoinColumn(name="userId", referencedColumnName="id")
*/
private $user;
(followed by the usual getters and setters)
and the project tables entity is:
class Projects
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $projectName
*
* #ORM\Column(name="projectName", type="string", length=255)
*/
private $projectName;
/**
* #ORM\OneToMany(targetEntity="AssignedProjects", mappedBy="project")
*/
protected $assignment;
Any help would be much appreciated!
Either you use the ProjectId and UserId columns and manage the relationship manually (not recommended) or you use the doctrine relationships(recommended), but don´t do both things. If you go for the second option, don´t include the projectId and userId columns, they are automatically created for you by doctrine. So, your AssignedProjects class should be:
class AssignedProjects {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id * #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Projects", inversedBy="assignment")
* #ORM\JoinColumn(name="projectId", referencedColumnName="id")
*/
private $project;
/**
* #ORM\ManyToOne(targetEntity="Dev\UserBundle\Entity\User", inversedBy="assignment")
* #ORM\JoinColumn(name="userId", referencedColumnName="id")
*/
private $user;
and in your controller you would do:
$assignedProject = new AssignedProjects();
$assignedProject->setProject($project);
$assignedProject->setUser($user[0]);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
Note that I am setting the Project and User fields, not the ids
By the way, unless you need to save extra data about this project assignement (things like the date or similar), you can declare a direct ManyToMany relationship between User and Project and do away with this class, Doctrine would generate the needed table by itself
With Doctrine2, you don't have to declare the foreign key (projectId) but only the association (project). So you can delete $projectId property, as well as setProjectId ans getProjectId methods. Same fix for $user...
Instead, you will use setProject like that :
$assignedProject = new AssignedProjects();
$assignedProject->setProject($project);
$assignedProject->setUser($user[0]);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
Have a look to Doctrine2 documentation, it will help you, for sure !
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/association-mapping.html