Modellverein


Eloquent: Assoziation

Einführung

Datenbanktabellen stehen normalerweise in Beziehung zueinander. Beispielsweise kann ein Blog-Beitrag viele Kommentare enthalten oder eine Bestellung kann einem Benutzer entsprechen, der die Bestellung aufgegeben hat. Beredt Vereinfacht die Verwaltung und Nutzung dieser Zuordnungen und unterstützt mehrere Arten von Zuordnungen:

Assoziationen definieren

Eloquente Assoziationen werden als Methoden in Eloquent-Modellklassen dargestellt. Wie das Eloquent-Modell selbst können Assoziationen auch als leistungsstarker Builder für Abfrageanweisungen verwendet werden und leistungsstarke Kettenaufrufe und Abfragefunktionen bereitstellen. Beispielsweise können wir eine Einschränkung an den verketteten Aufruf der posts-Assoziation anhängen:

$user->posts()->where('active', 1)->get();

Aber bevor wir uns mit der Verwendung von Assoziationen befassen, lernen wir, wie man jeden Assoziationstyp definiert.

Eins-zu-eins

Eins-zu-eins ist die grundlegendste Beziehung. Beispielsweise könnte ein User-Modell mit einem Phone-Modell verknüpft sein. Um diese Assoziation zu definieren, müssen wir eine User-Methode im phone-Modell schreiben. Rufen Sie die phone-Methode innerhalb der hasOne-Methode auf und geben Sie ihr Ergebnis zurück:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model{  
      /**
     * Get the phone record associated with the user.
     */   
      public function phone()   
       {       
            return $this->hasOne('App\Phone');  
         }
     }

hasOne Der erste Parameter der Methode ist der Klassenname des zugehörigen Modells. Sobald die Modellzuordnung definiert ist, können wir die dynamischen Eigenschaften von Eloquent verwenden, um die zugehörigen Datensätze abzurufen. Dynamische Eigenschaften ermöglichen Ihnen den Zugriff auf relationale Methoden genau wie im Modell definierte Eigenschaften:

$phone = User::find(1)->phone;

Eloquent ermittelt den Fremdschlüsselnamen basierend auf dem Modellnamen. In diesem Fall wird automatisch davon ausgegangen, dass das Phone-Modell einen user_id-Fremdschlüssel hat. Wenn Sie diese Konvention außer Kraft setzen möchten, können Sie einen zweiten Parameter an die hasOne-Methode übergeben:

return $this->hasOne('App\Phone', 'foreign_key');

Darüber hinaus geht Eloquent davon aus, dass der Wert des Fremdschlüssels gleich dem Wert der übergeordneten ID ist (bzw benutzerdefinierter $primaryKey)-Spaltenabgleich. Mit anderen Worten: Eloquent sucht in der Spalte „user_id“ des Telefondatensatzes nach einem Wert, der mit der Spalte „id“ der Tabelle „Benutzer“ übereinstimmt. Wenn Sie möchten, dass die Zuordnung einen anderen benutzerdefinierten Schlüsselnamen als id verwendet, können Sie den dritten Parameter an die hasOne-Methode übergeben:

return $this->hasOne('App\Phone', 'foreign_key', 'local_key');

Definieren Sie die umgekehrte Zuordnung

Wir Auf das User-Modell kann bereits über das Phone-Modell zugegriffen werden. Definieren wir nun eine weitere Zuordnung für das Modell Phone, die uns Zugriff auf das Modell User gewährt, dem das Telefon gehört. Wir können eine umgekehrte Assoziation mithilfe der hasOne-Methode definieren, die der belongsTo-Methode entspricht:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Phone extends Model{  
      /**
     * 获得拥有此电话的用户
     */  
      public function user()  
        {      
          return $this->belongsTo('App\User'); 
         }
      }

Im obigen Beispiel versucht Eloquent, Phone mit user_id im User-Modell abzugleichen id am Modell. Der Standard-Fremdschlüsselname wird ermittelt, indem der Name der Beziehungsmethode überprüft und _id als Suffixname verwendet wird. Wenn der Fremdschlüssel des Phone-Modells jedoch nicht user_id ist, kann ein benutzerdefinierter Schlüsselname als zweiter Parameter an die belongsTo-Methode übergeben werden:

/**
 * 获得拥有此电话的用户
 */
 public function user(){ 
    return $this->belongsTo('App\User', 'foreign_key');
   }

Wenn dies beim übergeordneten Modell nicht der Fall ist verwenden id Als Primärschlüssel oder wenn Sie verschiedene Felder zum Verbinden untergeordneter Modelle verwenden möchten, können Sie belongsTo übergeben Die Methode übergibt den dritten Parameter in Form der Angabe des benutzerdefinierten Schlüssels der übergeordneten Datentabelle:

/**
 * 获得拥有此电话的用户
 */
 public function user(){ 
    return $this->belongsTo('App\User', 'foreign_key', 'other_key');
  }

Eins-zu-viele

„Eins-zu-viele“-Assoziation wird verwendet, um ein einzelnes Modell so zu definieren, dass es eine beliebige Anzahl anderer verknüpfter Modelle hat. Beispielsweise kann ein Blog-Beitrag unendlich viele Kommentare enthalten. Wie alle anderen Eloquent-Beziehungen wird eine Eins-zu-Viele-Beziehung durch Schreiben einer Methode im Eloquent-Modell definiert:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Post extends Model{  
      /**
     * 获取博客文章的评论
     */  
      public function comments()   
       {     
          return $this->hasMany('App\Comment');  
       }
  }

Denken Sie daran, dass Eloquent automatisch das Fremdschlüsselattribut des Comment-Modells bestimmt. Konventionell verwendet Eloquent die „Snake Case“-Form des Modellnamens sowie das Suffix _id als Fremdschlüsselfeld. Daher geht Eloquent im obigen Beispiel davon aus, dass der Fremdschlüssel des Modells, der Comment entspricht, Post ist. post_id

Sobald die Beziehung definiert ist, kann die Sammlung von Kommentaren durch Zugriff auf das

-Attribut des Modells abgerufen werden. Denken Sie daran: Da Eloquent „dynamische Eigenschaften“ bereitstellt, können wir auf die Beziehungsmethode genauso zugreifen wie auf die Eigenschaften des Modells: Post

$comments = App\Post::find(1)->comments;foreach ($comments as $comment) {    //}
comments Da natürlich alle Beziehungen auch als Builder für Abfrageanweisungen verwendet werden können, können Sie verkettete Aufrufe verwenden um der

-Methode zusätzliche Einschränkungen hinzuzufügen:

$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();
comments Genau wie die

-Methode können Sie auch verwenden

-Methode überschreiben Sie die Standardfremdschlüssel und lokalen Schlüssel, indem Sie zusätzliche Parameter übergeben: hasOne

return $this->hasMany('App\Comment', 'foreign_key');
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
hasMany

One-to-many (reverse)

Jetzt können wir alle Kommentare eines Artikels abrufen und dann eine Zuordnung definieren, um den Artikel über die Kommentare zu erhalten. Diese Assoziation ist die umgekehrte Assoziation der

-Assoziation. Sie muss mit der

-Methode im untergeordneten Modell definiert werden: hasMany

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Comment extends Model{ 
    /**
     * 获取此评论所属文章
     */   
     public function post()   
      {      
        return $this->belongsTo('App\Post');   
       }
   }
belongsToNachdem diese Beziehung definiert ist, können wir auf die

-Modelle zugreifen

Verwenden Sie dieses „dynamische Attribut“, um das zugehörige Comment abzurufen Modelliert: post

$comment = App\Comment::find(1);
echo $comment->post->title;
Post Im obigen Beispiel versucht Eloquent, das

des

-Modells mit dem Comment des post_id-Modells abzugleichen. Der Standard-Fremdschlüsselname wird von Eloquent anhand des Assoziationsnamens bestimmt, gefolgt von _ und dem Primärschlüsselfeldnamen als Suffix. Wenn der Fremdschlüssel des Post-Modells natürlich nicht id ist, können Sie den benutzerdefinierten Schlüsselnamen als zweiten Parameter an die Comment-Methode übergeben: post_id

/**
 * 获取此评论所属文章
 */
 public function post(){
     return $this->belongsTo('App\Post', 'foreign_key');
   }
belongsToWenn dies beim übergeordneten Modell nicht der Fall ist verwenden

Als Primärschlüssel oder wenn Sie verschiedene Felder zum Verbinden untergeordneter Modelle verwenden möchten, können Sie

übergeben Die Methode übergibt den dritten Parameter in Form der Angabe des benutzerdefinierten Schlüssels der übergeordneten Datentabelle: id

/**
 * 获取此评论所属文章
 */
 public function post(){ 
    return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
  }
belongsTo

Viele-zu-viele

Viele-zu-viele-Beziehungen sind etwas komplexer als hasOne- und hasMany-Beziehungen. Beispielsweise kann ein Benutzer viele Rollen haben und diese Rollen werden von anderen Benutzern geteilt. Beispielsweise könnten viele Benutzer die Rolle „Administrator“ haben. Um diese Zuordnung zu definieren, sind drei Datenbanktabellen erforderlich: users, roles und role_user. Die role_user-Tabelle ist in alphabetischer Reihenfolge nach den beiden zugehörigen Modellen benannt und enthält die Felder user_id und role_id.

Many-to-many-Assoziation wird durch Aufrufen des von der internen Methode belongsToMany zurückgegebenen Ergebnisses definiert. Beispielsweise definieren wir die Methode User im Modell roles:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;class User extends Model{  
      /**
     * 用户拥有的角色
     */   
      public function roles()   
       {      
         return $this->belongsToMany('App\Role');  
        }
     }

Sobald die Zuordnung definiert ist, können Sie roles übergeben Dynamische Attribute erhalten Benutzerrollen:

$user = App\User::find(1);
foreach ($user->roles as $role) {  
  //
}

Natürlich können Sie wie bei allen anderen Assoziationsmodellen die Methode roles verwenden, um der Abfrageanweisung mithilfe von Kettenaufrufen Einschränkungen hinzuzufügen:

$roles = App\User::find(1)->roles()->orderBy('name')->get();

Wie zuvor Wie bereits erwähnt, verkettet Eloquent die Namen der beiden relationalen Modelle in alphabetischer Reihenfolge, um den Tabellennamen der relationalen Join-Tabelle zu ermitteln. Natürlich können Sie diese Konvention auch nicht verwenden und einfach den zweiten Parameter an die belongsToMany-Methode übergeben:

return $this->belongsToMany('App\Role', 'role_user');

Neben der Anpassung des Tabellennamens der Verbindungstabelle können Sie auch zusätzliche Parameter an < übergeben 🎜> Methode zum Definieren des Schlüsselnamens des Felds in der Tabelle. Der dritte Parameter ist der Fremdschlüsselname des Modells, das diese Zuordnung in der Verbindungstabelle definiert, und der vierte Parameter ist der Fremdschlüsselname eines anderen Modells in der Verbindungstabelle: belongsToMany

return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');

Definition Reverse Association

Um eine Viele-zu-Viele-Reverse-Assoziation zu definieren, müssen Sie nur die Methode

im Assoziationsmodell aufrufen. Wir definieren die belongsToMany-Methode im Role-Modell: users

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Role extends Model{    
    /**
     * 拥有此角色的用户。
     */   
      public function users()   
       {      
         return $this->belongsToMany('App\User');  
        }
      }

Wie Sie sehen können, ist sie genau die gleiche wie die im

-Modell definierte, außer dass das Modell als < eingeführt wird 🎜>. Da wir die Methode AppUser wiederverwendet haben, gelten hier auch der Tabellenname der benutzerdefinierten Join-Tabelle und der Feldname des Schlüssels in der benutzerdefinierten Join-Tabelle. UserbelongsToMany

Holen Sie sich die Zwischentabellenfelder

Wie Sie gerade erfahren haben, benötigen viele-zu-viele-Beziehungen eine Zwischentabelle, um Unterstützung zu bieten. Angenommen, unser User-Objekt ist mit mehreren Role-Objekten verknüpft. Nachdem Sie diese zugeordneten Objekte erhalten haben, können Sie das Attribut pivot des Modells verwenden, um auf die Daten in der Zwischentabelle zuzugreifen:

$user = App\User::find(1);
foreach ($user->roles as $role) { 
   echo $role->pivot->created_at;
  }

Es ist zu beachten, dass jedes Role Modellobjekt, das wir erhalten, automatisch <🎜 zugewiesen wird > Eigenschaft, die ein Modellobjekt der Zwischentabelle darstellt und wie andere Eloquent-Modelle verwendet werden kann. pivot

Standardmäßig enthält das

-Objekt nur die Primärschlüssel der beiden verwandten Modelle. Wenn Ihre Zwischentabelle weitere zusätzliche Felder enthält, müssen Sie dies bei der Definition der Beziehung explizit angeben: pivot

return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

Wenn Sie möchten, dass die Zwischentabelle die Zeitstempel

und created_at automatisch verwaltet, fügen Sie beim Definieren der Zuordnung updated_at hinzu Die Methode lautet: withTimestamps

return $this->belongsToMany('App\Role')->withTimestamps();

Benutzerdefinierter

Attributnamepivot

Wie bereits erwähnt, kann über das Attribut

auf Attribute aus der Zwischentabelle zugegriffen werden. Es steht Ihnen jedoch frei, den Namen dieser Eigenschaft anzupassen, um ihre Verwendung in Ihrer Anwendung besser widerzuspiegeln. pivot

Wenn Ihre App beispielsweise Benutzer enthält, die sich anmelden können, besteht möglicherweise eine Viele-zu-Viele-Beziehung zwischen Benutzern und Blogs. Wenn dies der Fall ist, möchten Sie den Zwischentabellen-Accessor möglicherweise

anstelle von subscription benennen. Dies kann mithilfe der pivot-Methode beim Definieren der Beziehung erfolgen: as

return $this->belongsToMany('App\Podcast')           
     ->as('subscription')                
     ->withTimestamps();

Nach der Definition können Sie mit einem benutzerdefinierten Namen auf die Zwischentabellendaten zugreifen:

$users = User::with('podcasts')->get();
foreach ($users->flatMap->podcasts as $podcast) { 
   echo $podcast->subscription->created_at;
 }

durch die Zwischentabelle Filterbeziehung

Beim Definieren einer Beziehung können Sie auch die Methoden

und wherePivot zum Filtern verwenden wherePivotIn Zurückgegebenes Ergebnis: belongsToMany

return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);

Zwischentabellenmodell definieren

Benutzerdefiniertes Zwischentabellenmodell definieren
Wenn Sie ein benutzerdefiniertes Modell zur Darstellung der Zwischentabelle in der Assoziationsbeziehung definieren möchten, können Sie beim Definieren die Methode using aufrufen Verein. Benutzerdefinierte 多对多-Zwischentabellenmodelle müssen von der IlluminateDatabaseEloquentRelationsPivot-Klasse ausgehen, und benutzerdefinierte 多对多(多态)-Zwischentabellenmodelle müssen die IlluminateDatabaseEloquentRelationsMorphPivot-Klasse erben. Zum Beispiel:
Wenn wir die Zuordnung des Rollenmodells schreiben, verwenden wir das benutzerdefinierte Zwischentabellenmodell UserRole

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Role extends Model{   
     /**
     * 拥有此角色的所有用户
     */   
     public function users() 
        {   
             return $this->belongsToMany('App\User')->using('App\UserRole'); 
        }
   }

Beim Definieren des UserRole-Modells müssen wir die Klasse Pivot erweitern :

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Relations\Pivot;
    class UserRole extends Pivot{   
     //
  }

Sie können eine Kombination aus using und withPivot verwenden, um Spalten aus einer Zwischentabelle abzurufen. Wenn Sie beispielsweise die Spaltennamen an die Methode withPivot übergeben, können Sie die Spalten UserRole und created_by aus der Zwischentabelle updated_by abrufen.

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Role extends Model{   
     /**
     * 拥有此角色的用户。
     */  
       public function users()  
         {     
            return $this->belongsToMany('App\User')                   
                 ->using('App\UserRole')                        
                 ->withPivot([                         
                    'created_by',                            
                    'updated_by'                      
                    ]);  
            }
       }

Benutzerdefiniertes Relay-Modell mit inkrementierender ID

Wenn Sie eine Viele-zu-Viele-Beziehung mit einem benutzerdefinierten Relay-Modell definieren und dieses Das Relay-Modell über eine automatische Inkrementierter Primärschlüssel. Sie sollten sicherstellen, dass die benutzerdefinierte Relay-Modellklasse ein incrementing-Attribut mit dem Wert true definiert :

/**
 * 标识 ID 是否自增。
 *
 * @var bool
 */
 public $incrementing = true;

Remote-Eins-zu-Eins-Beziehung

Remote-Eins-zu-Eins-Zuordnung wird durch eine implementiert Zwischenassoziationsmodell.
Wenn beispielsweise jeder Anbieter einen Benutzer hat und jeder Benutzer mit einem Benutzerverlauf verknüpft ist, kann der Anbieter über den Benutzer auf den Benutzerverlauf zugreifen. Schauen wir uns die Datenbank an, die zum Definieren dieser Beziehungstabelle erforderlich ist:

suppliers
    id - integer
users
    id - integer
    supplier_id - integer

history
    id - integer
    user_id - integer

Obwohl die history-Tabelle kein supplier_id enthält, kann die hasOneThrough-Beziehung Zugriff auf die Benutzerhistorie ermöglichen, um auf das Lieferantenmodell zuzugreifen. Nachdem wir nun die Tabellenstruktur der Beziehung untersucht haben, definieren wir die entsprechende Methode für das Supplier-Modell:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Supplier extends Model{   
     /**
     * 用户的历史记录。
     */  
       public function userHistory()  
         {      
           return $this->hasOneThrough('App\History', 'App\User');  
          }
       }

Der erste Parameter, der an die hasOneThrough-Methode übergeben wird, ist der Name des gewünschten Modells Zugriff und der zweite Der erste Parameter ist der Name des Zwischenmodells.

Bei der Durchführung verwandter Abfragen werden normalerweise die herkömmlichen Fremdschlüsselnamen von Eloquent verwendet. Wenn Sie die zugehörigen Schlüssel anpassen möchten, können Sie dies tun, indem Sie den dritten und vierten Parameter an die Methode hasOneThrough übergeben. Der dritte Parameter stellt den Fremdschlüsselnamen des Zwischenmodells dar und der vierte Parameter stellt den Fremdschlüssel des dar endgültiger Name. Der fünfte Parameter stellt den lokalen Schlüsselnamen dar, während der sechste Parameter den lokalen Schlüsselnamen des Zwischenmodells darstellt:

class Supplier extends Model{  
  /**
     * 用户的历史记录。
     */   
     public function userHistory()   
      {     
         return $this->hasOneThrough(         
            'App\History',            
            'App\User',            
            'supplier_id', // 用户表外键            
             'user_id', // 历史记录表外键            
             'id', // 供应商本地键            
             'id' // 用户本地键     
              );   
          }
      }

Remote-Eins-zu-Viele-Assoziation

Remote-Eins-zu-Viele-Assoziation bietet eine bequeme und kurze Möglichkeit, Assoziationen auf Remote-Ebene über Zwischenassoziationen zu erhalten. Beispielsweise kann ein Country-Modell über Zwischenmodelle User mehrere Post-Modelle erhalten. In diesem Beispiel können Sie ganz einfach alle Blogbeiträge aus einem bestimmten Land sammeln. Werfen wir einen Blick auf die Datentabelle, die zum Definieren dieser Zuordnung erforderlich ist:

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string

Obwohl die Tabelle posts das Feld country_id nicht enthält, ermöglicht uns die Zuordnung hasManyThrough den Zugriff auf eines über $country->posts Alle Benutzerartikel unter dem Land. Um diese Abfrage abzuschließen, überprüft Eloquent zunächst das Feld users der Zwischentabelle country_id und nachdem alle übereinstimmenden Benutzer-IDs gefunden wurden, verwendet Eloquent diese IDs, um die Suche in der Tabelle posts abzuschließen.

Da wir nun die Datentabellenstruktur kennen, die zum Definieren dieser Zuordnung erforderlich ist, definieren wir sie im Country Modell:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Country extends Model{   
     /**
     * 当前国家所有文章。
     */   
      public function posts()  
        {    
            return $this->hasManyThrough('App\Post', 'App\User'); 
         }
     }

hasManyThrough Methodennr. Ein Parameter ist der Name der Modell, auf das wir letztendlich zugreifen möchten, während der zweite Parameter der Name des Zwischenmodells ist.

Bei der Durchführung verwandter Abfragen werden normalerweise die herkömmlichen Fremdschlüsselnamen von Eloquent verwendet. Wenn Sie die zugehörigen Schlüssel anpassen möchten, können Sie dies tun, indem Sie den dritten und vierten Parameter an die Methode hasManyThrough übergeben. Der dritte Parameter stellt den Fremdschlüsselnamen des Zwischenmodells dar und der vierte Parameter stellt den Fremdschlüssel des dar endgültiger Name. Der fünfte Parameter stellt den lokalen Schlüsselnamen dar, während der sechste Parameter den lokalen Schlüsselnamen des Zwischenmodells darstellt:

class Country extends Model{ 
   public function posts()   
    {     
       return $this->hasManyThrough(        
           'App\Post',            
           'App\User',            
           'country_id', // 用户表外键            
           'user_id', // 文章表外键            
           'id', // 国家表本地键            
           'id' // 用户表本地键      
           );  
      }
  }

Polymorphe Assoziation

Polymorphe Assoziationen ermöglichen die Unterordnung eines Zielmodells mehreren Modellen mit einer einzigen Assoziation.

Eins-zu-eins (polymorph)

Tabellenstruktur

Eine polymorphe Eins-zu-eins-Assoziation ähnelt einer einfachen Eins-zu-eins-Assoziation, das Zielmodell kann jedoch zu mehreren Modellen in einer einzelnen Assoziation gehören. Beispielsweise könnten die Blogs Post und User eine Beziehung zum Image-Modell haben. Die Verwendung einer Eins-zu-Eins-polymorphen Zuordnung ermöglicht die Verwendung einer eindeutigen Liste von Bildern sowohl für Blogbeiträge als auch für Benutzerkonten. Schauen wir uns zunächst die Tabellenstruktur an:

posts
    id - integer
    name - string

users
    id - integer
    name - string

images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string

Achten Sie besonders auf die Spalten images und imageable_id der Tabelle imageable_type. Die Spalte imageable_id enthält den ID-Wert des Beitrags oder Benutzers, während die Spalte imageable_type den Klassennamen des übergeordneten Modells enthält. Eloquent verwendet die Spalte imageable, um beim Zugriff auf imageable_type den „Typ“ des übergeordneten Modells zu bestimmen.

Modellstruktur

Als nächstes schauen wir uns die zugehörige Modelldefinition an:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Image extends Model{   
     /**
     * 获取拥有此图片的模型。
     */    
     public function imageable()  
       {     
          return $this->morphTo();  
        }
       }
     class Post extends Model{  
    /**
     * 获取文章图片。
     */    
     public function image()  
       {       
        return $this->morphOne('App\Image', 'imageable');   
        }
      }
   class User extends Model{   
    /**
     * 获取用户图片。
     */   
     public function image()   
     {     
       return $this->morphOne('App\Image', 'imageable'); 
     }
    }

Abrufen der Zuordnung

Sobald die Tabelle und das Modell definiert sind, kann über das Modell auf diese Zuordnung zugegriffen werden. Um beispielsweise das Artikelbild abzurufen, können Sie das dynamische Attribut image verwenden:

$post = App\Post::find(1);
$image = $post->image;

Sie können das übergeordnete Modell auch aus dem polymorphen Modell abrufen, indem Sie auf den Methodennamen zugreifen, der den Aufruf morphTo ausführt. In diesem Fall handelt es sich um die Image-Methode des imageable-Modells. Wir können also wie eine dynamische Eigenschaft auf diese Methode zugreifen:

$image = App\Image::find(1);
$imageable = $image->imageable;

Image Die imageable-Zuordnung des Modells gibt entweder eine Post- oder eine User-Instanz zurück, je nachdem, um welches Modell es sich bei dem Bildattribut handelt.

Eins-zu-viele (polymorph)

Tabellenstruktur

Eine Eins-zu-Viele-Assoziation ähnelt einer einfachen Eins-zu-Viele-Assoziation, allerdings kann das Zielmodell zu mehreren Modellen in einer einzigen Assoziation gehören. Gehen Sie davon aus, dass Benutzer in der Anwendung gleichzeitig Artikel und Videos „kommentieren“ können. Mithilfe polymorpher Assoziationen können diese Situationen gleichzeitig mit einer einzigen comments-Tabelle erfüllt werden. Werfen wir zunächst einen Blick auf die Tabellenstruktur, die zum Aufbau dieser Beziehung verwendet wird:

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

Modellstruktur

Als nächstes schauen wir uns den Aufbau dieser Beziehung an Modelldefinition der Assoziation:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Comment extends Model{   
     /**
     * 获取拥有此评论的模型。
     */   
      public function commentable() 
         {      
           return $this->morphTo();   
         }
      }
    class Post extends Model{   
    /**
     * 获取此文章的所有评论。
     */  
      public function comments()  
        {    
            return $this->morphMany('App\Comment', 'commentable');  
          }
       }
     class Video extends Model{  
    /**
     * 获取此视频的所有评论。
     */   
     public function comments()  
       {    
           return $this->morphMany('App\Comment', 'commentable');  
       }
    }

Zuordnung abrufen

Sobald die Datenbanktabelle und das Modell definiert sind, kann über das Modell auf die Assoziation zugegriffen werden. Sie können beispielsweise mit dem dynamischen Attribut comments auf alle Kommentare zu einem Artikel zugreifen:

$post = App\Post::find(1);foreach ($post->comments as $comment) {
    //
  }

Sie können das Modell, zu dem er gehört, auch aus dem polymorphen Modell abrufen, indem Sie auf den Namen der Methode zugreifen, die das < ausführt 🎜> anrufen. In diesem Fall handelt es sich um die morphTo-Methode des Comment-Modells: commentable

$comment = App\Comment::find(1);
$commentable = $comment->commentable;

Die Comment-Zuordnung des Modells gibt entweder eine commentable- oder eine Post-Instanz zurück, je nachdem, zu welchem ​​Kommentar sie gehört zum Modellieren. Video

Many-to-many (polymorph)

Tabellenstruktur

Many-to-many polymorphes Assoziationsverhältnis

und morphOne Der Zusammenhang ist etwas komplizierter. Beispielsweise können die Blog-Modelle morphMany und Post eine polymorphe Beziehung zum Video-Modell aufweisen. Die Verwendung einer polymorphen Viele-zu-Viele-Assoziation ermöglicht die gemeinsame Nutzung von Blogbeiträgen und Videos mithilfe eines eindeutigen Tags. Das Folgende ist die Tabellenstruktur einer polymorphen Viele-zu-Viele-Assoziation: Tag

posts
    id - integer
    name - string

videos
    id - integer
    name - string

tags
    id - integer
    name - string

taggables
    tag_id - integer
    taggable_id - integer
    taggable_type - string

Modellstruktur

Als nächstes definieren Sie die Assoziation für das Modell. Sowohl das

- als auch das Post-Modell verfügen über Video-Methoden, die die morphToMany-Methode der Eloquent-Basisklasse aufrufen: tags

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Post extends Model{   
     /**
     * 获取文章的所有标签。
     */   
      public function tags()  
        {     
           return $this->morphToMany('App\Tag', 'taggable');  
         }
      }

Definieren Sie die umgekehrte Assoziationsbeziehung

Als nächstes müssen Sie eine Methode für jedes Assoziationsmodell im Tag-Modell definieren. In diesem Beispiel definieren wir die posts-Methode und die videos-Methode:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Tag extends Model{ 
     /**
     * 获取被打上此标签的所有文章。
     */   
      public function posts() 
         {    
             return $this->morphedByMany('App\Post', 'taggable');  
          }   
     /**
     * 获取被打上此标签的所有视频。
     */   
      public function videos()  
        {       
         return $this->morphedByMany('App\Video', 'taggable');  
         }
     }

Erhalten Sie die Zuordnung

Sobald die Datenbanktabelle und das Modell definiert sind, Greifen Sie über das Modell auf die Zuordnung zu. Sie können beispielsweise das dynamische Attribut tags verwenden, um auf alle Tags des Artikels zuzugreifen:

$post = App\Post::find(1);foreach ($post->tags as $tag) { 
   //
}

Sie können auch auf den Methodennamen zugreifen, der den Methodenaufruf morphedByMany ausführt, um das Modell abzurufen, zu dem es gehört das polymorphe Modell. In diesem Beispiel handelt es sich um die Methode Tag oder posts des Modells videos. Auf diese Methoden kann wie auf dynamische Eigenschaften zugegriffen werden:

$tag = App\Tag::find(1);foreach ($tag->videos as $video) {
    //
 }

Benutzerdefinierter polymorpher Typ

Standardmäßig Laravel Store zugeordnetes Modell Typen unter Verwendung vollständig qualifizierter Klassennamen. Da im obigen Eins-zu-viele-Beispiel Comment entweder zu einem Post oder einem Video gehören kann, lautet der Standardwert für commentable_type jeweils AppPost bzw. AppVideo. Möglicherweise möchten Sie jedoch die Datenbank von der internen Struktur Ihrer Anwendung entkoppeln. In diesem Fall können Sie eine „Morph Map“ definieren, um Eloquent anzuweisen, einen benutzerdefinierten Namen anstelle des entsprechenden Klassennamens zu verwenden:

use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([ 
   'posts' => 'App\Post',    
   'videos' => 'App\Video',
 ]);

kann in der AppServiceProvider-Funktion von boot oder in der Funktion „Erstellen“ registriert werden ein separater Dienstleister. morphMap

Abfragebeziehungen

Da alle Arten von Eloquent-Beziehungen durch Methoden definiert werden, können Sie diese Methoden stattdessen dort aufrufen Es ist nicht erforderlich, die zugehörige Abfrage tatsächlich auszuführen. Darüber hinaus fungieren alle Eloquent-Beziehungstypen als Abfrageersteller, sodass Sie über eine Aufrufkette kontinuierlich Einschränkungen hinzufügen können, bevor Sie SQL in der Datenbank ausführen.

Angenommen, das

-Modell eines Blogsystems hat viele zugehörige User-Modelle: Post

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model{    
    /**
     * 获取该用户的所有文章。
     */  
     public function posts()  
       {     
          return $this->hasMany('App\Post');   
        }
    }

Sie können die

-Zuordnungen abfragen und ihnen zusätzliche Einschränkungen hinzufügen: posts

$user = App\User::find(1);
$user->posts()->where('active', 1)->get();

Sie können jeden Abfrage-Builder für die Zuordnung verwenden Methoden finden Sie in der Dokumentation zum Abfrage-Generator, um zu erfahren, welche Methoden für Sie nützlich sein könnten.

Relationsmethoden vs. dynamische Eigenschaften

Wenn Sie Ihrer Eloquent-Relationsabfrage keine zusätzlichen Einschränkungen hinzufügen müssen, können Sie auf die Relation wie auf eine Eigenschaft zugreifen. Wenn Sie beispielsweise weiterhin die Beispielmodelle User und Post verwenden, können Sie auf alle Artikel des Benutzers wie folgt zugreifen:

$user = App\User::find(1);
foreach ($user->posts as $post) {
    //
  }

Dynamische Eigenschaften werden „verzögert geladen“, was bedeutet, dass sie nur geladen werden, wenn Sie greifen tatsächlich auf die zugehörigen Daten zu. Daher verwenden Entwickler häufig Vorladen, um Beziehungen vorab zu laden, von denen sie wissen, dass sie nach dem Laden des Modells darauf zugreifen werden. Bei SQL-Abfragen, die beim Laden von Modellzuordnungen ausgeführt werden müssen, reduziert Eager Loading die Anzahl der Abfrageausführungen erheblich.

Bestehende Beziehungen abfragen

Beim Zugriff auf Modelldatensätze möchten Sie möglicherweise die Abfrageergebnisse basierend auf der Existenz von einschränken die Beziehung. Wenn Sie beispielsweise alle Artikel mit mindestens einem Kommentar erhalten möchten, können Sie den Assoziationsnamen an die Methoden has und orHas übergeben:

// 获取至少存在一条评论的所有文章...
$posts = App\Post::has('comments')->get();

Außerdem können Sie den Operator und die Menge weiter angeben Passen Sie die Abfrage an:

// 获取评论超过三条的文章...
$posts = App\Post::has('comments', '>=', 3)->get();

kann auch die „Punkt“-Syntax verwenden, um verschachtelte has-Anweisungen zu erstellen. Sie können beispielsweise Artikel mit mindestens einem Kommentar erhalten und abstimmen:

// 获取拥有至少一条带有投票评论的文章...
$posts = App\Post::has('comments.votes')->get();

Wenn Sie mehr Funktionalität benötigen, können Sie die Methoden whereHas und orWhereHas verwenden, um die „Where“-Bedingung auf das < zu setzen 🎜> Abfrage. Mit diesen Methoden können Sie benutzerdefinierte Einschränkungen zur Zuordnung hinzufügen, z. B. die Überprüfung des Kommentarinhalts: has

use Illuminate\Database\Eloquent\Builder;
// 获取至少带有一条评论内容包含 foo% 关键词的文章...
$posts = App\Post::whereHas('comments', function ($query)
 { 
    $query->where('content', 'like', 'foo%');})->get();
    // 获取至少带有十条评论内容包含 foo% 关键词的文章...
    $posts = App\Post::whereHas('comments', function ($query)
     { 
        $query->where('content', 'like', 'foo%');
      }, '>=', 10)->get();

Abfrage nach nicht vorhandenen Zuordnungen

Beim Zugriff auf Modelldatensätze möchten Sie möglicherweise die Abfrageergebnisse basierend auf dem Nichtvorhandensein der Zuordnung einschränken. Angenommen, Sie möchten

Artikel erhalten, die keine Kommentare haben. Sie können dies tun, indem Sie den Assoziationsnamen an die Methoden und doesntHave übergeben: orDoesntHave

$posts = App\Post::doesntHave('comments')->get();

Wenn Sie mehr benötigen Funktionalität können Sie < verwenden. Die Methoden 🎜> und

fügen der whereDoesntHave-Abfrage „Where“-Bedingungen hinzu. Mit diesen Methoden können Sie der Zuordnung benutzerdefinierte Einschränkungen hinzufügen, z. B. das Erkennen von Kommentarinhalten: orWhereDoesntHave

use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments', function (Builder $query)
 {  
   $query->where('content', 'like', 'foo%');
 })->get();
doesntHave Sie können auch die „Punkt“-Syntax verwenden, um verschachtelte Zuordnungsabfragen durchzuführen. Die folgende Abfrage ruft beispielsweise Artikel mit Kommentaren von Autoren ab, die nicht gesperrt wurden:

use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments.author', function (Builder $query) 
{   
 $query->where('banned', 1);
})->get();

Zugehörige Modellanzahl

Wenn Sie nur die statistische Anzahl der zugehörigen Ergebnisse zählen möchten, ohne sie tatsächlich zu laden, können Sie die Methode withCount verwenden, die in der Spalte {relation}_count des platziert wird Ergebnismodell. Ein Beispiel lautet wie folgt:

$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
    echo $post->comments_count;
   }

Sie können „Zählungen“ zu mehreren Beziehungen hinzufügen, genau wie das Hinzufügen von Einschränkungen zu Abfragen:

$posts = App\Post::withCount(['votes', 'comments' => function ($query)
 { 
    $query->where('content', 'like', 'foo%');
  }])->get();
    echo $posts[0]->votes_count;echo $posts[0]->comments_count;

Sie können die Ergebnisse der Beziehungsanzahl auch mit einem Alias ​​versehen, was Ihnen das Hinzufügen ermöglicht „zählt“ auf derselben Beziehung. Mehrere Zählungen:

$posts = App\Post::withCount([
    'comments',    
    'comments as pending_comments_count' => function ($query) { 
           $query->where('approved', false);   
      }])->get();
   echo $posts[0]->comments_count;
    echo $posts[0]->pending_comments_count;

Wenn Sie withCount- und select-Abfragen zusammenfügen, achten Sie darauf, sie zu addieren select wird nach der Methode aufgerufen: withCount

$query = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;

Preloading

Beim Zugriff auf eine Eloquent-Assoziation als Eigenschaft, Die Assoziationsdaten werden „verzögert geladen“. Auf diese Weise werden die zugehörigen Daten erst beim ersten Zugriff auf die Eigenschaft tatsächlich geladen. Allerdings kann Eloquent beim Abfragen des übergeordneten Modells untergeordnete Beziehungen „vorab laden“. Durch eifriges Laden kann das N 1-Abfrageproblem gemildert werden. Um das N 1-Abfrageproblem zu veranschaulichen, betrachten Sie den Fall, in dem das

-Modell mit Book verknüpft ist: Author

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Book extends Model{  
      /**
     * 获取书籍作者。
     */ 
      public function author() 
         {    
             return $this->belongsTo('App\Author');   
          }
       }

Nun holen wir uns alle Bücher und ihre Autoren:

$books = App\Book::all();
foreach ($books as $book) 
{ 
   echo $book->author->name;
}

Diese Schleife führt eine Abfrage aus, um alle Bücher abzurufen, und führt dann für jedes Buch eine Abfrage aus, um den Autor abzurufen. Wenn wir 25 Bücher haben, führt diese Schleife 26 Abfragen aus: 1 zur Abfrage des Buchs und 25 zusätzliche Abfragen zur Abfrage des Autors jedes Buchs.

Glücklicherweise konnten wir Eager Loading verwenden, um den Vorgang auf nur zwei Abfragen zu reduzieren. Zum Zeitpunkt der Abfrage können Sie die Methode

verwenden, um die Zuordnungen anzugeben, die Sie vorab laden möchten: with

$books = App\Book::with('author')->get();
foreach ($books as $book) {
    echo $book->author->name;
  }

In diesem Beispiel wurden nur zwei Abfragen ausgeführt:

select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)

Mehrere Zuordnungen vorab laden

Manchmal müssen Sie möglicherweise mehrere verschiedene Zuordnungen in einem einzigen Vorgang vorab laden. Um dies zu erreichen, übergeben Sie einfach einen Array-Parameter, der aus mehreren zugehörigen Namen besteht, an die Methode

: with

$books = App\Book::with(['author', 'publisher'])->get();

Geschachteltes Vorladen

kann die „Punkt“-Syntax verwenden. Vorladen verschachtelt Verbände. Zum Beispiel das Vorabladen aller Buchautoren und ihrer Kontaktinformationen in einer eloquenten Aussage:

$books = App\Book::with('author.contacts')->get();

Vorabladen bestimmter Spalten

Es ist nicht immer notwendig, jede Spalte der Beziehung abzurufen . In diesem Fall können Sie mit Eloquent die Spalten angeben, die Sie für die Zuordnung erhalten möchten:

$users = App\Book::with('author:id,name')->get();

{note} Wenn Sie diese Funktion verwenden, achten Sie darauf, <🎜 in die Liste der abzurufenden Spalten aufzunehmen > Spalte.

id

Einschränkungen für das Vorladen hinzufügen

Manchmal möchten Sie möglicherweise eine Beziehung vorab laden und der Vorladeabfrage zusätzliche Abfragebedingungen hinzufügen, wie im folgenden Beispiel:

$users = App\User::with(['posts' => function ($query) { 
   $query->where('title', 'like', '%first%');
  }])->get();

In diesem Beispiel wird Eloquent dies tun Laden Sie nur die Artikel vor, deren Spalte title das Schlüsselwort first enthält. Sie können auch andere Abfrage-Builder-Methoden aufrufen, um den Vorladevorgang weiter anzupassen:

$users = App\User::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc');
  }])->get();

{note} Beim Einschränken des Vorladens können die Abfrage-Builder-Methoden limit und take nicht verwendet werden.

Vorladen

Vielleicht möchten Sie auch Eager Loading durchführen, nachdem das Modell geladen wurde. Wenn Sie beispielsweise verwandte Daten dynamisch laden möchten, ist die Methode load für Sie sehr nützlich:

$books = App\Book::all();
if ($someCondition) {
    $books->load('author', 'publisher');
  }

Wenn Sie die Abfrage beim Eager Loading bedingt einschränken möchten, können Sie sie in laden Form eines Arrays, der Schlüssel ist die entsprechende Assoziation, der Wert ist eine Closure-Abschlussfunktion, der Parameter des Abschlusses ist ein query Beispiel:

$books->load(['author' => function ($query) {
    $query->orderBy('published_date', 'asc');
   }]);

Wenn die Beziehung nicht geladen ist, können Sie die loadMissing-Methode verwenden:

public function format(Book $book){
    $book->loadMissing('author');    
    return [    
        'name' => $book->name,        
        'author' => $book->author->name   
       ];
   }

Nested Lazy Loading & morphTo

Wenn Sie die morphTo-Beziehung sowie die verschachtelten Beziehungen zu den verschiedenen Entitäten, die die Beziehung möglicherweise zurückgibt, schnell laden möchten, können Sie diese verwenden loadMorph Methode.

Diese Methode akzeptiert den Namen der morphTo-Beziehung als ersten Parameter und der zweite Parameter empfängt ein Modellarray und ein Beziehungsarray. Schauen Sie sich zur Veranschaulichung dieses Ansatzes das folgende Modellbeispiel an:

<?php
    use Illuminate\Database\Eloquent\Model;
    class ActivityFeed extends Model{   
     /**
     * Get the parent of the activity feed record.
     */   
   public function parentable() 
      {    
          return $this->morphTo(); 
       }
    }

Nehmen wir in diesem Beispiel an, dass die Modelle Event, Photo und Post das Modell ActivityFeed erstellen können. Nehmen wir außerdem an, dass das Modell Event zum Modell Calendar gehört, das Modell Photo dem Modell Tag zugeordnet ist und das Modell Post zum Modell Author gehört.

Mithilfe dieser Modelldefinitionen und Beziehungen können wir die ActivityFeed Modellinstanz abrufen und alle parentable Modelle und ihre jeweiligen verschachtelten Beziehungen auf einmal laden:

$activities = ActivityFeed::with('parentable')
    ->get()    
    ->loadMorph('parentable', [ 
           Event::class => ['calendar'],        
           Photo::class => ['tags'],        
           Post::class => ['author'],   
          ]);

Einfügen & Zugehöriges Modell aktualisieren

Speichermethode

Eloquent bietet eine praktische Möglichkeit, Assoziationen zu neuen Modellen hinzuzufügen. Beispielsweise müssen Sie möglicherweise ein neues Comment zu einem Post-Modell hinzufügen. Sie müssen das Comment-Attribut in post_id nicht manuell festlegen, sondern können direkt die save-Methode des zugehörigen Modells verwenden, um Comment direkt einzufügen:

$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);

Es sollte beachtet werden Wir verwenden keine dynamischen Attribute, um auf die comments-Zuordnung zuzugreifen. Stattdessen rufen wir die Methode comments auf, um die zugehörige Instanz abzurufen. Die save-Methode fügt dem post_id-Modell automatisch die entsprechenden Comment-Werte hinzu.

Wenn Sie mehrere verknüpfte Modelle speichern müssen, können Sie die Methode saveMany verwenden:

$post = App\Post::find(1);
$post->comments()->saveMany([ 
   new App\Comment(['message' => 'A new comment.']),    
   new App\Comment(['message' => 'Another comment.']),
 ]);

Speichern rekursive Modelle und verknüpfte Daten

Wenn Sie möchtensave Für Ihr Modell und alle zugehörigen Daten können Sie die Methode push verwenden:

$post = App\Post::find(1);
$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';$post->push();

Neue Methode

Zusätzlich zu den Methoden save und saveMany können Sie auch die Methode create verwenden. Es akzeptiert eine Reihe von Eigenschaften, erstellt ein Modell und fügt es in die Datenbank ein. Der Unterschied zwischen der save-Methode und der create-Methode besteht außerdem darin, dass die save-Methode eine vollständige Eloquent-Modellinstanz akzeptiert, während create ein normales PHP-Array akzeptiert:

$post = App\Post::find(1);
$comment = $post->comments()->create([
    'message' => 'A new comment.',
  ]);

{Tipp} Bevor Sie die create-Methode verwenden, lesen Sie bitte unbedingt das Kapitel zur Stapelzuweisung in diesem Dokument.

Sie können auch die createMany-Methode verwenden, um mehrere verwandte Modelle zu erstellen:

$post = App\Post::find(1);$post->comments()->createMany([
    [  
          'message' => 'A new comment.',  
     ],    
     [    
           'message' => 'Another new comment.',  
     ],
  ]);

Sie können auch findOrNew, firstOrNew, firstOrCreate und updateOrCreate verwenden Verfahren Erstellen und aktualisieren Sie Beziehungsmodelle.

belongsTo Assoziation aktualisieren

Beim Aktualisieren einer belongsTo Assoziation müssen Sie Sie können die Methode associate verwenden. Diese Methode legt den Fremdschlüssel im untergeordneten Modell fest:

$account = App\Account::find(10);
$user->account()->associate($account);$user->save();

Die belongsTo-Methode kann beim Entfernen der dissociate-Zuordnung verwendet werden. Diese Methode setzt den zugehörigen Fremdschlüssel auf null:

$user->account()->dissociate();$user->save();

Mit der Beziehung

Standardmodell

belongsTo können Sie ein Standardmodell angeben. Wenn die angegebene Beziehung null ist, wird das Standardmodell zurückgegeben. Dieses Muster wird als Nullobjektmuster bezeichnet und kann unnötige Überprüfungen in Ihrem Code reduzieren. Wenn im folgenden Beispiel kein Autor für den veröffentlichten Beitrag gefunden wird, gibt die user-Beziehung ein leeres AppUser-Modell zurück:

/**
 * 获取帖子的作者。
 */
 public function user(){
     return $this->belongsTo('App\User')->withDefault();
   }

Wenn Sie dem Standardmodell Attribute hinzufügen müssen, können Sie übergeben ein Array oder eine Rückrufmethode für withDefault Medium:

/**
 * 获取帖子的作者。
 */
 public function user(){
     return $this->belongsTo('App\User')->withDefault([ 
            'name' => 'Guest Author', 
          ]);
       }
 /**
 * 获取帖子的作者。
 */
 public function user(){
     return $this->belongsTo('App\User')->withDefault(function ($user) {
             $user->name = 'Guest Author'; 
            });
        }

Many-to-Many-Assoziation

Anhängen/Abtrennen

Eloquent Darüber hinaus werden einige zusätzliche Hilfsmethoden bereitgestellt, um die Verwendung verwandter Modelle komfortabler zu gestalten. Nehmen wir beispielsweise an, dass ein Benutzer mehrere Rollen haben kann und jede Rolle von mehreren Benutzern gemeinsam genutzt werden kann. Das Anhängen einer Rolle an einen Benutzer erfolgt durch Einfügen eines Datensatzes in die Zwischentabelle. Dieser Vorgang kann mit der attach-Methode durchgeführt werden:

$user = App\User::find(1);
$user->roles()->attach($roleId);

Beim Anhängen einer Beziehung an ein Modell können Sie auch einen Satz übergeben der einzufügenden Werte:

$user->roles()->attach($roleId, ['expires' => $expires]);

Natürlich ist es manchmal auch notwendig, die Rolle des Benutzers zu entfernen. Viele-zu-viele-bezogene Datensätze können mit detach entfernt werden. Die Methode detach entfernt die entsprechenden Datensätze aus der Zwischentabelle; beide Modelle bleiben jedoch in der Datenbank:

// 移除用户的一个角色...
$user->roles()->detach($roleId);
// 移除用户的所有角色...
$user->roles()->detach();

Der Einfachheit halber erlauben attach und detach auch die Übergabe eines ID-Arrays :

$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([
    1 => ['expires' => $expires],    
    2 => ['expires' => $expires]
  ]);

Synchronisierungszuordnung

Sie können auch verwenden sync Methode zum Aufbau einer Viele-zu-Viele-Assoziation. Die Methode sync empfängt ein Array von IDs, um die Datensätze der Zwischentabelle zu ersetzen. Unter den Zwischentabellendatensätzen werden alle Datensätze entfernt, die nicht im ID-Array enthalten sind. Nach Abschluss des Vorgangs bleibt also nur die ID des angegebenen Arrays in der Zwischentabelle erhalten:

$user->roles()->sync([1, 2, 3]);

Sie können der Zwischentabelle auch zusätzliche Daten über die ID übergeben:

$user->roles()->sync([1 => ['expires' => true], 2, 3]);

Wenn Sie die vorhandene ID nicht entfernen möchten, können Sie syncWithoutDetaching verwenden Methoden:

$user->roles()->syncWithoutDetaching([1, 2, 3]);

Zuordnung wechseln

Many-to-many-Zuordnung bietet auch die toggle-Methode zum „Umschalten“ des zusätzlichen Status eines bestimmten ID-Arrays. Wenn die angegebene ID in der Zwischentabelle angehängt wurde, wird sie entfernt. Wenn die angegebene ID entfernt wurde, wird sie ebenfalls angehängt:

$user->roles()->toggle([1, 2, 3]);

Zusätzliche Daten speichern unter Zwischentabellen

Speichern Sie beim Umgang mit Viele-zu-Viele-Beziehungen Als zweiten Parameter erhält die Methode ein zusätzliches Datenarray:

App\User::find(1)->roles()->save($role, ['expires' => $expires]);

Zwischentabellendatensatz aktualisieren

Wenn Sie einen vorhandenen Datensatz in der Zwischentabelle aktualisieren müssen, können Sie updateExistingPivot verwenden. Diese Methode empfängt den Fremdschlüssel der Zwischentabelle und das zu aktualisierende Datenarray für die Aktualisierung:

$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);

Update parent timestamp

Wenn ein Modell zu belongsTo oder belongsToMany zu einem anderen Modell gehört, gehört beispielsweise Comment zu Post Manchmal ist es nützlich, ein untergeordnetes Modell zu aktualisieren, was zu einem aktualisierten Zeitstempel des übergeordneten Modells führt. Wenn beispielsweise das Comment-Modell aktualisiert wird, möchten Sie automatisch eine Aktualisierung des Post-Zeitstempels des übergeordneten updated_at-Modells „auslösen“. Eloquent macht es einfach. Fügen Sie einfach ein touches-Attribut hinzu, das den zugehörigen Namen zum untergeordneten Modell enthält:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Comment extends Model{ 
       /**
     * 要触发的所有关联关系
     *
     * @var array
     */  
      protected $touches = ['post'];   
     /**
     * 评论所属的文章
     */   
     public function post() 
        {     
           return $this->belongsTo('App\Post');  
         }
      }

Wenn Sie nun ein Comment aktualisieren, wird auch das Post-Feld, das dem übergeordneten updated_at-Modell entspricht, auf aktualisiert Machen Sie es einfacher zu wissen, wann der Cache eines Post Modells ungültig gemacht werden muss:

$comment = App\Comment::find(1);
$comment->text = 'Edit to this comment!';
$comment->save();
Dieser Artikel erschien zuerst am LearnKu.com Website.