2016-04-03 23 views
0

ich nicht meinen Kopf um dies zu erreichen:Testing OneToMany Beziehung Laravel, Eloquent funktioniert nicht

$fragment = factory(Fragment::class)->create(); 

$this->assertCount(0, $fragment->values); 

fragment->fetch(); // updates the 'values' by adding one Value object. 

var_dump($fragment->id); // i.e. 6 
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count()); // 0 
var_dump(Fragment::first()->values->count()); // 1 

$this->assertCount(1, $fragment->values); 

ich DatabaseTranscations verwenden, so dass nach ein Fragment erstellt wird, gibt es immer eine und nur eine. Daher sind $ fragment und Fragment :: first() genau die gleiche Instanz. Aber ... die Wertebeziehung ist anders. Wie kann das der Fall sein?

Beachten Sie, dass dies nur während des Testens geschieht, wenn ich dies manuell über meinen Controller teste (und die Werte werden an die Blade-Vorlagenseite übergeben), funktioniert es gut. Ich bin verwirrt: S.

Irgendwelche Ideen?

Antwort

1

Beziehungsattribute ($fragment->values) werden nur einmal geladen. Sie werden nicht auf dem neuesten Stand gehalten, wenn Sie Elemente aus der Beziehung hinzufügen oder löschen. Sie treffen die Datenbank nicht jedes Mal, um nach Änderungen zu suchen.

Ihre zweite Zeile ist $this->assertCount(0, $fragment->values);. Zugriff auf $fragment->values hier faul lädt die Beziehung, und wie Ihr Assert beweist, ist es leer.

Sie rufen dann $fragment->fetch(), in dem Ihr Kommentar sagt, fügt ein Objekt Value zu dem Fragment hinzu. Ihr Beziehungsattribut ($fragment->values) wurde jedoch bereits aus der vorherigen Anweisung geladen, sodass es nicht das zusätzliche Objekt Value widerspiegelt, das Sie der Beziehung hinzugefügt haben.

Daher wird auch nach dem Aufruf an fetch(), $fragment->values immer noch eine leere Sammlung sein. Fragment::first()->values enthält die neu verwandte Value obwohl, da es eine neue Instanz der Fragment erhält, und wenn es die values zum ersten Mal lädt, wird es die zugehörige Value abholen. Wenn Sie die Beziehung neu laden müssen, können Sie die load() Methode verwenden. Wenn Sie dies nach Ihrem Anruf zu fetch() hinzufügen (oder in Ihrer fetch() Methode, was auch immer für Sie sinnvoll ist), wird Ihr Test gut funktionieren.

$fragment = factory(Fragment::class)->create(); 

$this->assertCount(0, $fragment->values); 

$fragment->fetch(); // updates the 'values' by adding one Value object. 

var_dump($fragment->id); // i.e. 6 
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count()); // 0 

// reload the values relationship 
$fragment->load('values'); 

var_dump($fragment->values->count()); // 1 
var_dump(Fragment::first()->values->count()); // 1 

$this->assertCount(1, $fragment->values); 

Die andere Option, die Sie haben, ist die Beziehung Abfrage zu verwenden, indem die Beziehung Methode anstelle der Beziehung Zugriff auf das Attribut. Wenn Sie $fragment->values()->count() (Anmerkung: values(), nicht values) tun, trifft das jedes Mal die Datenbank und gibt immer die aktuelle Anzahl zurück.

+0

Ausgezeichnet, das funktioniert gut. Seltsamerweise habe ich die Dokumente gelesen und habe das obige Verhalten nicht verstanden. Es gibt natürlich eine Erwähnung zum eifrigen Laden (https://laravel.com/docs/5.2/eloquent-relationships#lazy-eager-loading). –

Verwandte Themen