问题
Little example about Books and Authors: DB structure:
Entities (they were generated form database using symfony2 console commands):
Author:
/**
* Author
*
* @ORM\Table(name="authors")
* @ORM\Entity
*/
class Author
{
private $_isCachable = true;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Books", mappedBy="author", cascade={"persist","remove","detach","merge","refresh"})
*/
private $book;
/**
* Constructor
*/
public function __construct()
{
$this->book = new \Doctrine\Common\Collections\ArrayCollection();
}
}
Book:
<?php
namespace App\CoreBundle\Entity;
use App\CoreBundle\RedisLayer\Marks\Insert;
use App\CoreBundle\RedisLayer\Marks\Update;
use Doctrine\ORM\Mapping as ORM;
/**
* Book
*
* @ORM\Table(name="books")
* @ORM\Entity
*/
class Book
{
private $_isCachable = true;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="ttile", type="string", length=255, nullable=false)
*/
private $ttile;
/**
* @var string
*
* @ORM\Column(name="isbn", type="string", length=255, nullable=false)
*/
private $isbn;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Authors", inversedBy="book", cascade={"persist","remove","detach","merge","refresh"})
* @ORM\JoinTable(name="author_books",
* joinColumns={
* @ORM\JoinColumn(name="book_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="author_id", referencedColumnName="id")
* }
* )
*/
private $author;
/**
* Constructor
*/
public function __construct()
{
$this->author = new \Doctrine\Common\Collections\ArrayCollection();
}
}
So when I run this code:
$book = new \App\CoreBundle\Entity\Book();
$book->setTtile('book title: '.uniqid());
$book->setIsbn('book isbn: '.uniqid());
$author = new \App\CoreBundle\Entity\Author();
$author->setName('author title: '.uniqid());
$author->addBook($book);
$entityManager->persist($author);
$entityManager->flush();
I expect doctrine to generate these SQLs:
"START TRANSACTION"]
# CREATE BOOK
INSERT INTO books (ttile, isbn) VALUES (?, ?)
array(2) {
[1] =>
string(25) "book title: 524ea3cf34d5f"
[2] =>
string(24) "book isbn: 524ea3cf34da3"
}
array(2) {
[1] =>
string(6) "string"
[2] =>
string(6) "string"
}
# CREATE AUTHOR
INSERT INTO authors (name) VALUES (?)
array(1) {
[1] =>
string(27) "author title: 524ea3cf34de9"
}
array(1) {
[1] =>
string(6) "string"
}
# CREATE LINKS
INSERT INTO author_books (book_id, author_id) VALUES (?, ?)
array(2) {
[0] =>
int(34)
[1] =>
int(23)
}
"COMMIT"
But i get only SQLs for #CERATE AUTHOR and #CREATE BOOK. SQL for linking table was not generated.
What is the problem?
If I run this code:
$book = new \App\CoreBundle\Entity\Book(); $book->setTtile('book title: '.uniqid()); $book->setIsbn('book isbn: '.uniqid()); $author = new \App\CoreBundle\Entity\Author(); $author->setName('author title: '.uniqid()); $author->addBook($book); $book->addAuthor($author); // added $entityManager->persist($author); $entityManager->flush();
all is OK. So I need to add book to author and author to book? Is it possible to create book and author and then and book to author and flush (without adding author to book) ?
If I use doctrine onFLush event listener I can use
getScheduledEntityUpdates
(list of entities that should be updated),getScheduledEntityInsertions
(list of entities that should be updated) andgetScheduledEntityDeletions
(list of entities that should be deleted) methods of the unitOfWork object. But this is only entities. How can I get info about linking table? I need to get SQL for linking table at doctrine onFlush event.
回答1:
You need to ensure that both Book:authors and Author:books have the proper values before persisting.
Specifically:
class Authors
{
public function addBook($book)
{
$this->books[] = $book;
$book->addAuthor($this);
}
Do the same on the Book entity.
BTW, change Books and Authors to Book and Author. Otherwise it will drive you crazy. You can keep the table names plural if you want.
====================================================
Question #3:
When doctrine creates a linking table then it hides it completely. What you need to do is to make your own BookAuthor entity and then set one to many relations from it to Book/Author. At that point you will have full access to it. You can also add additional properties if you want.
来源:https://stackoverflow.com/questions/19180219/doctrine-many-to-many-relations-and-onflush-event