I have a Entity with composite keys. See below:
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
*
*/
protected $bank;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
because Doctrine has some issues with composite keys it won't generates sequences (I'm working in PostgreSQL), how do I deal with this in order to generate $bank which is the PK?
If sounds like you don't want a composite key, just a primary key on $bank and a foreign key on $company. If that's the case,
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $bank;
/**
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
should do it.
Related
I'm creating my entities and I want to create an entity with two columns that need to have a specific constraint. If addressId is defined, then extAddressId can be null (and it has to be null).
/**
* #ORM\Entity()
* #ORM\Table(name="widgets")
*/
class Widget
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $addressId;
/**
* #ORM\Column(type="integer")
*/
private $extAddressId;
}
I know how to do it with SQL but not with doctrine.
CREATE TABLE widgets
(
id integer,
addressId integer,
extAddressId integer,
CONSTRAINT if_addressId_then_extAddressId_is_not_null
CHECK ( (NOT addressId) OR (extAddressId IS NOT NULL) )
);
According to the documentation you can add check constraints like this :
/**
* #ORM\Column(type="integer", options={"check":"[your check condition]"})
*/
private $addressId;
/**
* #ORM\Column(type="integer", options={"check":"[your check condition]"})
*/
private $extAddressId;
Haven't tested myself.
I have a Question entity with a property called code. I want to set the value of code equal to id on default with Doctrine annotations.
This is how I tried but I'm getting an error:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $code = $id;
Or:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer", options = {"default": $id})
*/
private $code;
Thanks.
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html
I don't know what is your need but maybe postPersist event is what you want :
postPersist - The postPersist event occurs for an entity after the
entity has been made persistent. It will be invoked after the database
insert operations. Generated primary key values are available in the
postPersist event.
Then in your entity :
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $code;
/** #PostPersist */
public function doStuffOnPostPersist()
{
$this->code = $this->id;
}
It is important to understand that your doctrine entity will have an ID only after having been persisted, thus after the post persist event.
I have related entities. Many to Many relation and the annotation exists on only one entity:
/**
* #ORM\ManyToMany(targetEntity="Event")
* #ORM\JoinTable(name="viewed_events",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="event_id", referencedColumnName="id")}
* )
**/
protected $viewedEvents;
The problem is when I try to delete Event entity I get Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails error. How do I solve this? I tried adding orphanRemoval=true like that: #ORM\ManyToMany(targetEntity="Event", orphanRemoval=true) and also tried adding cascade="delete" and cascade="all" instead with no success.
I give you one simple example so that you can work out what you need to add/change in your application.
Assume that there is a M-N relationship between Student and Course entities.
STUDENT
class Student
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="StudentCourse", mappedBy="studentInverse", cascade={"persist", "remove"})
*/
protected $studentInverse;
public function __construct()
{
$this->studentInverse = new \Doctrine\Common\Collections\ArrayCollection();
}
}
COURSE
class Course
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="StudentCourse", mappedBy="courseMap", cascade={"persist", "remove"})
*/
protected $courseInverse;
public function __construct()
{
$this->courseInverse = new \Doctrine\Common\Collections\ArrayCollection();
}
}
STUDENTCOURSE (this the one you're more interested in)
class StudentCourse
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Course", inversedBy="courseInverse")
* #ORM\JoinColumn(name="course", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $courseMap;
/**
* #ORM\ManyToOne(targetEntity="Student", inversedBy="studentInverse")
* #ORM\JoinColumn(name="student", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $studentMap;
}
onDelete="CASCADE"
On Yours JoinColumn.
I have three entities:
School
Schooltype
Branch
With following relation:
Schooltype to School (One to Many)
Schooltype to Branch (One to Many)
Branch to School (One to Many)
If i update my database structure "php app/console doctrine:schema:update --force" i receive following error message.
[Doctrine\DBAL\DBALException]
An exception occurred while executing 'ALTER TABLE school ADD CONSTRAINT FK_F99EDABBDCD6CC49 FOREIGN KEY (branch_id) REFERENCES schooltype_branch (id)':
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`ebm2`.`#sql-3cf_e6e`, CONSTRAINT `FK_F99EDABBDCD6CC49` FOREIGN KEY (`branch_id`) REFERENCES `schooltype_branch`
(`id`))
But i do not find my mistake, can somebody give me a hint for this issue?
I will also show some relevant parts of my three entities:
School:
class School implements BuildingInterface
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="SchoolType", inversedBy="schools")
* #ORM\JoinColumn(name="schooltype_id", referencedColumnName="id")
*/
protected $schooltype;
/**
* #ORM\ManyToOne(targetEntity="SchooltypeBranch", inversedBy="school")
* #ORM\JoinColumn(name="branch_id", referencedColumnName="id")
*/
protected $branch;
}
Schooltype:
class SchoolType implements BuildingTypeInterface
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\School", mappedBy="schooltype")
*/
protected $schools;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\SchooltypeBranch", mappedBy="schooltype")
*/
protected $branch;
}
Schooltype Branch:
class SchooltypeBranch
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="SchoolType", inversedBy="branch")
* #ORM\JoinColumn(name="schooltype_id", referencedColumnName="id")
*/
protected $schooltype;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\School", mappedBy="branch")
*/
protected $school;
}
Apparently a foreign key constraint is failing, like if school table has a branch_id not present in schooltype_branch table.
I have a form that shows entity:
class Event
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\OneToMany(targetEntity="EventAttendee", mappedBy="event", cascade={"all"})
*/
private $attendees;
}
and a collection within it:
class EventAttendee
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="Event", inversedBy="attendees")
* #ORM\JoinColumn(name="event_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $event;
/**
*
* #ORM\OneToOne(targetEntity="Employee")
* #ORM\JoinColumn(name="employee_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $employee;
}
If I delete an employee from the collection and add it again, I'm getting integrity constraint violation. This is because Doctrine's UnitOfWork first executes Inserts and then Deletes. Therefore, when it inserts a new record db still has the old one with the same employee.
Doctrine2 developers did not provide any working solution for Symfony2 users (here is the thread: http://www.doctrine-project.org/jira/browse/DDC-601).
And thus, I'm asking the question here: is it anyhow possible to avoid this issue?
EDIT:
My current workaround is:
find all not-persisted colletion items ready to insert
remove them from the collection and save to a variable
remove all the items that were really deleted in the form
call flush()
add all the items for insert back to the collection
call flush()
This works for me, however doesn't look good. Maybe someone has a better solution.