Symfony:已检测到循环,因此无法进行拓扑排序

v7pvogib  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(102)

当我尝试在Symfony 6.3应用中删除一个用户时,我得到了以下消息:检测到一个循环,因此拓扑排序是不可能的。getCycle()方法提供了形成循环的节点列表。
我检查了我的所有实体,带有Doctrine属性。我查看了#[ORM参数,以确保删除中的级联以正确的顺序和方向执行。所有似乎都是正确的。我的用户实体有许多一对多和多对一关系,我确保删除设置的级联是从我的用户实体到相关实体执行的。
你必须知道,我的用户有不同的状态(在验证,活动,暂停,退出),我必须历史化(即保持每一个变化的历史),所以我创建了一个StateHisto实体,它与我的User实体有多对一的关系。
但出于性能考虑,我必须将用户的最后一个状态保存在一个属性中才能直接获取它。因此,我向我的用户实体添加了一个lastStateHisto属性,该属性与StateHisto实体具有一对一关系。
下面是我的代码摘录:
使用者实体:

#[Vich\Uploadable]
#[ORM\Table(name: '`user`')]
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[UniqueEntity(fields: ['surname', 'firstname', 'birthDate'], message: 'L\'utilisateur existe déjà')]
#[InheritanceType('SINGLE_TABLE')]
#[DiscriminatorColumn(name: 'discr', type: 'string')]
#[DiscriminatorMap(['user' => 'User', 'apprenant' => 'Apprenant', 'benevole' => 'Benevole', 'enfant' => 'Enfant'])]

class User implements UserInterface, PasswordAuthenticatedUserInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    protected $id;

    #[ORM\Column(type: 'string', length: 180, unique: true)]
    protected $username;

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     *
     * @var File|null
     */
    #[Vich\UploadableField(mapping: 'user_image', fileNameProperty: 'imageName', size: 'imageSize')]
    protected ?File $imageFile = null;

    /**
     * @var string|null
     */
    #[ORM\Column(type: 'string', nullable: true)]
    protected ?string $imageName = null;

    /**
     * @var int|null
     */
    #[ORM\Column(type: 'integer', nullable: true)]
    protected ?int $imageSize = null;

    /**
     * @var \DateTimeInterface|null
     */
    #[ORM\Column(type: 'datetime', nullable: true)]
    protected ?\DateTimeInterface $updatedAt = null;

    #[ORM\Column(type: 'json')]
    protected $roles = [];

    /**
     * @var string The hashed password
     */
    #[ORM\Column(type: 'string')]
    protected $password;

    #[ORM\Column(type: 'string', length: 255)]
    protected $surname;

    #[ORM\Column(type: 'string', length: 255)]
    protected $firstname;

    #[ORM\Column(type: 'string', length: 255)]
    protected $title;

    #[ORM\Column(type: 'date')]
    protected $birthDate;

    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    protected $tel1;

    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    protected $tel2;

    #[ORM\Column(type: 'string', length: 3000, nullable: true)]
    protected $comment;

    #[ORM\Column(type: 'string', length: 360, unique: true, nullable: true)]
    protected $email;

    #[ORM\OneToMany(mappedBy: 'user', targetEntity: StateHisto::class, cascade: ['persist', 'remove'], fetch: 'EAGER', orphanRemoval: true)]
    #[ORM\JoinColumn()]
    /**
     * States: 1=In validation, 2=Active, 3=In pause, 4=Inactive
     */
    protected $stateHisto;

    #[ORM\OneToOne(cascade: ['persist'])]
    #[ORM\JoinColumn(nullable: true)]
    private ?StateHisto $lastStateHisto = null;

字符串
StateHisto实体:

#[ORM\Entity(repositoryClass: StateHistoRepository::class)]
class StateHisto
{

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private $id;

    #[ORM\Column(type: 'date')]
    private $date;

    #[ORM\Column(type: 'integer')]
    #[Assert\Choice(1, 2, 3, 4)]
    /**
     * States: 1=In validation, 2=Active, 3=In pause, 4=Inactive
     */
    private $state;

    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private $reason;

    #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'stateHisto')]
    #[ORM\JoinColumn(nullable: false)]
    private $user;

    #[ORM\Column(nullable: true)]
    private ?int $stdExitReason = null;

wbgh16ku

wbgh16ku1#

过了一会儿,我意识到错误消息中提到的循环是我在同一个实体StateHisto上组合了一对多关系和一对一关系。这使得从用户到StateHisto表的删除操作无法级联。
这里需要做的是,在启动用户删除之前,首先将lastStateHisto属性(保存一对一关系的属性)设置为null。
这意味着在控制器中,您可以这样做:

$user->setLastStateHisto(null);
        $entityManager->persist($user);
        $entityManager->flush();
        $entityManager->remove($user);
        $entityManager->flush();

字符串
这样就行了

相关问题