2015-05-21 13 views
6

buduję ten związek ManyToMany między moimi dwoma podmiotami w Symfony2 i chcą mieć tabelę łączącą się z charsetlatin1 i engineMyISAM (są UTF- 8 i InnoDB domyślnie).Zmień charset i silnik do stolika pośredniego ManyToMany relacji za Doctrine2 za

Oto one:

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; 

Jak widać, wiem jak poprawnie ustawić te informacje dla tabele moich jednostek, ale jak mogę zrobić dla tabeli paiement_commande?


Próbowałem:

/* 
* @ORM\JoinTable(name="paiement_commande", options={"collate"="latin1_general_ci", "charset"="latin1", "engine":"MyISAM"}) 
*/ 
private $commandes; 

Ale mam z polecenia $ php app/console doctrine:schema:validate:

[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 

Jak mogę ustawić tej relacji ManyToMany między moimi dwoma podmiotami i nadal być w stanie określić zarówno dla engine i charset dla nowo utworzonej tabeli łączenia?

Dzięki za pomoc!

Odpowiedz

7

Niestety, nie można kontrolować silnika, zestawu znaków, zestawiania i innych właściwości, takich jak ten z tabel łączenia przez doktrynę. Jak widać, adnotacja @JoinTable nie zawiera argumentu options, takiego jak @Table.

Ale zawsze możesz zarządzać tymi rzeczami ręcznie, a Doctrine nie będzie narzekać (podczas sprawdzania poprawności schematu). Stwórz więc sam stół do łączenia, lub przygotuj go i dostosuj zgodnie z własnymi potrzebami.

osobista rada

IMHO nie powinno polegać na Doktryny utworzyć lub zmienić swój schemat.

Użycie poleceń konsoli Doctrine do utworzenia i zmiany bazy danych jest dobre dla bazy danych programowania, a także przydatne do uzyskania wstępnego wskazania, czego SQL potrzebujesz (zobacz orm:schema-tool:update --dump-sql).

Ale do wykorzystania w produkcji ten kod SQL powinien być zawsze ręcznie modyfikowany. Doctrine po prostu nie zawsze generuje poprawny SQL. Podobnie jak w przypadku, masz inne przypadki, które nie biorą pod uwagę.

Inne narzędzia

Proponuję przyjrzeć się kilku innych narzędzi do zarządzania migracji bazy danych.

Doctrine Migrations jest jednym.Zauważ, że to narzędzie korzysta z narzędzia Doctrine ORM do generowania kodu SQL (patrz migrations:diff), więc napotkasz na te same problemy. Różnica polega na tym, że możesz stworzyć "wersje", które możesz następnie zmienić i zmienić, aż będziesz mieć to, czego chcesz. Ta ostateczna "wersja" to rzecz, którą aplikujesz do swojej bazy danych.

Innym popularnym narzędziem do migracji jest Phinx. Jest bardziej dynamiczny i niezależny od ramek (więc nie potrzebuje Doctrine).

+0

FYI: Wysłałem żądanie ściągnięcia do Doctrine2, które, mam nadzieję, naprawi ten problem: https://github.com/doctrine/doctrine2/pull/5953 – mattsches

0

Doctrine używa foreign_keys w dowolnym odwzorowaniu relacji - są one dostępne tylko w InnoDB. Co więcej, doktryna nie powiedzie się, gdy spróbujesz wykonać transakcję na silniku nietransakcyjnym (np. MyISAM), here. Wszakże istnieją pewne implementations w Doctrine 2,2 lub 2,3

1

radzę byłoby pozwolić Nauki i InnoDB nie gdzie są dobrzy, obchodzenia się z więzów integralności i relacje. Prawdopodobnie chcesz użyć MyISAM do funkcji wyszukiwania, więc lepiej byłoby utworzyć kopię odpowiednich danych.

Możesz podpiąć wszystkie zdarzenia, które uruchamia Doctrine, i skopiować dane encji do innej tabeli. Zdarzenia te są bardzo wydajne i pozwalają na podłączenie do niemal każdego scenariusza: http://doctrine-orm.readthedocs.org/en/latest/reference/events.html

można utworzyć abonenta w Symfony, która koncentruje się na obsłudze wszystkich wydarzeń dla tej jednostki: http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html

3

Sztuczka może być użycie innego podmiotu jako stół do łączenia.

Upraszczając:

<?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; 

myślę, że to i tak lepiej korzystać z tego rodzaju pośredniej jednostki, ponieważ w pewnym momencie w aplikacji może być konieczne do przechowywania danych pośrednich, a to byłoby jedynym sposobem rób to (i zmiana każdego fragmentu kodu związanego z relacją byłaby dość bolesna).

Powiązane problemy