php - onetomany - manytoone symfony 3
Cambie el juego de caracteres y el motor para la tabla intermedia de la relaciĆ³n ManyToMany de Doctrine2 (4)
Desafortunadamente no se puede controlar el motor, conjunto de caracteres, colación y otras propiedades como esta de tablas de unión a través de doctrina. Como puede ver, la anotación @JoinTable
no tiene un argumento de options
, como @Table
tiene.
Pero siempre puede administrar estos elementos manualmente y Doctrine no se quejará (al validar el esquema). Entonces, cree la tabla de unión usted mismo o haga que Doctrine la cree y la ajuste de acuerdo con sus deseos.
Asesoramiento personal
En mi humilde opinión, no debe confiar en Doctrine para crear o modificar su esquema.
Usar los comandos de la consola de Doctrine para crear y modificar la base de datos está bien para su base de datos de desarrollo, y también es útil para obtener una indicación inicial de qué SQL necesita (ver orm:schema-tool:update --dump-sql
).
Pero para el uso de producción, este SQL siempre debe revisarse manualmente. Doctrine simplemente no siempre genera el SQL correcto. Como en el caso que tienes, hay otros casos extremos que no se tienen en cuenta.
Otras herramientas
Sugiero que eche un vistazo a otras herramientas para administrar migraciones de bases de datos.
Doctrine Migrations es uno. Tenga en cuenta que esta herramienta se basa en Doctrine ORM para generar SQL (consulte migrations:diff
), por lo que se encontrará con los mismos problemas. La diferencia es que puede hacer que cree "versiones", que luego puede revisar y modificar, hasta que tenga lo que desea. Esa "versión" final es lo que aplica a su base de datos.
Otra herramienta de migración popular es Phinx . Es más dinámico e independiente del marco (por lo que no necesita Doctrine).
Estoy construyendo esta relación ManyToMany entre mis dos entidades en Symfony2 y deseo que la tabla de enlaces sea del charset
latin1 y del engine
MyISAM (son UTF-8 e InnoDB por defecto).
Aquí están :
Entity / Commande
<?php
// ...
/**
* Commande
*
* @ORM/Table(name="commande", options={"collate"="latin1_general_ci", "charset"="latin1", "engine":"MyISAM"})
* @ORM/Entity()
*/
class Commande
{
// ...
/**
* @var ArrayCollection
*
* @ORM/ManyToMany(targetEntity="Paiement", inversedBy="commandes", cascade={"persist"})
* @ORM/JoinTable(name="paiement_commande",
* joinColumns={@ORM/JoinColumn(name="commande_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM/JoinColumn(name="paiement_id", referencedColumnName="id")}
* )
*/
private $paiements;
Entity / Paiement
<?php
// ...
/**
* Paiement
*
* @ORM/Table(name="paiement", options={"collate"="latin1_general_ci", "charset"="latin1", "engine":"MyISAM"})
* @ORM/Entity()
*/
class Paiement
{
// ...
/**
* @var ArrayCollection
*
* @ORM/ManyToMany(targetEntity="Commande", mappedBy="paiements", cascade={"persist"})
* @ORM/JoinTable(name="paiement_commande")
*/
private $commandes;
Como puede ver, sé cómo configurar correctamente esta información para las tablas de mi entidad, pero ¿cómo puedo hacer para la tabla paiement_commande
?
Lo intenté:
/*
* @ORM/JoinTable(name="paiement_commande", options={"collate"="latin1_general_ci", "charset"="latin1", "engine":"MyISAM"})
*/
private $commandes;
Pero obtuve, desde la $ php app/console doctrine:schema:validate
command:
[Doctrine/Common/Annotations/AnnotationException]
[Creation Error] The annotation @ORM/JoinTable declared on property Entity/Paiement::$commandes does not have a property named "options". Available properties: name, schema, joinColumns, inverseJoinColumns
¿Cómo puedo establecer esta relación ManyToMany entre mis dos entidades y aún así poder especificar tanto el engine
como el charset
de charset
para la nueva tabla de enlaces creada?
¡Gracias por la ayuda!
Doctrine usa foreign_keys
en cualquier mapeo de relaciones, estas solo están disponibles en InnoDB
. Además de eso, la doctrina fallará cuando intente realizar una transacción en un motor no transaccional (como MyISAM), aquí . Después de todo, hay algunas implementaciones en Doctrine
2.2 o 2.3
Mi consejo sería dejar que Doctrine e InnoDB hagan lo que hacen bien, manejando la integridad referencial y las relaciones. Probablemente desee utilizar MyISAM para la funcionalidad de búsqueda, por lo que sería mejor crear una copia de los datos relevantes para eso.
Puede conectar todos los eventos que Doctrine desencadena y hacer una copia de los datos de la entidad en otra tabla. Estos eventos son realmente poderosos y le permiten conectarse a casi todos los escenarios: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html
Puede crear un suscriptor en Symfony que se centre en el manejo de todos los eventos para esa entidad: http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html
Un truco podría ser usar otra entidad como una tabla de unión.
Simplemente pon :
<?php
// ...
/**
* PaiementCommande
*
* @ORM/Table(name="paiement_commande", options={"collate"="latin1_general_ci", "charset"="latin1", "engine":"MyISAM"})
* @ORM/Entity()
*/
class PaiementCommande
{
// ...
/** *
* @ORM/ManyToOne(targetEntity="Commande")
*/
private $commande;
/** *
* @ORM/ManyToOne(targetEntity="Paiement")
*/
private $paiement;
Creo que de todos modos es mejor usar este tipo de entidad intermedia ya que en un punto de la aplicación puede que necesite almacenar datos intermedios, y esta sería la única forma de hacerlo (y cambiar cada parte del código relacionado con la relación ser bastante doloroso).