我正在尝试清除实体集合。这是我的关系方案:
Game <-> GameQuest[]
Player <-> PlayerGameQuestLink[]
PlayerGameQuestLink 实体具有一些关于每个玩家的任务何时激活、完成等的元数据。 Player 侧的级联未设置。
这是我的关系的定义方式:
/**
* @ORM\OneToMany(targetEntity="App\Entity\PlayerGameQuestLink", mappedBy="player")
*/
private $gameQuestLinks;
这是我的
PlayerGameQuestLink
类,没有 getter 和 setter:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="player_retailer_game_quest_link")
*/
class PlayerRetailerGameQuestLink
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private int $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\PlayerRetailer", inversedBy="gameQuestLinks")
*/
private $player;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\GameQuest")
*/
private $gameQuest;
/**
* @ORM\Column(type="datetime", nullable="true")
*/
private $activatedAt = null;
/**
* @ORM\Column(type="datetime", nullable="true")
*/
private $doneAt = null;
/**
* @ORM\Column(type="datetime", nullable="true")
*/
private $completedAt = null;
这里是删除失败的测试代码,没有任何异常和错误:
public function resetGameQuests(Game $game)
{
$players = $game->getPlayers();
/**
* @var Player $player
*/
foreach ($players as $player) {
$player->getGameQuestLinks()->forAll(function($index, $link) {
$this->em->remove($link);
});
//$player->getGameQuestLinks()->clear();
//$this->em->persist($player);
}
$this->em->flush();
// $gameQuests = $game->getGameQuests()->toArray();
// foreach ($gameQuests as $gameQuest) {
// $this->em->remove($gameQuest);
// }
// $game->getGameQuests()->clear();
//
// $this->em->flush();
// $this->createGameQuests($game);
}
我尝试在
Doctrine ORM
代码中调试它,放置断点。
我看到它确实提交了正确的 SQL 语句。但是,一旦
commit()
在 PDO 连接上返回成功结果,数据库表 中的所有条目都会使用不同的 id 重新创建。我知道这听起来很奇怪,但这是真的。
更奇怪的是,当我将 SQL 语句 (
DELETE FROM player_game_quest_link WHERE id = N;
) 复制并粘贴到 MySQL Workbench SQL 编辑器时,它们做得很好。
我尝试手动运行事务中的 DELETE 语句 - 删除成功。另外,我尝试暂时编辑 Doctrine 的代码并删除
$conn->beginTransaction()
和 $conn->commit()
调用,还添加了 $conn->setAutocommit(true)
- 但错误仍然存在,所以它绝对与事务无关。
还尝试在
UnitOfWork
的 commit()
方法的其他部分放置断点,以查看是否有任何插入或集合更新 - 没有触发任何内容。
最后,我在
vendor/doctrine/dbal/src/Connection.php
方法中的 insert()
文件中放置了一个断点 - 以确保在请求期间不会调用它。确实不是。
这可能是一些罕见的 SQL 驱动程序问题吗?
我的
Doctrine
版本是2.7.1
,Symfony
版本是5.3
,MySQL Server
版本是8.0.36
。 PHP
版本是8.3.2
。我正在 Windows 10 1909
上运行它。
如果可以请帮忙调试
我找到了解决方案。问题出在这段代码中:
$player->getGameQuestLinks()->forAll(function($index, $link) {
$this->em->remove($link);
});
foreach
无法按照我的想法使用持久集合,而无需先将其转换为带有 toArray()
的数组,因此我仅删除 one 第一个玩家的链接。我以为的“行重新创建”实际上是部分删除(因为我测试的游戏有 12 名玩家,每个玩家 100 个任务,并且 MySQL Workbench 中为了性能而将结果限制设置为 100 行)。
正确的代码是这样的:
foreach ($players as $player) {
$player->getGameQuestLinks()->clear();
}
$this->em->flush();