Heim >Backend-Entwicklung >PHP-Tutorial >Laravel-Framework – Detaillierte Einführung in die erweiterten Teile von EloquentORM
Eins zu Eins
Angenommen, das BenutzerModell ist mit dem Telefonmodell verknüpft. Um eine solche Zuordnung zu definieren, müssen Sie im Benutzer eine Telefonmethode definieren Modell, das eine durch die hasOne-Methode definierte Assoziation zurückgibt.
<?phpnamespace 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'); } }
Der erste Parameter der hasOne-Methode ist das zuzuordnende Modell. Nachdem es definiert wurde, können Sie die folgende Syntax verwenden, um die Assoziationsattribute abzufragen
$phone = User::find(1)->phone;
Eloquent geht davon aus, dass der zugehörige Fremdschlüssel auf dem Modellnamen basiert, sodass das Telefonmodell automatisch das Feld user_id als Fremdschlüssel verwendet. Sie können den zweiten und dritten Parameter zum Überschreiben verwenden 🎜>
return $this->hasOne('App\Phone', 'foreign_key');return $this->hasOne('App\Phone', 'foreign_key', 'local_key');um die umgekehrte Beziehung zu definieren Nachdem Sie das obige Modell definiert haben, können Sie das Benutzermodell verwenden, um das Telefonmodell abzurufen. Natürlich können Sie den entsprechenden Benutzer auch über das Telefon abrufen Modell. Dies verwendet die Methode „Eins zu Viele“
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Phone extends Model{ /** * Get the user that owns the phone. */ public function user() { return $this->belongsTo('App\User'); // return $this->belongsTo('App\User', 'foreign_key'); // return $this->belongsTo('App\User', 'foreign_key', 'other_key'); } }Angenommen, es gibt einen Beitrag mit vielen zugehörigen Kommentarinformationen. In diesem Fall sollte eine Eins-zu-Viele-Zuordnung vorliegen verwendet werden, unter Verwendung der hasMany-Methode
Abfrageoperation
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Post extends Model{ /** * Get the comments for the blog post. */ public function comments() { return $this->hasMany('App\Comment'); } }
Umgekehrte Zuordnung definieren
$comments = App\Post::find(1)->comments; foreach ($comments as $comment) { //} $comments = App\Post::find(1)->comments()->where('title', 'foo')->first();Umgekehrte Zuordnung verwendet auch die „gehörtTo“-Methode, siehe One To One Abschnitt.
Many-to-Many
$comment = App\Comment::find(1); echo $comment->post->title;Many-to-many-Assoziation verfügt über eine zusätzliche Zwischentabelle und ist daher komplizierter zu implementieren als hasOne und hasMany. Stellen Sie sich ein Szenario vor, in dem ein Benutzer mehreren Rollen angehören kann und eine Rolle auch mehreren Benutzern angehören kann. Dadurch werden drei Tabellen eingeführt: Benutzer, Rollen, Rollenbenutzer. Die Tabelle „role_user“ ist eine verwandte Tabelle und enthält zwei Felder „user_id“ und „role_id“. Many-to-many-Zuordnung erfordert die Methode „gehörtToMany“
Das Obige definiert, dass ein Benutzer mehreren Rollen angehört. Sobald die Beziehung hergestellt ist, kann sie abgefragt werden
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class User extends Model{ /** * The roles that belong to the user. */ public function roles() { // 指定关联表 // return $this->belongsToMany('App\Role', 'role_user'); // 指定关联表,关联字段 // return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id'); return $this->belongsToMany('App\Role'); } }
Umgekehrte Assoziationsbeziehung
user = App\User::find(1); foreach ($user->roles as $role) { //}$roles = App\User::find(1)->roles()->orderBy('name')->get();Die umgekehrte Beziehung wird genauso implementiert wie die Vorwärtsbeziehung
Rufen Sie den Spaltenwert der Zwischentabelle ab
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Role extends Model{ /** * The users that belong to the role. */ public function users() { return $this->belongsToMany('App\User'); } }Für viele -zu-viele-Beziehungen einführen Eine Zwischentabelle wird erstellt, daher muss eine Möglichkeit vorhanden sein, die Spaltenwerte der Zwischentabelle abzufragen, z. B. den Zeitpunkt, zu dem die Beziehung hergestellt wurde usw. Verwenden Sie zum Abfragen das Pivot-Attribut die Zwischentabelle
Der obige Code greift auf das Feld „created_at“ der Zwischentabelle zu.
$user = App\User::find(1); foreach ($user->roles as $role) { echo $role->pivot->created_at; }Beachten Sie, dass auf die Schlüssel des Modells standardmäßig über das Pivot
-Objekt zugegriffen werden kann
Wenn die Zwischentabelle zusätzliche Attribute enthält, müssen Sie beim Festlegen der Zuordnung die Methode withPivot verwenden. Geben Sie explizit den Spaltennamen anreturn $this->belongsToMany('App\Role')->withPivot('column1', 'column2');Diese Beziehung ist relativ leistungsfähig: Angenommen, es gibt ein Szenario: Das Ländermodell enthält mehrere Benutzermodelle, und jedes Benutzermodell enthält mehrere Post-Modelle, das heißt, es gibt viele Benutzer in einem Land, und diese Benutzer haben viele Posts in einem bestimmten Land. Wie kann dies mithilfe der Has Many Through-Beziehung erreicht werden? 🎜>
Verwendung der Beziehung „Hats Many Through“
countries id - integer name - stringusers id - integer country_id - integer name - stringposts id - integer user_id - integer title - string
Methode Der erste Parameter von hasManyThrough ist der Name des Modells, auf das wir zugreifen möchten, und der zweite Parameter ist der Name des Zwischenmodells.
Polymorphe Beziehungen (polymorphe Assoziation)namespace App; use Illuminate\Database\Eloquent\Model;class Country extends Model{ /** * Get all of the posts for the country. */ public function posts() { // return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id'); return $this->hasManyThrough('App\Post', 'App\User'); } }
Polymorphe Beziehungen ermöglichen die Zugehörigkeit desselben Modells zu mehreren verschiedenen Modellen unter Verwendung einer Assoziation. Unter der Annahme eines solchen Szenarios haben wir eine Post-Tabelle und einen Kommentar Tabelle: Benutzer können sowohl Beiträge als auch Kommentare mit „Gefällt mir“ markieren.
HasManyThrough hasManyThrough( string $related, string $through, string|null $firstKey = null, string|null $secondKey = null, string|null $localKey = null)Die Tabellenstruktur ist wie folgt
Wie Sie sehen können, verwenden wir das Feld likeable_type in der Likes-Tabelle, um zu bestimmen, ob dem Datensatz ein Beitrag oder ein Kommentar gefällt Wenn die Tabellenstruktur vorhanden ist, ist es an der Zeit, sie zu definieren Modell
Standardmäßig ist der Typ von likeable_type der vollständige Name des zugehörigen Modells, wie hier AppPost und AppComment.posts id - integer title - string body - textcomments id - integer post_id - integer body - textlikes id - integer likeable_id - integer likeable_type - string
Normalerweise verwenden wir einen benutzerdefinierten Wert, um den zugehörigen Tabellennamen zu identifizieren. Daher müssen wir die Zuordnung beispielsweise in der Boot-Methode des Dienstanbieterobjekts registrieren , in der Boot-Methode von
,<?php namespace App; use Illuminate\Database\Eloquent\Model;class Like extends Model{ /** * Get all of the owning likeable models. */ public function likeable() { return $this->morphTo(); } }class Post extends Model{ /** * Get all of the product's likes. */ public function likes() { return $this->morphMany('App\Like', 'likeable'); } }class Comment extends Model{ /** * Get all of the comment's likes. */ public function likes() { return $this->morphMany('App\Like', 'likeable'); } }ruft polymorphe Beziehungen ab
AppServiceProvider
greift auf alle „Gefällt mir“-Angaben eines Beitrags zu
use Illuminate\Database\Eloquent\Relations\Relation;Relation::morphMap([ 'posts' => App\Post::class, 'likes' => App\Like::class,]);
$post = App\Post::find(1); foreach ($post->likes as $like) { //}
Many-to-many polymorphe Assoziation
$like = App\Like::find(1); $likeable = $like->likeable;Many-to-many-Assoziation verwendet die Methoden morphToMany und morphedByMany, hier ist kein Unsinn mehrAssoziationsbeziehungsabfrageIn Eloquent werden alle Beziehungen
mithilfe von Funktionen
definiert, die es Ihnen ermöglichen, verwandte Instanzen abzurufen, ohne eine verwandte Abfrage auszuführen. Angenommen, wir haben ein Blog-System und das Benutzermodell ist mit vielen Post-Modellen verknüpft:Sie können die Zuordnung wie folgt abfragen und zusätzliche Einschränkungen
/** * Get all of the posts for the user. */public function posts() { return $this->hasMany('App\Post'); }hinzufügen
Wenn den zugehörigen Attributen keine Einschränkungen hinzugefügt werden müssen, kann auf sie direkt als Attribute des Modells zugegriffen werden. Im obigen Beispiel können wir beispielsweise die folgende Methode verwenden, um auf den Benutzerbeitrag zuzugreifen 动态的属性都是延迟加载的,它们只有在被访问的时候才会去查询数据库,与之对应的是预加载,预加载可以使用关联查询出所有数据,减少执行sql的数量。 使用has方法可以基于关系的存在性返回结果 如果需要更加强大的功能,可以使用whereHas和orWhereHas方法,把where条件放到has语句中。 在访问Eloquent模型的时候,默认情况下所有的关联关系都是延迟加载的,在使用的时候才会开始加载,这就造成了需要执行大量的sql的问题,使用预加载功能可以使用关联查询出所有结果 接下来我们检索所有的书和他们的作者 上面的查询将会执行一个查询查询出所有的书,然后在遍历的时候再执行N个查询查询出作者信息,显然这样做是非常低效的,幸好我们还有预加载功能,可以将这N+1个查询减少到2个查询,在查询的时候,可以使用with方法指定哪个关系需要预加载。 对于该操作,会执行下列两个sql 预加载多个关系 嵌套的预加载 延迟预加载# 有时候,在上级模型已经检索出来之后,可能会需要预加载关联数据,可以使用load方法 保存单个关联模型 多对多关联可以为save的第二个参数指定关联表中的属性 上述代码会更新中间表的expires字段。 使用create方法与save方法的不同在于它是使用数组的形式创建关联模型的 更新belongsTo关系的时候,可以使用associate方法,该方法会设置子模型的外键 要移除belongsTo关系的话,使用dissociate方法 中间表查询条件# 当查询时需要对使用中间表作为查询条件时,可以使用 Attaching / Detaching# attach和detach方法支持数组参数,同时添加和移除多个 使用updateExistingPivot方法更新中间表 同步中间表(同步关联关系)# 使用sync方法,可以指定两个模型之间只存在指定的关联关系 上述两个方法都会让用户只存在1,2,3三个角色,如果用户之前存在其他角色,则会被删除。 更新父模型的时间戳# 假设场景如下,我们为一个帖子增加了一个新的评论,我们希望这个时候帖子的更新时间会相应的改变,这种行为在Eloquent中是非常容易实现的。 在子模型中使用$touches属性实现该功能 现在,更新评论的时候,帖子的updated_at字段也会被更新$user = App\User::find(1);foreach ($user->posts as $post) { //}
查询关系存在性
// 检索至少有一个评论的所有帖子...$posts = App\Post::has('comments')->get();
// Retrieve all posts that have three or more comments...$posts = Post::has('comments', '>=', 3)->get();
// Retrieve all posts that have at least one comment with votes...$posts = Post::has('comments.votes')->get();
// 检索所有至少存在一个匹配foo%的评论的帖子$posts = Post::whereHas('comments', function ($query) {
$query->where('content', 'like', 'foo%');
})->get();
预加载
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Book extends Model{
/**
* Get the author that wrote the book.
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
$books = App\Book::all();
foreach ($books as $book) {
echo $book->author->name;
}
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
$books = App\Book::with('author', 'publisher')->get();
$books = App\Book::with('author.contacts')->get();
带约束的预加载
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();$users = App\User::with(['posts' => function ($query) {
$query->orderBy('created_at', 'desc');
}])->get();
$books = App\Book::all();if ($someCondition) { $books->load('author', 'publisher');
}$books->load(['author' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);
关联模型插入
save方法
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);$post->comments()->save($comment);
保存多个关联模型
$post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);
save方法和多对多关联
App\User::find(1)->roles()->save($role, ['expires' => $expires]);
create方法
$post = App\Post::find(1);$comment = $post->comments()->create([
'message' => 'A new comment.',]);
更新 “Belongs To” 关系
$account = App\Account::find(10);
$user->account()->associate($account);
$user->save();
$user->account()->dissociate();$user->save();
Many to Many 关系
wherePivot
, wherePivotIn
,orWherePivot
,orWherePivotIn
添加查询条件。$enterprise->with(['favorites' => function($query) {
$query->wherePivot('enterprise_id', '=', 12)->select('id');
}]);
$user = App\User::find(1);
// 为用户添加角色
$user->roles()->attach($roleId);
// 为用户添加角色,更新中间表的expires字段
$user->roles()->attach($roleId, ['expires' => $expires]);
// 移除用户的单个角色
$user->roles()->detach($roleId);
// 移除用户的所有角色
$user->roles()->detach();
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);
更新中间表(关联表)字段
$user = App\User::find(1);$user->roles()->updateExistingPivot($roleId, $attributes);
$user->roles()->sync([1, 2, 3]);
$user->roles()->sync([1 => ['expires' => true], 2, 3]);
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;class Comment extends Model{ /**
* All of the relationships to be touched.
*
* @var array
*/
protected $touches = ['post']; /**
* Get the post that the comment belongs to.
*/
public function post()
{ return $this->belongsTo('App\Post');
}
}
$comment = App\Comment::find(1);$comment->text = 'Edit to this comment!';$comment->save();
Das obige ist der detaillierte Inhalt vonLaravel-Framework – Detaillierte Einführung in die erweiterten Teile von EloquentORM. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!