Symfony 2.7.2. Lehre ORM 2.4.7. MySQL 5.6.12. PHP 5.5.0.
Ich habe eine Entität mit einer benutzerdefinierten ID-Generatorstrategie. Es funktioniert einwandfrei.
Unter Umständen muss ich diese Strategie mit einer "handgemachten" ID überschreiben. Es funktioniert, wenn die Haupteinheit ohne Assoziationen gelöscht wird. Aber es funktioniert nicht mit Assoziationen. Dieser Beispielfehler wird ausgelöst:
Beim Ausführen von 'INSERT INTO articles_tags (article_id, tag_id) VALUES (?,?)' mit params ["a004r0", 4] ist eine Ausnahme eingetreten:
SQLSTATE [23000]: Integritätseinschränkungsverletzung: 1452 Hinzufügen oder Aktualisieren einer untergeordneten Zeile nicht möglich: Eine Fremdschlüsseleinschränkung schlägt fehl (
sf-test1
.articles_tags
, CONSTRAINTFK_354053617294869C
FREMDSCHLÜSSEL (article_id
) REFERENCESarticle
(id
) ON DELETE CASCADE)
So reproduzieren Sie:
app/config/parameters.yml
mit Ihren DB-Parametern. Erstellen Sie mithilfe des Beispiel-Namespaces AppBundle
die Entitäten Article
und Tag
im Verzeichnis src/AppBundle/Entity
.
Erzeuge Getter und Setter für die obigen Entitäten:
%Vor% Erstellen Sie ArticleNumberGenerator
class in src/AppBundle/Doctrine
:
Datenbank erstellen: php app/console doctrine:database:create
.
php app/console doctrine:schema:create
. Bearbeiten Sie das Beispiel AppBundle DefaultController
in src\AppBundle\Controller
. Ersetzen Sie den Inhalt durch:
Server ausführen: php app/console server:run
.
Navigieren Sie zu Ссылка . Aktualisieren Sie 2 Mal, um diese Nachricht zu sehen:
Erstellte Artikel-ID a003r0.
Navigieren Sie nun zu Ссылка . Das erwartete Ergebnis ist:
Erstellte Artikel-ID test1.
, stattdessen erhalten Sie den Fehler:
Beim Ausführen von 'INSERT INTO articles_tags (article_id, tag_id) VALUES (?,?)' mit params ["a004r0", 4] ist eine Ausnahme eingetreten:
SQLSTATE [23000]: Integritätseinschränkungsverletzung: 1452 Hinzufügen oder Aktualisieren einer untergeordneten Zeile nicht möglich: Eine Fremdschlüsseleinschränkung schlägt fehl (
sf-test1
.articles_tags
, CONSTRAINTFK_354053617294869C
FREMDSCHLÜSSEL (article_id
) REFERENCESarticle
(id
) ON DELETE CASCADE)
offensichtlich, weil Artikel mit id
"a004r0" nicht existiert.
Wenn ich $article->getTags()->add($tag);
in createHandmadeAction
auskommentiere, funktioniert es - das Ergebnis ist:
Erstellt Artikel-ID-Test.
und die Datenbank wird entsprechend aktualisiert:
%Vor%, aber nicht, wenn eine Beziehung hinzugefügt wird. Aus einem Grund verwendet Doctrine nicht das handgemachte id
für Assoziationen, sondern verwendet die Standard-Id-Generator-Strategie.
Was ist hier falsch? Wie kann ich den Entity Manager davon überzeugen, meine handgefertigten Ids für Assoziationen zu verwenden?
Ihr Problem hängt mit dem Aufruf von $em->persist($article);
zusammen, bevor Sie ClassMetadata
ändern.
Wenn die neue Entität beibehalten wird, generiert UnitOfWork
id
mit ArticleNumberGenerator
und speichert sie im Feld entityIdentifiers
. Später ManyToManyPersister
verwendet diesen Wert mit Hilfe von PersistentCollection
beim Füllen der Relationstabellenzeile.
Beim Aufruf von flush
UoW
berechnet den Änderungssatz der Entität und speichert den tatsächlichen ID-Wert - deshalb erhalten Sie korrekte Daten, nachdem Sie keine Assoziation hinzugefügt haben. Aber es aktualisiert Daten von entityIdentifiers
nicht.
Um das zu beheben, könnten Sie persist
einfach hinter das Ändern des ClassMetadata-Objekts verschieben. Aber der Weg sieht immer noch aus wie Hack. IMO ist der optimale Weg, den benutzerdefinierten Generator zu schreiben, der zugewiesene ID verwenden wird, wenn die eine bereitgestellt wird, oder neue generieren.
PS . Die andere Sache, die berücksichtigt werden sollte - Ihre Art der Generierung ID ist nicht sicher, es wird doppelte IDs auf der Hochlast produzieren.
UPD
Verpasst, dass UoW
nicht idGeneratorType
verwendet (es wird von metadata factory verwendet, um den richtigen Wert für idGenerator
zu setzen), also sollten Sie die richtige idGenerator
Das funktioniert wie erwartet.
Tags und Links php symfony oop doctrine2 associations