2015-03-08 5 views
7

Ich habe eine Pivot-Tabelle, die Benutzer mit Arbeitsbereichen verbindet. In der Pivot-Tabelle habe ich auch eine Spalte für die Rolle, die die Benutzerrolle für diesen Arbeitsbereich definiert. Kann ich Accessor (Getter) & Mutator (Setter) -Methoden für die Rolle in der Pivot-Tabelle bereitstellen? Ich habe versucht, überall hinzuschauen, aber Details zu Pivot-Tabellen in eloquenten sind ziemlich spärlich.Accessors (Getter) & Mutators (Setter) Auf einem Pivot-Tisch in Laravel

Ich bin mir nicht sicher, ob ich ein benutzerdefiniertes Pivot-Modell einrichten muss? Wenn ich das täte, wäre ein Beispiel großartig, da die Dokumentation zu Pivot-Modellen sehr einfach ist.

Danke.

+0

Ich versuche, es manuell zu tun. Hier ist, was ich habe: http://laravel.io/bin/RE2ze – ATLChris

Antwort

7

Wenn alles, was Sie tun müssen, um Zugang zusätzliche Felder auf der Pivot-Tabelle ist, müssen Sie nur die withPivot() Methode auf der Beziehungsdefinition verwenden:

class User extends Model { 
    public function workspaces() { 
     return $this->belongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 
} 

class Workspace extends Model { 
    public function users() { 
     return $this->belongsToMany('App\Models\User')->withPivot('role'); 
    } 
} 

Jetzt wird Ihre Rolle Feld auf der Pivot-Tabelle zur Verfügung stehen :

$user = User::first(); 

// get data 
foreach($user->workspaces as $workspace) { 
    var_dump($workspace->pivot->role); 
} 

// set data 
$workspaceId = $user->workspaces->first()->id; 
$user->workspaces()->updateExistingPivot($workspaceId, ['role' => 'new role value']); 

Wenn Sie wirklich Accessoren erstellen müssen/Mutatoren für Ihre Pivot-Tabelle, müssen Sie eine benutzerdefinierte Pivot-Tabelle Klasse erstellen. Ich habe das vorher nicht getan, also weiß ich nicht, ob das tatsächlich funktioniert, aber es sieht so aus:

Erstellen Sie eine neue Pivot-Klasse, die Ihre Accessoren/Mutatoren enthält. Diese Klasse sollte die Standard-Pivot-Klasse erweitern. Diese neue Klasse ist die Klasse, die instanziiert wird, wenn der Benutzer oder der Arbeitsbereich eine Pivot-Modellinstanz erstellt.

Aktualisieren Sie jetzt Ihre Benutzer- und Arbeitsbereichsmodelle, um diese neue Pivot-Tabellenklasse anstelle der Standardklasse zu erstellen. Dies geschieht durch Überschreiben der newPivot()-Methode, die von der Model-Klasse bereitgestellt wird. Sie möchten diese Methode überschreiben, sodass Sie eine Instanz Ihrer neuen UserWorkspacePivot-Klasse anstelle der Standard-Pivot-Klasse erstellen.

class User extends Model { 
    // normal many-to-many relationship to workspaces 
    public function workspaces() { 
     // don't forget to add in additional fields using withPivot() 
     return $this->belongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 

    // method override to instantiate custom pivot class 
    public function newPivot(Model $parent, array $attributes, $table, $exists) { 
     return new UserWorkspacePivot($parent, $attributes, $table, $exists); 
    } 
} 

class Workspace extends Model { 
    // normal many-to-many relationship to users 
    public function users() { 
     // don't forget to add in additional fields using withPivot() 
     return $this->belongsToMany('App\Models\User')->withPivot('role'); 
    } 

    // method override to instantiate custom pivot class 
    public function newPivot(Model $parent, array $attributes, $table, $exists) { 
     return new UserWorkspacePivot($parent, $attributes, $table, $exists); 
    } 
} 
+0

Ich schätze Ihre ausführliche Antwort sehr, aber leider funktioniert das nicht. 'GetRoleAttribute' und 'setRoleAttribute' werden niemals angewendet. – ATLChris

+0

@ATLChris Ich habe gerade versucht, das ist eine Testumgebung und es sieht aus wie es funktioniert. Können Sie Ihren aktuellen Code posten, was Sie gerade tun, was Sie erwarten, was tatsächlich passiert und welche Fehler Sie bekommen? – patricus

+1

@ATLChris diese Lösung funktioniert. Ich habe dieses Problem mit diesem Ansatz gelöst. Für weitere Details können Sie den Artikel lesen [Laravel - Benutzerdefinierte Pivot-Modell in Eloquent] (http://softonsofa.com/laravel-custom-pivot-model-in-eloquent/) – hhsadiq

0

Dies ist eine schwierige Frage. Die Lösungen, die ich mir vorstellen kann, sind stinkend und können später zu Problemen führen.

Ich werde die Antwort von Patricus erweitern, damit es funktioniert.

Ich wollte Patricus 'Antwort kommentieren, aber es gibt einfach zu viel zu erklären. Um seine Lösung mit attach und sync arbeiten zu lassen, müssen wir einige hässliche Dinge tun.

Das Problem

Lassen Sie uns zunächst das Problem mit seiner Lösung identifizieren. Seine Getter und Setter funktionieren, aber die anglo-to-Many-Beziehung verwendet das Pivot-Modell nicht, wenn sync, attach oder detach ausgeführt wird. Dies bedeutet, dass jedes Mal, wenn wir einen dieser Parameter mit dem Parameter $attributes aufrufen, die nicht mutierten Daten in die Datenbankspalte übernommen werden.

// This will skip the mutator on our extended Pivot class 
$user->workspaces()->attach($workspace, ['role' => 'new role value']); 

Wir konnte nur versuchen, sich daran zu erinnern, dass jedes Mal, wenn wir eine von diesen nennen wir nicht den zweiten Parameter verwenden können, die die mutierten Daten zu befestigen und rufen Sie einfach updateExistingPivot mit den Daten, die mutiert werden müssen.So wäre ein attach sein, was Patricus erklärte:

$user->workspaces()->attach($workspace); 
$user->workspaces()->updateExistingPivot($workspaceId, ['role' => 'new role value']); 

und wir konnten nie die richtige Art und Weise der Weitergabe der Dreh als attach zweiten Parameter im ersten Beispiel gezeigt Methoden-Attribute verwenden. Dies führt zu mehr Datenbank-Anweisungen und Code-Fäulnis, weil Sie immer daran denken müssen, nicht den normalen Weg zu gehen. Sie könnten später zu ernsthaften Problemen kommen, wenn Sie annehmen, dass jeder Entwickler oder selbst Sie nur wissen, die Methode attach nicht mit dem zweiten Parameter zu verwenden, wie es beabsichtigt war.

Die Lösung (ungetestet und unvollkommen)

Zur Anzeige attach an den Schwenksäulen mit dem Mutator rufen Sie etwas verrückt erstreckt tun müssen. Ich habe das nicht getestet, aber es kann Sie auf den richtigen Weg bringen, wenn Sie Lust haben, es zu versuchen. Wir müssen zuerst unsere eigenen Beziehungsklasse erstellen, die BelongsToMany und implementiert unsere eigene attach Methode erweitert:

use Illuminate\Database\Eloquent\Relations\BelongsToMany; 

class UserWorkspaceBelongsToMany extends BelongsToMany { 
    public function attach($id, array $attributes = [], $touch = true) 
    { 
     $role = $attributes['role']; 
     unset($attributes['role']); 
     parent::attach($id, $attributes, $touch); 
     $this->updateExistingPivot($id, ['role' => $role], $touch); 
    } 
    // You will need sync here too 
} 

Jetzt müssen wir jedes Model::belongsToMany unsere neue UserWorkspaceBelongsToMany Klasse anstelle des normalen BelongsToMany nutzen machen. Wir tun dies, indem Sie die belongsToMany in unserem User und Workspace-Klasse spöttisch:

// put this in the User and Workspace Class 
public function userWorkspaceBelongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null) 
{ 
    if (is_null($relation)) { 
     $relation = $this->getBelongsToManyCaller(); 
    } 

    $foreignKey = $foreignKey ?: $this->getForeignKey(); 

    $instance = new $related; 

    $otherKey = $otherKey ?: $instance->getForeignKey(); 

    if (is_null($table)) { 
     $table = $this->joiningTable($related); 
    } 

    $query = $instance->newQuery(); 

    return new UserWorkspaceBelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); 
} 

Wie Sie sehen können, rufen wir noch die Datenbank mehr, aber wir müssen über jemanden keine Sorge attach mit den Dreh Attribute aufrufen und Sie werden nicht mutiert.

Jetzt verwenden, die in Ihrem Modell anstelle des normalen belongsToMany:

class User extends Model { 
    public function workspaces() { 
     return $this->userWorkspaceBelongsToMany('App\Models\Workspace')->withPivot('role'); 
    } 
} 

class Workspace extends Model { 
    public function users() { 
     return $this->userWorkspaceBelongsToMany('App\Models\User')->withPivot('role'); 
    } 
} 
+0

Sie schreiben wirklich hart auf die 'UserWorkspaceBelongsToMany' Klasse. – lcjury