Estou tentando fazer um exemplo simples para aprender como excluir uma linha de uma tabela pai e excluir automaticamente as linhas correspondentes na tabela filho usando o Doctrine2.
Aqui estão as duas entidades que estou usando:
Child.php:
<?php
namespace Acme\CascadeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="child")
*/
class Child {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="Father", cascade={"remove"})
*
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="father_id", referencedColumnName="id")
* })
*
* @var father
*/
private $father;
}
Father.php
<?php
namespace Acme\CascadeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="father")
*/
class Father
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
As tabelas foram criadas corretamente no banco de dados, mas a opção Ao excluir cascata não é criada. O que estou fazendo de errado?
php
doctrine-orm
symfony
cascading-deletes
rfc1484
fonte
fonte
Respostas:
Existem dois tipos de cascatas no Doctrine:
1) Nível ORM - usa
cascade={"remove"}
na associação - este é um cálculo feito no UnitOfWork e não afeta a estrutura do banco de dados. Quando você remove um objeto, o UnitOfWork itera sobre todos os objetos da associação e os remove.2) Nível do banco de dados - usa
onDelete="CASCADE"
no joinColumn da associação - isso adicionará Ao excluir cascata à coluna de chave estrangeira no banco de dados:Também quero ressaltar que, da maneira que você tem sua cascata = {"remove"} agora, se você excluir um objeto filho, essa cascata removerá o objeto pai. Claramente não é o que você quer.
fonte
onDelete
assim como,cascade = {"remove"}
por exemplo, quando você tem algum objeto relacionado ao fosUser. Ambos os objetos não devem existir sozinhos@ORM\JoinColumn(onDelete="CASCADE")
e ainda permitir que a doutrina lide com os nomes das colunas automaticamente.onDelete="CASCADE"
isso não terá nenhum efeito, pois o Doctrinecascade={"remove"}
remove as entidades relacionadas antes de remover a entidade raiz (é necessário). Portanto, quando a entidade raiz é excluída, não há mais relações externasonDelete="CASCADE"
a serem excluídas. Mas para ter certeza, sugiro que você simplesmente crie um pequeno caso de teste e observe as consultas que estão sendo executadas e sua ordem de execução.Aqui está um exemplo simples. Um contato tem de um a muitos números de telefone associados. Quando um contato é excluído, desejo que todos os seus números de telefone associados também sejam excluídos, portanto, uso ON DELETE CASCADE. O relacionamento um para muitos / muitos para um é implementado com a chave estrangeira nos números de telefone.
Ao adicionar "ON DELETE CASCADE" à restrição de chave estrangeira, os números de telefone serão excluídos automaticamente quando o contato associado for excluído.
Agora, quando uma linha na tabela de contatos é excluída, todas as suas linhas de número de telefone associadas serão excluídas automaticamente.
Para obter o mesmo resultado no Doctrine, para obter o mesmo comportamento "ON DELETE CASCADE" no nível do banco de dados, configure o @JoinColumn com a opção onDelete = "CASCADE" .
Se você faz agora
você verá que o mesmo SQL será gerado como no primeiro exemplo bruto de SQL
fonte
onDelete="cascade"
é colocado corretamente na entidade (no filho) porque é o SQL em cascata , que é colocado no filho. Somente a Doutrina em cascata (cascade=["remove"]
que não é usada aqui) é colocada no pai.