我正在使用具有 onDelete: 'cascade' 的关系来解决一个奇怪的问题。 简而言之,我删除了父对象,级联在数据库中工作正常,也删除了子对象。 然后,如果我再次通过entityManager->find()读取对象,则无法找到父实体,而ORM会找到子实体,即使数据库中没有这样的对象。
我真的很感激任何想法,因为我已经尝试了很多不同的事情,但没有运气......但我想我没有发现一些明显的错误。
这是我的代码:
<?php
require_once "bootstrap.php";
// create objects
$s1 = new Shelf();
$s1->setCategory("Science fiction");
$entityManager->persist($s1);
$b1 = new Book();
$b1->setAuthor("Isaac Asimov");
$b1->setTitle("End of Eternity");
$b1->setShelf($s1);
$entityManager->persist($b1);
$entityManager->flush();
$shelfId = $s1->getId();
$bookId = $b1->getId();
// delete objects
$entityManager->remove($s1);
$entityManager->flush();
// --> this deletes on the DB both the shelf and the book
// read the objects again
$shelfAfterDel = $entityManager->find(Shelf::class, $shelfId);
$bookAfterDel = $entityManager->find(Book::class, $bookId);
echo "shelf: " . ($shelfAfterDel!=null? $shelfAfterDel->getCategory() : "null") . "\n";
// --> this prints 'null' (OK)
echo "book: " . ($bookAfterDel!=null? $bookAfterDel->getTitle() : "null") . "\n";
// --> this prints 'End of Eternity' (NOT OK)
货架.php
<?php
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
#[ORM\Entity]
#[ORM\Table(name: 'shelf')]
class Shelf
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private string $category;
#[ORM\OneToMany(targetEntity: Book::class, mappedBy: 'shelf')]
private Collection $books;
public function __construct()
{
$this->books = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getCategory(): string
{
return $this->category;
}
public function setCategory(string $category): void
{
$this->category = $category;
}
public function addBook(Book $book): void
{
$this->books[] = $book;
}
}
Book.php
<?php
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'book')]
class Book
{
#[ORM\Id]
#[ORM\Column]
#[ORM\GeneratedValue]
private ?int $id = null;
#[ORM\Column]
private string $author;
#[ORM\Column]
private string $title;
#[ORM\ManyToOne(targetEntity: Shelf::class, inversedBy: 'books')]
#[ORM\JoinColumn(onDelete: 'CASCADE', nullable: false)]
private Shelf $shelf;
public function setShelf(Shelf $shelf): void
{
$this->shelf = $shelf;
}
public function getShelf(): Shelf
{
return $this->shelf;
}
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): string
{
return $this->author;
}
public function setAuthor(string $author): void
{
$this->author = $author;
}
public function setTitle($title): void
{
$this->title = $title;
}
public function getTitle():string
{
return $this->title;
}
}
bootstrap.php
require_once "vendor/autoload.php";
$config = ORMSetup::createAttributeMetadataConfiguration(
paths: [__DIR__ . '/src'],
isDevMode: true,
);
$connection = DriverManager::getConnection([
'driver' => 'pdo_mysql',
'host' => '127.0.0.1',
'port' => '3306',
'user' => 'root',
'password' => 'XXXXXX',
'dbname' => 'phpunit',
], $config);
$entityManager = new EntityManager($connection, $config);
composer.json
{
"require": {
"php": ">=8.0.0",
"monolog/monolog": "^3.8",
"doctrine/orm": "^3",
"doctrine/dbal": "^4",
"symfony/cache": "^7"
},
"autoload": {
"psr-4": {
"": "src/"
}
},
"archive": {
"exclude": [
"vendor",
".DS_Store",
"*.log"
]
}
}
通常 Doctrine 不知道刷新后数据库级别发生了什么,因为实体是在内存中管理的,调用
$entityManager->clear();
通过清除身份映射来解决此问题,强制 Doctrine 从数据库中获取新数据以进行后续操作。
https://stackoverflow.com/a/59970767/16742310