How to modify Symfony ORM insert\update query - symfony

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 = '';

Related

Symfony/Doctrine: entity appears invalid / not shown. Why?

I have the following entity:
<?php
namespace App\Entity\Geo;
use Doctrine\ORM\Mapping as ORM;
/*
* #ORM\Entity(repositoryClass="App\Repository\Geo\CityRepository")
* #ORM\Table(name="geo_cities")
*/
class City
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
protected ?int $id = null;
/**
* Name of the city
*
* #ORM\Column(type="string", length=50, nullable=false)
*/
protected string $name;
/**
* Addition for name of city
*
* #ORM\Column(type="string", length=20, nullable=false)
*/
protected ?string $name_more = null;
// Setters and getters
}
This entity is considered as invalid in Symfony console.
When I execute php bin/console doctrine:mapping:info, it is not listed.
I tried to rename entity, the namespace, remove fields, add fields but in all cases, the entity is not valid.
Any idea ?
Note: I have another entity with same structure and it is valid for doctrine.
It's missing one * here
/*
* #ORM\Entity(repositoryClass="App\Repository\Geo\CityRepository")
* #ORM\Table(name="geo_cities")
*/

Error when persisting doctrine entity with OneToMany association

New entities in a collection using cascade persist will produce an Exception and rollback the flush() operation. The reason is that the "UserGroupPrivilege" entity has identity through a foreign entity "UserGroup".
But if the "UserGroupPrivilege" has its own identity with auto generated value the code works just fine, and I don't want that I want the identity to be a composite key to enforce validation. here is my code:
Entity UserGroup:
class UserGroup
{
/**
* #var integer
*
* #ORM\Column(type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(type="boolean", nullable=false)
* #Type("integer")
*/
private $active;
/**
* #ORM\OneToMany(targetEntity="UserGroupPrivilege", mappedBy="userGroup", cascade={"persist"})
*/
private $privileges;
Entity UserGroupPrivilege:
class UserGroupPrivilege
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer", nullable=false)
*
*/
private $privilegeId;
/**
* #var UserGroup
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="UserGroup", inversedBy="privileges")
* #ORM\JoinColumn(name="userGroupId", referencedColumnName="id")
*/
private $userGroup;
/**
* #var string
* #ORM\Column(type="string", nullable=false)
*/
private $name;
/**
* #var string
* #ORM\Column(type="string", nullable=false)
*/
private $value;
Controller:
$userGroup = new UserGroup();
$userGroupPrivilege = new UserGroupPrivilege();
userGroupPrivilege->setUserGroup($userGroup)
->setName($arrPrivilege['name'])
->setValue($arrPrivilege['value'])
->setPrivilegeId($arrPrivilege['privilegeId']);
$userGroup->addPrivilege($userGroupPrivilege);
$data = $repo->saveUserGroup($userGroup);
return $data;
Repository:
$em = $this->getEntityManager();
$em->persist($userGroup);
$em->flush();
I get the following error:
Entity of type UserGroupPrivilege has identity through a foreign entity UserGroup, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'UserGroupPrivilege'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.
Error message is pretty self explanatory. To relate UserGroupPrivilege to UserGroup, UserGroup must have it's ID set. However, since you've just created both entities it has no id because it hasn't been persisted to database yet.
In your case :
$em = $this->getEntityManager();
$em->persist($userGroup);
$em->persist($userGroupPrivilege);
$em->flush();
Can you "enforce validation" with unique constraint:
/**
* #Entity
* #Table(uniqueConstraints={#UniqueConstraint(name="ugppriv_idx", columns={"priviledgeId", "userGroup"})})
*/
class UserGroupPriviledge
{
...

Symfony2 Doctrine2 ManyToMany Composite key Column name referenced does not exist

I have a ManyToMany relation with a composite key on the reverse side.
When I use the console command doctrine:schema:update I have the following error:
[Doctrine\ORM\ORMException]
Column name `keyword` referenced for relation from Map\MapBundle\Entity\
Student towards Map\MapBundle\Entity\SkillType does not exist.
I have an entity student (unique key) with a ManyToMany relation with an entity skill (composite key) which has a ManyToOne relation with skillType (unique key).
Here is the different class mapping I have:
Class Student
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Student
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\StudentRepository")
*/
class Student {
/**
*
* #var integer #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Map\MapBundle\Entity\SkillType")
* #ORM\JoinTable(name="students_skills",
* joinColumns={
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword"),
* #ORM\JoinColumn(name="attribut", referencedColumnName="attribut")
* })
*/
private $skills;
}
Class skill
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Skill
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\SkillRepository")
*/
class Skill {
/**
* #ORM\ManyToOne(targetEntity="Map\MapBundle\Entity\skillType")
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword")
* #ORM\Id
*/
private $keyword;
}
Classe skillType
<?php
namespace Map\MapBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* SkillType
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Map\MapBundle\Entity\SkillTypeRepository")
*/
class SkillType {
/**
* #var string
*
* #ORM\Column(name="keyword", type="string", length=255)
* #ORM\Id
*/
private $keyword;
}
I tried to exchange the keyword and attribut #joinColumn lines, but I have the same error message with attribut instead of keyword.
I can't see what's wrong with my mapping. The table skill exists and has columns named keyword and attribut.
I hope that somebody will see where I made a mistake (probably a typo error like a missing character or a case mistake).
Thank you for your answer. It helped me a lot and i succeded doing the schema update.
Here is the code I finaly used
/**
* #ORM\ManyToMany(targetEntity="Carte\CarteBundle\Entity\Skill")
* #ORM\JoinTable(name="students_skills",
* joinColumns={#ORM\JoinColumn(name="student_id", referencedColumnName="id")},
* inverseJoinColumns={
* #ORM\JoinColumn(name="keyword", referencedColumnName="keyword"),
* #ORM\JoinColumn(name="attribut", referencedColumnName="attribut")
* })
*/
private $skills;
You write that you want Student to have the many-to-many relation with Skill, but you connected it with SkillType instead. And you're missing the inverseJoinColumns property and you didn't referenced Student properly.
Try the following annotation (untested and after looking at the documentation):
/**
* #ORM\ManyToMany(targetEntity="Map\MapBundle\Entity\Skill")
* #ORM\JoinTable(name="students_skills",
* joinColumns={#ORM\JoinColumn(name="student_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="skill_keyword", referencedColumnName="keyword")}
* )
*/
private $skills;

Use foreign keys as where argument in Symfony/Doctrine

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);
;

Symfony2 Doctrine2 column being set to null

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

Resources