Estoy tratando de hacer un ejemplo simple para aprender cómo eliminar una fila de una tabla primaria y eliminar automáticamente las filas coincidentes en la tabla secundaria usando Doctrine2.
Aquí están las dos entidades que estoy 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;
}
Las tablas se crean correctamente en la base de datos, pero no se crea la opción On Delete Cascade. ¿Qué estoy haciendo mal?
php
doctrine-orm
symfony
cascading-deletes
rfc1484
fuente
fuente
Respuestas:
Hay dos tipos de cascadas en Doctrine:
1) Nivel ORM - usos
cascade={"remove"}
en la asociación - este es un cálculo que se realiza en UnitOfWork y no afecta la estructura de la base de datos. Cuando elimina un objeto, UnitOfWork iterará sobre todos los objetos de la asociación y los eliminará.2) Nivel de base de datos - usos
onDelete="CASCADE"
en joinColumn de la asociación - esto agregará On Delete Cascade a la columna de clave externa en la base de datos:También quiero señalar que la forma en que tiene su cascada = {"eliminar"} en este momento, si elimina un objeto secundario, esta cascada eliminará el objeto principal. Claramente no es lo que quieres.
fuente
onDelete
así como,cascade = {"remove"}
por ejemplo, cuando tiene algún objeto relacionado con fosUser. Ambos objetos no deberían existir solos@ORM\JoinColumn(onDelete="CASCADE")
y dejar que la doctrina maneje los nombres de las columnas automáticamente.onDelete="CASCADE"
no tendrá ningún efecto ya que Doctrinecascade={"remove"}
elimina las entidades relacionadas antes de eliminar la entidad raíz (tiene que hacerlo). Entonces, cuando se elimina la entidad raíz, no quedan relaciones exteriores paraonDelete="CASCADE"
eliminar. Pero para estar seguro, sugeriría que simplemente cree un pequeño caso de prueba y observe las consultas que se ejecutan y su orden de ejecución.Aquí hay un ejemplo simple. Un contacto tiene uno o muchos números de teléfono asociados. Cuando se elimina un contacto, quiero que también se eliminen todos sus números de teléfono asociados, así que uso ON DELETE CASCADE. La relación uno a muchos / muchos a uno se implementa con la clave externa en los números de teléfono.
Al agregar "ON DELETE CASCADE" a la restricción de clave externa, phone_numbers se eliminará automáticamente cuando se elimine su contacto asociado.
Ahora, cuando se elimina una fila en la tabla de contactos, todas sus filas asociadas phone_numbers se eliminarán automáticamente.
Para lograr lo mismo en Doctrine, para obtener el mismo comportamiento de nivel de base de datos "ON DELETE CASCADE", debe configurar @JoinColumn con la opción onDelete = "CASCADE" .
Si ahora lo haces
verá que se generará el mismo SQL que en el primer ejemplo de SQL sin formato
fuente
onDelete="cascade"
se coloca correctamente en la entidad (en el elemento secundario) porque se trata de una conexión en cascada de SQL , que se coloca en el elemento secundario. Solo el Doctrine en cascada (cascade=["remove"]
que no se usa aquí) se coloca en el padre.