Laravel: Rücksendung der Namespace Besitzer eine polymorphe Beziehung
Finde ich eine Reihe von Diskussionen zu diesem aber keine eindeutige Lösung. Hier sind zwei links, obwohl ich werde alles in meiner Frage hier.
Einfache Erklärung
Dies ist eine einfache Erklärung für mein problem für jemanden bereits vertraut mit Laravel ist polymorphe Beziehungen.
Bei der Verwendung von $morphClass, der Inhalt von $morphClass, die in der Datenbank gespeichert wird, wie die morph - "Typ" wird für den Klassennamen, wenn Sie versuchen, den Besitzer zu finden, der eine polymorphe Beziehung. Dies führt zu einem Fehler, da die ganze Stelle von $morphClass ist, dass es sich nicht um ein vollständig Namespace name der Klasse.
Wie definieren Sie den Klassennamen, dass die polymorphe Beziehung verwenden sollte?
Ausführlichere Erklärung
Dies ist eine ausführlichere Erklärung, die erklären, genau das, was ich versuche zu tun, und warum bin ich versucht, es zu tun mit Beispielen.
Bei der Verwendung von Polymorphen Beziehungen in Laravel, was wird gespeichert, wie die "morph_type" - Typ in der Datenbank wird davon ausgegangen, dass die Klasse.
So, in diesem Beispiel:
class Photo extends Eloquent {
public function imageable()
{
return $this->morphTo();
}
}
class Staff extends Eloquent {
public function photos()
{
return $this->morphOne('Photo', 'imageable');
}
}
class Order extends Eloquent {
public function photos()
{
return $this->morphOne('Photo', 'imageable');
}
}
Die Datenbank würde so Aussehen:
staff
- id - integer
- name - string
orders
- id - integer
- price - integer
photos
- id - integer
- path - string
- imageable_id - integer
- imageable_type - string
Nun die erste Reihe von Fotos, die könnte wie folgt Aussehen:
id,Pfad,imageable_id,imageable_type
1,Bild.png -, 1 -, Personal -
Nun kann ich entweder den Zugriff auf die Foto aus einem Stab-Modell oder ein Mitarbeiter ein Foto-Modell.
//Find a staff member and dump their photos
$staff = Staff::find(1);
var_dump($staff->photos);
//Find a photo and dump the related staff member
$photo = Photo::find(1);
var_dump($photo->imageable);
So weit So gut. Allerdings, wenn ich namespace-ich laufen in ein problem.
namespace App/Store;
class Order {}
namespace App/Users;
class Staff {}
namespace App/Photos;
class Photo {}
Nun was ist gesichert in meiner Datenbank ist diese:
id,Pfad,imageable_id,imageable_type
1,Bild.png,1,App/Benutzer/Mitarbeiter
Aber ich will nicht, dass. Das ist eine schreckliche Idee, um die volle Klasse in einem Namespace befinden, Namen in der Datenbank gespeichert, so!
Glücklicherweise Laravel hat eine option, um ein $morphClass variable. Etwa so:
class Staff extends Eloquent {
protected $morphClass = 'staff';
public function photos()
{
return $this->morphOne('Photo', 'imageable');
}
}
Nun die Zeile in meiner Datenbank wird so Aussehen, das ist genial!
id,Pfad,imageable_id,imageable_type
1,Bild.png -, 1 -, Personal -
Und immer die Fotos von einem Mitarbeiter funktioniert sehr gut.
//Find a staff member and dump their photos
$staff = Staff::find(1);
//This works!
var_dump($staff->photos);
Jedoch die polymorph-Zauber zu finden, der Besitzer des Fotos nicht funktioniert:
//Find a photo and dump the related staff member
$photo = Photo::find(1);
//This doesn't work!
var_dump($photo->imageable);
//Error: Class 'staff' not found
Vermutlich muss es eine Möglichkeit zu informieren, die polymorphe Beziehung, was classname zu verwenden, wenn $morphClass aber ich kann nicht finden jede Bezugnahme auf, wie diese Arbeit sollte in den docs, in den source-code oder über Google.
Hilfe?
- Hast du versucht, pass, $this->morphOne () - Modell-Namen mit namespace?
- Welches argument würde es sein?
- zuerst return $this->morphOne('App/Fotos/Foto', 'druckbaren');
- Ah ja, das habe ich getan, sorry kopieren und einfügen die ganze Sache wieder schien sich nicht lohnt, aber das macht keinen Unterschied. Es ist die morphTo() das ist das problem, nicht das morphOne()
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es 2 einfache Möglichkeiten - der eine unten, der andere in @lukasgeiter Antwort, wie vorgeschlagen, von Taylor Otwell, die ich auf jeden Fall vorschlagen, prüfen, wie gut:
getan:
Ich würde es nicht verwenden echt Klasse Namen (
Order
undStaff
) mögliche Duplikate zu vermeiden. Es gibt sehr wenig chance, dass etwas genannt würdeMorphXxxx
so ist es ziemlich sicher.Dies ist besser als das speichern von namespaces (ich bin nicht dagegen, das sieht in der db, jedoch wäre es ungünstig, falls Sie etwas ändern - sagen statt
App\Models\User
verwendenCartalyst\Sentinel\User
etc), weil alles, was Sie brauchen, ist ein vertauschen der Umsetzung durch Aliase config.Aber es gibt auch ein Nachteil - Sie nicht wissen, was das Modell ist, nur durch überprüfung der db - falls es Ihnen wichtig ist.
MyClass::class
bei der Festlegung der morphOne Beziehung, so dass ich nie vor diesem problem. Aber ich hätte nie gedacht, über die Auswirkungen der Umgestaltung auf die Datenbank, vielen Dank!Ich wie @JarekTkaczyks Lösung und ich würde vorschlagen, Sie verwenden. Aber, der Vollständigkeit halber, es ist eine andere Art Taylor kurz erwähnt, auf github
Können Sie ein Attribut-accessor für die
imageable_type
- Attribut, und verwenden Sie dann eine "classmap" array, um die richtige Klasse.Hinweis, dass Sie immer noch müssen die
morphClass
Attribut für die Abfrage von der anderen Seite der Beziehung obwohl.$array['Type'] != $array['type']
ABERnew 'Type' == new 'type'
- willkommen auf PHP 😉$types
wie Klassennamen, sondern eher zwischen groß-und Kleinschreibung von Bezeichnern. Wenn ich dich missverstanden, fühlen Sie sich frei, zu suggerieren, ein edit...'' => self:class
zu den$types
array oder sonst wäre es zu beschweren, wenn Sie zuerst das Modell speichernBei der Verwendung von Laravel 5.2 (oder neuer) können Sie das neue feature
morphMap
um dieses Problem zu beheben. Nur fügen Sie diese an dieboot
Funktion inapp/Providers/AppServiceProvider
:Mehr dazu: https://nicolaswidart.com/blog/laravel-52-morph-map
boot
Funktion inapp/Providers/AppServiceProvider
.$relation = Relation::morphMap();
vor der Rückkehr zu die Karte Holen und dannreturn $this->morphOne($relation['photo'], 'imagable');
. Nicht sicher, ob es einen einfacheren Weg, aber so ist es die Arbeit mit-heraus sagen Foto nicht gefunden.$table->morphs('imageable');
um Ihre Fotos migration. Erstellenimageable_type
undimageable_id
für Sie, das ist einfacher zu schreiben. Gefunden im test setup - hierLassen laravel setzen Sie es in die db - namespace und alle. Wenn Sie die kurze classname für etwas, neben Ihrer Datenbank hübscher aus, dann definieren Sie einen accessor für Sie so etwas wie :
Die Argumentation, die ich immer wieder kommen, um in Fällen wie diesem ist, dass Laravel ist ziemlich gut getestet, und funktioniert wie erwartet für die meisten Teil. Warum kämpfen die Rahmen, wenn Sie nicht haben, um - vor allem, wenn Sie einfach nur genervt von der namespace wird in der db. Ich Zustimmen, dass es keine gute Idee ist, so zu tun, aber ich fühle auch, dass ich meine Zeit sinnvoller, über sich und die Arbeit auf der Domäne-code.
Damit eager loading polymorpher Beziehungen zB
Photo::with('imageable')->get();
es notwendig null zurück, wenn der Typ leer ist.