Persatuan model
- Takrifkan perkaitan songsang
- Satu-dengan-banyak
- Satu-dengan-banyak (terbalik) .
- Model geganti tersuai dengan penambahan ID
- Perhubungan satu dengan satu jauh
- Perkaitan satu-ke-banyak jauh Struktur jadual
- Struktur model
- Struktur jadual
- Model struktur
- .
- Jenis polimorfisme tersuai
- Perkaitan pertanyaan
- Kaedah persatuan Vs Atribut dinamik
- Persoalan persatuan sedia ada
- Persoalan persatuan bukan wujud
- pramuat Tambah kekangan
- Pramuat
- Pramuat berbilang persatuan
- Pramuat bersarang
- Pramuat lajur yang ditentukan
- Pramuat muatan morphTo
- Kaedah Simpanan
- Persatuan Ramai-ke-Ramai
- Tambah/Cabut
- Segerakkan Persatuan Simpan data tambahan pada jadual perantaraan
- media terkini
- Pengenalan
- Definisi persatuan
- One-to-one
- One-to-manyOne-to-many One-to-many
- banyak-pasangan Banyak
- Model jadual perantaraan tersuai
- Jauh satu sama satu
- Persatuan satu-ke-banyak
- quociation vs.
- Berdasarkan pertanyaan perkaitan yang tidak wujud
- kiraan data berkaitan
- Memuat pramuat
- pramuat pramuat ing
- Sisipkan & kemas kini model yang berkaitan
- kaedah
simpan kod> buat kaedah
Milik Persatuan - kaedah
- Many-to-Many Association
save
方法create
方法- 更新
Belongs To
Kemas kini cap waktu set ibu bapa
- Dapatkan persatuan
- Sisipkan & kemas kini model berkaitan
Fasih: Persatuan
Satu-ke-satu
Tentukan Persatuan
Persatuan fasih dibentangkan sebagai kaedah dalam kelas model Eloquent. Seperti model Eloquent itu sendiri, persatuan juga boleh digunakan sebagai pembina pernyataan pertanyaan yang berkuasa, menyediakan panggilan berantai yang berkuasa dan fungsi pertanyaan. Sebagai contoh, kita boleh melampirkan kekangan pada rantaian panggilan ke perkaitan posts
: posts
关联的链式调用中附加一个约束条件:
$user->posts()->where('active', 1)->get();
不过在深入使用关联之前,让我们先学习如何定义每种关联类型。
一对一
一对一是最基本的关联关系。例如,一个 User
模型可能关联一个 Phone
模型。为了定义这个关联,我们要在 User
模型中写一个 phone
方法。在 phone
方法内部调用 hasOne
方法并返回其结果:
<?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
方法的第一个参数是关联模型的类名。一旦定义了模型关联,我们就可以使用 Eloquent 动态属性获得相关的记录。动态属性允许你访问关系方法就像访问模型中定义的属性一样:
$phone = User::find(1)->phone;
Eloquent 会基于模型名决定外键名称。在这种情况下,会自动假设 Phone
模型有一个 user_id
外键。如果你想覆盖这个约定,可以传递第二个参数给 hasOne
方法:
return $this->hasOne('App\Phone', 'foreign_key');
另外,Eloquent 假设外键的值是与父级 id (或自定义 $primaryKey) 列的值相匹配的。换句话说,Eloquent 将会在 Phone 记录的 user_id 列中查找与用户表的 id 列相匹配的值。如果您希望该关联使用 id 以外的自定义键名,则可以给 hasOne 方法传递第三个参数:
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
定义反向关联
我们已经能从 User
模型访问到 Phone
模型了。现在,让我们再在 Phone
模型上定义一个关联,这个关联能让我们访问到拥有该电话的 User
模型。我们可以使用与 hasOne
方法对应的 belongsTo
方法来定义反向关联:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Phone extends Model{ /** * 获得拥有此电话的用户 */ public function user() { return $this->belongsTo('App\User'); } }
在上面的例子中, Eloquent 会尝试匹配 Phone
模型上的 user_id
至 User
模型上的 id
。它是通过检查关系方法的名称并使用 _id
作为后缀名来确定默认外键名称的。但是,如果 Phone
模型的外键不是 user_id
,那么可以将自定义键名作为第二个参数传递给 belongsTo
方法:
/** * 获得拥有此电话的用户 */ public function user(){ return $this->belongsTo('App\User', 'foreign_key'); }
如果父级模型没有使用 id
作为主键,或者是希望用不同的字段来连接子级模型,则可以通过给 belongsTo
/** * 获得拥有此电话的用户 */ public function user(){ return $this->belongsTo('App\User', 'foreign_key', 'other_key'); }Tetapi sebelum kita menyelami penggunaan perkaitan, mari kita pelajari cara mentakrifkan setiap jenis perkaitan.
One-to-one
Pengguna
mungkin dikaitkan dengan model Telefon
. Untuk mentakrifkan perkaitan ini, kita perlu menulis kaedah phone
dalam model User
. Panggil kaedah hasOne
di dalam kaedah phone
dan kembalikan hasilnya: 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取博客文章的评论 */ public function comments() { return $this->hasMany('App\Comment'); } }🎜 Parameter pertama kaedah
hasOne
ialah nama kelas bagi model yang berkaitan. Setelah perkaitan model ditakrifkan, kita boleh menggunakan sifat dinamik Eloquent untuk mendapatkan rekod yang berkaitan. Sifat dinamik membolehkan anda mengakses kaedah hubungan sama seperti sifat yang ditakrifkan dalam model: 🎜$comments = App\Post::find(1)->comments;foreach ($comments as $comment) { //}🎜Eloquent akan menentukan nama kunci asing berdasarkan nama model. Dalam kes ini, secara automatik diandaikan bahawa model
Telefon
mempunyai kunci asing user_id
. Jika anda ingin mengatasi konvensyen ini, anda boleh menghantar parameter kedua kepada kaedah hasOne
: 🎜$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();🎜 Selain itu, Eloquent menganggap bahawa nilai kunci asing adalah sama dengan nilai id induk (atau padanan lajur $primaryKey) tersuai. Dalam erti kata lain, Eloquent akan mencari nilai dalam lajur user_id rekod Telefon yang sepadan dengan lajur id jadual Pengguna. Jika anda mahu perkaitan menggunakan nama kunci tersuai selain id, anda boleh menghantar parameter ketiga kepada kaedah hasOne: 🎜
return $this->hasMany('App\Comment', 'foreign_key'); return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
Tentukan perkaitan terbalik
🎜Kami sudah boleh mengakses modelPhone
daripada model User
. Sekarang, mari kita tentukan perkaitan lain pada model Telefon
yang akan memberi kita akses kepada model Pengguna
yang memiliki telefon. Kita boleh mentakrifkan perkaitan terbalik menggunakan kaedah belongsTo
yang sepadan dengan kaedah hasOne
: 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model{ /** * 获取此评论所属文章 */ public function post() { return $this->belongsTo('App\Post'); } }🎜Dalam contoh di atas, Eloquent akan cuba memadankan
Phone
user_id
pada model kepada id
pada model User
. Ia menentukan nama kunci asing lalai dengan memeriksa nama kaedah perhubungan dan menggunakan _id
sebagai akhiran nama. Walau bagaimanapun, jika kunci asing model Phone
bukan user_id
, maka nama kunci tersuai boleh dihantar sebagai parameter kedua kepada belongsTo
kaedah: 🎜 $comment = App\Comment::find(1); echo $comment->post->title;🎜Jika model induk tidak menggunakan
id
sebagai kunci utama, atau anda mahu menggunakan medan yang berbeza untuk menyambung model anak, anda boleh menghantar parameter ketiga kepada belongsTo Kaedah
Nyatakan kunci tersuai jadual data induk dalam borang: 🎜/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key'); }🎜🎜🎜🎜🎜🎜
One-to-many
"One-to-many" perkaitan digunakan untuk mentakrifkan satu model untuk mempunyai sebarang bilangan model lain yang berkaitan. Sebagai contoh, catatan blog mungkin mempunyai bilangan komen yang tidak terhingga. Seperti semua perhubungan Eloquent yang lain, takrifan perhubungan satu-dengan-banyak ialah menulis kaedah dalam model Eloquent:
/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key', 'other_key'); }
Ingat bahawa Eloquent akan secara automatik menentukan atribut kunci asing bagi model Comment
. Mengikut konvensyen, Eloquent akan menggunakan bentuk "snake case" bagi nama model, ditambah dengan akhiran _id
sebagai medan kunci asing. Oleh itu, dalam contoh di atas, Eloquent akan menganggap bahawa kunci asing pada Comment
yang sepadan dengan model Post
ialah post_id
. Comment
模型的外键属性。按照约定,Eloquent 将会使用所属模型名称的 『snake case』形式,再加上 _id
后缀作为外键字段。因此,在上面这个例子中,Eloquent 将假定 Comment
对应到 Post
模型上的外键就是 post_id
。
一旦关系被定义好以后,就可以通过访问 Post
模型的 comments
属性来获取评论的集合。记住,由于 Eloquent 提供了『动态属性』 ,所以我们可以像访问模型的属性一样访问关联方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model;class User extends Model{ /** * 用户拥有的角色 */ public function roles() { return $this->belongsToMany('App\Role'); } }
当然,由于所有的关联还可以作为查询语句构造器使用,因此你可以使用链式调用的方式,在 comments
方法上添加额外的约束条件:
$user = App\User::find(1); foreach ($user->roles as $role) { // }
正如 hasOne
方法一样,你也可以在使用 hasMany
方法的时候,通过传递额外参数来覆盖默认使用的外键与本地键:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
一对多(反向)
现在,我们已经能获得一篇文章的所有评论,接着再定义一个通过评论获得所属文章的关联关系。这个关联是 hasMany
关联的反向关联,需要在子级模型中使用 belongsTo
方法定义它:
return $this->belongsToMany('App\Role', 'role_user');
这个关系定义好以后,我们就可以通过访问 Comment
模型的 post
这个『动态属性』来获取关联的 Post
模型了:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
在上面的例子中,Eloquent 会尝试用 Comment
模型的 post_id
与 Post
模型的 id
进行匹配。默认外键名是 Eloquent 依据关联名,并在关联名后加上 _ 再加上主键字段名作为后缀确定的。当然,如果 Comment
模型的外键不是 post_id
,那么可以将自定义键名作为第二个参数传递给 belongsTo
方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的用户。 */ public function users() { return $this->belongsToMany('App\User'); } }
如果父级模型没有使用 id
作为主键,或者是希望用不同的字段来连接子级模型,则可以通过给 belongsTo
Comments
model Post
. Ingat, memandangkan Eloquent menyediakan "sifat dinamik", kita boleh mengakses kaedah perhubungan sama seperti mengakses sifat model: $user = App\User::find(1); foreach ($user->roles as $role) { echo $role->pivot->created_at; }Sudah tentu, kerana semua perhubungan juga boleh digunakan sebagai pembina pernyataan pertanyaan, anda boleh menggunakan cara panggilan berantai, tambah tambahan kekangan pada kaedah
comments
: return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');Sama seperti kaedah
hasOne
, anda juga boleh menggunakan kaedah hasMany
Apabila, ganti penggunaan lalai kunci asing dan kunci tempatan dengan menghantar parameter tambahan: return $this->belongsToMany('App\Role')->withTimestamps();
hasMany
Anda perlu menggunakan kaedah belongsTo
untuk mentakrifkannya dalam model kanak-kanak: 🎜return $this->belongsToMany('App\Podcast') ->as('subscription') ->withTimestamps();🎜Selepas perhubungan ini ditakrifkan, kami. boleh mengaksesnya melalui
Comment
model post
"atribut dinamik" untuk mendapatkan model Post
yang berkaitan: 🎜$users = User::with('podcasts')->get(); foreach ($users->flatMap->podcasts as $podcast) { echo $podcast->subscription->created_at; }🎜Dalam contoh di atas, Eloquent akan mencuba Gunakan
Comment
model post_id
untuk memadankan Post
model id
. Nama kunci asing lalai ditentukan oleh Eloquent berdasarkan nama persatuan, diikuti dengan _ dan nama medan kunci utama sebagai akhiran. Sudah tentu, jika kunci asing bagi model Comment
bukan post_id
, anda boleh menghantar nama kunci tersuai sebagai parameter kedua kepada belongsTo
kaedah: 🎜 return $this->belongsToMany('App\Role')->wherePivot('approved', 1); return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);🎜Jika model induk tidak menggunakan
id
sebagai kunci utama, atau anda ingin menggunakan medan yang berbeza untuk menyambungkan model anak, anda boleh menghantar parameter ketiga kepada belongsTo Kaedah
Nyatakan kunci tersuai jadual data induk dalam borang: 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的所有用户 */ public function users() { return $this->belongsToMany('App\User')->using('App\UserRole'); } }🎜🎜🎜🎜🎜🎜
Many-to-many
Hubungan banyak-ke-banyak adalah lebih kompleks sedikit daripada hubungan hasOne
dan hasMany
. Sebagai contoh, pengguna boleh mempunyai banyak peranan, dan peranan ini dikongsi oleh pengguna lain. Sebagai contoh, ramai pengguna mungkin mempunyai peranan "Pentadbir". Untuk mentakrifkan perkaitan ini, tiga jadual pangkalan data diperlukan: pengguna
, roles
dan role_user
. Jadual role_user
dinamakan mengikut abjad daripada dua model yang berkaitan dan mengandungi medan user_id
dan role_id
. hasOne
和 hasMany
关联稍微复杂些。举个例子,一个用户可以拥有很多种角色,同时这些角色也被其他用户共享。例如,许多用户可能都有 「管理员」 这个角色。要定义这种关联,需要三个数据库表: users
,roles
和 role_user
。role_user
表的命名是由关联的两个模型按照字母顺序来的,并且包含了 user_id
和 role_id
字段。
多对多关联通过调用 belongsToMany
这个内部方法返回的结果来定义,例如,我们在 User
模型中定义 roles
方法:
<?php namespace App; use Illuminate\Database\Eloquent\Relations\Pivot; class UserRole extends Pivot{ // }
一旦关联关系被定义后,你可以通过 roles
动态属性获取用户角色:
<?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' ]); } }
当然,像其它所有关联模型一样,你可以使用 roles
方法,利用链式调用对查询语句添加约束条件:
/** * 标识 ID 是否自增。 * * @var bool */ public $incrementing = true;
正如前面所提到的,为了确定关联连接表的表名,Eloquent 会按照字母顺序连接两个关联模型的名字。当然,你也可以不使用这种约定,传递第二个参数到 belongsToMany
方法即可:
suppliers id - integer users id - integer supplier_id - integer history id - integer user_id - integer
除了自定义连接表的表名,你还可以通过传递额外的参数到 belongsToMany
方法来定义该表中字段的键名。第三个参数是定义此关联的模型在连接表里的外键名,第四个参数是另一个模型在连接表里的外键名:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Supplier extends Model{ /** * 用户的历史记录。 */ public function userHistory() { return $this->hasOneThrough('App\History', 'App\User'); } }
定义反向关联
要定义多对多的反向关联, 你只需要在关联模型中调用 belongsToMany
方法。我们在 Role
模型中定义 users
方法:
class Supplier extends Model{ /** * 用户的历史记录。 */ public function userHistory() { return $this->hasOneThrough( 'App\History', 'App\User', 'supplier_id', // 用户表外键 'user_id', // 历史记录表外键 'id', // 供应商本地键 'id' // 用户本地键 ); } }
如你所见,除了引入模型为 AppUser
外,其它与在 User
模型中定义的完全一样。由于我们重用了 belongsToMany
belongsToMany
Contohnya, kami mentakrifkan kaedah roles
dalam User< /code> model: countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
Setelah perkaitan ditakrifkan, anda boleh mendapatkan peranan pengguna melalui atribut dinamik roles
: 🎜<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model{
/**
* 当前国家所有文章。
*/
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
🎜Sudah tentu, seperti semua model persatuan lain, anda boleh menggunakan peranan
Kaedah, gunakan panggilan berantai untuk menambah kekangan pada pernyataan pertanyaan: 🎜class Country extends Model{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // 用户表外键
'user_id', // 文章表外键
'id', // 国家表本地键
'id' // 用户表本地键
);
}
}
🎜Seperti yang dinyatakan sebelum ini, untuk menentukan nama jadual jadual sambungan yang berkaitan, Eloquent akan menyambungkan nama dua model yang berkaitan dalam susunan abjad. Sudah tentu, anda juga tidak boleh menggunakan konvensyen ini dan menghantar parameter kedua kepada kaedah belongsToMany
: 🎜posts
id - integer
name - string
users
id - integer
name - string
images
id - integer
url - string
imageable_id - integer
imageable_type - string
🎜Selain menyesuaikan nama jadual jadual sambungan, anda juga boleh menghantar parameter tambahan kepada < kaedah code>belongsToMany
untuk mentakrifkan nama kunci medan dalam jadual. Parameter ketiga ialah nama kunci asing bagi model yang mentakrifkan perkaitan ini dalam jadual sambungan dan parameter keempat ialah nama kunci asing model lain dalam jadual sambungan: 🎜<?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'); } }
Tentukan perkaitan songsang
🎜Untuk menentukan perkaitan songsang banyak-ke-banyak, anda hanya perlu memanggil kaedahbelongsToMany
dalam model perkaitan. Kami mentakrifkan kaedah pengguna
dalam model Role
: 🎜$post = App\Post::find(1); $image = $post->image;🎜Seperti yang anda lihat, kecuali pengenalan model
AppUser
, semua yang lain adalah sama seperti dalam >User
adalah sama seperti yang ditakrifkan dalam model. Memandangkan kami menggunakan semula kaedah belongsToMany
, nama jadual cantum tersuai dan nama medan kunci dalam jadual cantum tersuai juga digunakan di sini. 🎜🎜🎜Dapatkan medan jadual perantaraan
Seperti yang baru anda ketahui, perhubungan banyak-ke-banyak memerlukan jadual perantaraan untuk memberikan sokongan Eloquent menyediakan beberapa kaedah berguna untuk berinteraksi dengan jadual ini. Sebagai contoh, katakan objek User
kami dikaitkan dengan berbilang objek Role
. Selepas mendapatkan objek yang berkaitan ini, anda boleh menggunakan atribut pivot
model untuk mengakses data dalam jadual perantaraan: User
对象关联了多个 Role
对象。在获得这些关联对象后,可以使用模型的 pivot
属性访问中间表的数据:
$image = App\Image::find(1); $imageable = $image->imageable;
需要注意的是,我们获取的每个 Role
模型对象,都会被自动赋予 pivot
属性,它代表中间表的一个模型对象,并且可以像其他的 Eloquent 模型一样使用。
默认情况下,pivot
对象只包含两个关联模型的主键,如果你的中间表里还有其他额外字段,你必须在定义关联时明确指出:
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
如果你想让中间表自动维护 created_at
和 updated_at
时间戳,那么在定义关联时附加上 withTimestamps
方法即可:
<?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'); } }
自定义 pivot
属性名称
如前所述,来自中间表的属性可以使用 pivot
属性访问。但是,你可以自由定制此属性的名称,以便更好的反应其在应用中的用途。
例如,如果你的应用中包含可能订阅的用户,则用户与博客之间可能存在多对多的关系。如果是这种情况,你可能希望将中间表访问器命名为 subscription
取代 pivot
。这可以在定义关系时使用 as
方法完成:
$post = App\Post::find(1);foreach ($post->comments as $comment) { // }
一旦定义完成,你可以使用自定义名称访问中间表数据:
$comment = App\Comment::find(1); $commentable = $comment->commentable;
通过中间表过滤关系
在定义关系时,你还可以使用 wherePivot
和 wherePivotIn
方法来过滤 belongsToMany
posts id - integer name - string videos id - integer name - string tags id - integer name - string taggables tag_id - integer taggable_id - integer taggable_type - stringPerlu diambil perhatian bahawa setiap objek model
Role
yang kami perolehi , secara automatik diberikan atribut pivot
, yang mewakili objek model jadual perantaraan dan boleh digunakan seperti model Eloquent yang lain. . Jika anda Jika anda mahu jadual perantaraan mengekalkan cap waktu created_at
dan updated_at
secara automatik, kemudian tambahkan kaedah withTimestamps
apabila mentakrifkan perkaitan: <?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取文章的所有标签。 */ public function tags() { return $this->morphToMany('App\Tag', 'taggable'); } }🎜Sesuaikan nama atribut
pivot
🎜🎜Seperti yang dinyatakan sebelum ini, atribut daripada jadual perantaraan boleh diakses menggunakan pivot< /kod> atribut . Walau bagaimanapun, anda bebas untuk menyesuaikan nama hartanah ini untuk menggambarkan penggunaannya dengan lebih baik dalam aplikasi anda. 🎜🎜Sebagai contoh, jika apl anda mengandungi pengguna yang mungkin melanggan, mungkin terdapat perhubungan banyak-ke-banyak antara pengguna dan blog. Jika ini berlaku, anda mungkin mahu menamakan pengakses jadual perantaraan langganan
dan bukannya pivot
. Ini boleh dilakukan menggunakan kaedah as
apabila mentakrifkan perhubungan: 🎜<?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');
}
}
🎜Setelah ditentukan, anda boleh mengakses data jadual perantaraan menggunakan nama tersuai: 🎜$post = App\Post::find(1);foreach ($post->tags as $tag) {
//
}
🎜🎜Tapis perhubungan melalui jadual perantaraan🎜🎜Apabila mentakrifkan perhubungan, anda juga boleh menggunakan kaedah wherePivot
dan wherePivotIn
untuk menapis belongsToMany
mengembalikan Keputusan untuk: 🎜$tag = App\Tag::find(1);foreach ($tag->videos as $video) {
//
}
🎜🎜🎜🎜🎜🎜Tentukan model jadual perantaraan
Tentukan model jadual perantaraan tersuai
Jika anda ingin menentukan model tersuai untuk mewakili jadual perantaraan dalam perhubungan persatuan, anda boleh memanggil kaedah menggunakan semasa mentakrifkan perkaitan. Model jadual perantaraan Many-to-many
tersuai mesti dilanjutkan daripada kelas IlluminateDatabaseEloquentRelationsPivot dan model jadual perantaraan Many-to-many
tersuai mesti mewarisi kelas IlluminateDatabaseEloquentRelationsMorphPivot. Sebagai contoh, using
方法。自定义多对多
中间表模型都必须扩展自 IlluminateDatabaseEloquentRelationsPivot 类,自定义多对多(多态)
中间表模型必须继承 IlluminateDatabaseEloquentRelationsMorphPivot 类。例如,
我们在写 Role 模型的关联时,使用自定义中间表模型 UserRole
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
当定义 UserRole
模型时,我们要扩展 Pivot
类:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model{
/**
* 获取该用户的所有文章。
*/
public function posts()
{
return $this->hasMany('App\Post');
}
}
你可以组合使用 using
和 withPivot
从中间表来检索列。例如,通过将列名传递给 withPivot
方法,就可以从 UserRole
中间表中检索出 created_by
和 updated_by
两列数据。
$user = App\User::find(1);
$user->posts()->where('active', 1)->get();
带有递增 ID 的自定义中继模型
如果你用一个自定义的中继模型定义了多对多的关系,而且这个中继模型拥有一个自增的主键,你应当确保这个自定义中继模型类中定义了一个 incrementing
属性其值为 true
:
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
远程一对一关系
远程一对一关联通过一个中间关联模型实现。
例如,如果每个供应商都有一个用户,并且每个用户与一个用户历史记录相关联,那么供应商可以通过用户访问用户的历史记录,让我们看看定义这种关系所需的数据库表:
// 获取至少存在一条评论的所有文章...
$posts = App\Post::has('comments')->get();
虽然 history
表不包含 supplier_id
,但 hasOneThrough
关系可以提供对用户历史记录的访问,以访问供应商模型。现在我们已经检查了关系的表结构,让我们在 Supplier
模型上定义相应的方法:
// 获取评论超过三条的文章...
$posts = App\Post::has('comments', '>=', 3)->get();
传递给 hasOneThrough
方法的第一个参数是希望访问的模型名称,第二个参数是中间模型的名称。
当执行关联查询时,通常会使用 Eloquent 约定的外键名。如果你想要自定义关联的键,可以通过给 hasOneThrough
Apabila kita menulis perkaitan model Peranan, kita menggunakan model jadual perantaraan tersuai UserRole
// 获取拥有至少一条带有投票评论的文章...
$posts = App\Post::has('comments.votes')->get();
Apabila mentakrifkan model UserRole
, kita perlu melanjutkan < kod>Pivot< /code> Kelas: 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();
Anda boleh menggunakan gabungan menggunakan
dan withPivot
untuk mendapatkan semula lajur daripada jadual perantaraan. Contohnya, created_by
dan updated_by
boleh diambil daripada jadual perantaraan UserRole
dengan menghantar nama lajur ke withPivot
kaedah. > Dua lajur data.
$posts = App\Post::doesntHave('comments')->get();
Model geganti tersuai dengan peningkatan ID
Jika anda mentakrifkan berbilang pasangan dengan model geganti tersuai berbilang perhubungan, dan model geganti mempunyai kunci utama auto-incrementing, anda harus memastikan bahawa kelas model relay tersuai mentakrifkan atribut incrementing
dengan nilai true
:🎜use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments', function (Builder $query)
{
$query->where('content', 'like', 'foo%');
})->get();
🎜🎜🎜🎜🎜Remote one-to-one relationship🎜🎜Remote one-to-one association melalui perantaraan pelaksanaan model Persatuan. 🎜Sebagai contoh, jika setiap pembekal mempunyai pengguna, dan setiap pengguna dikaitkan dengan sejarah pengguna, maka pembekal boleh mengakses sejarah pengguna melalui pengguna, mari lihat jadual pangkalan data yang diperlukan untuk mentakrifkan hubungan ini: 🎜use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments.author', function (Builder $query)
{
$query->where('banned', 1);
})->get();
🎜Walaupun Jadual history
tidak mengandungi supplier_id
, perhubungan hasOneThrough
boleh memberikan akses kepada sejarah pengguna untuk mengakses model pembekal. Sekarang setelah kita memeriksa struktur jadual perhubungan, mari kita tentukan kaedah yang sepadan pada model Pembekal
: 🎜$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
🎜Parameter pertama yang dihantar ke kaedah hasOneThrough
ialah yang diingini akses Nama model, parameter kedua ialah nama model perantaraan. 🎜🎜Apabila melaksanakan pertanyaan berkaitan, nama kunci asing konvensional Eloquent biasanya digunakan. Jika anda ingin menyesuaikan kunci yang berkaitan, anda boleh berbuat demikian dengan menghantar parameter ketiga dan keempat kepada kaedah hasOneThrough
Parameter ketiga mewakili nama kunci asing bagi model perantaraan dan parameter keempat mewakili Nama kunci asing bagi model akhir. Parameter kelima mewakili nama kunci tempatan, manakala parameter keenam mewakili nama kunci tempatan model perantaraan: 🎜$posts = App\Post::withCount(['votes', 'comments' => function ($query)
{
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;echo $posts[0]->comments_count;
🎜🎜🎜🎜🎜🎜Persatuan satu-ke-banyak jauh
Persatuan satu-ke-banyak jauh menyediakan cara yang mudah dan singkat untuk mendapatkan persatuan peringkat jauh melalui persatuan perantaraan. Contohnya, model Negara
boleh mempunyai berbilang model Post
melalui model User
perantaraan. Dalam contoh ini, anda boleh dengan mudah mengumpul semua catatan blog dari negara tertentu. Mari kita lihat jadual data yang diperlukan untuk mentakrifkan perkaitan ini: Country
模型可以通过中间的 User
模型获得多个 Post
模型。在这个例子中,你可以轻易地收集给定国家的所有博客文章。让我们来看看定义这种关联所需的数据表:
$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;
虽然 posts
表中不包含 country_id
字段,但 hasManyThrough
关联能让我们通过 $country->posts
访问到一个国家下所有的用户文章。为了完成这个查询,Eloquent 会先检查中间表 users
的 country_id
字段,找到所有匹配的用户 ID 后,使用这些 ID,在 posts
表中完成查找。
现在,我们已经知道了定义这种关联所需的数据表结构,接下来,让我们在 Country
模型中定义它:
$query = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;
hasManyThrough
方法的第一个参数是我们最终希望访问的模型名称,而第二个参数是中间模型的名称。
当执行关联查询时,通常会使用 Eloquent 约定的外键名。如果你想要自定义关联的键,可以通过给 hasManyThrough
方法传递第三个和第四个参数实现,第三个参数表示中间模型的外键名,第四个参数表示最终模型的外键名。第五个参数表示本地键名,而第六个参数表示中间模型的本地键名:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model{
/**
* 获取书籍作者。
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
多态关联
多态关联允许目标模型借助单个关联从属于多个模型。
一对一(多态)
表结构
一对一多态关联与简单的一对一关联类似;不过,目标模型能够在一个关联上从属于多个模型。例如,博客 Post
和 User
可能共享一个关联到 Image
模型的关系。使用一对一多态关联允许使用一个唯一图片列表同时用于博客文章和用户账户。让我们先看看表结构:
$books = App\Book::all();
foreach ($books as $book)
{
echo $book->author->name;
}
要特别留意 images
表的 imageable_id
和 imageable_type
列。 imageable_id
列包含文章或用户的 ID 值,而 imageable_type
列包含的则是父模型的类名。Eloquent 在访问 imageable
时使用 imageable_type
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
Walaupun jadual posts
tidak mengandungi medan country_id
, hasManyThrough
Persatuan itu membenarkan kami mengakses semua siaran pengguna di sesebuah negara melalui $country->posts
. Untuk melengkapkan pertanyaan ini, Eloquent akan menyemak medan country_id
pada jadual perantaraan users
Selepas mencari semua ID pengguna yang sepadan, gunakan ID ini untuk menyiarkan dalam catatan
Lengkapkan carian dalam jadual. Sekarang kita tahu struktur jadual data yang diperlukan untuk mentakrifkan perkaitan ini, mari kita takrifkannya dalam model Negara
: select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
kaedahhasManyThrough
Parameter pertama ialah nama model yang akhirnya ingin kami akses, manakala parameter kedua ialah nama model perantaraan. Apabila melaksanakan pertanyaan berkaitan, nama kunci asing konvensional Eloquent biasanya digunakan. Jika anda ingin menyesuaikan kunci yang berkaitan, anda boleh berbuat demikian dengan menghantar parameter ketiga dan keempat kepada kaedah hasManyThrough
Parameter ketiga mewakili nama kunci asing bagi model perantaraan dan parameter keempat mewakili Nama kunci asing bagi model akhir. Parameter kelima mewakili nama kunci tempatan, manakala parameter keenam mewakili nama kunci tempatan model perantaraan: $books = App\Book::with(['author', 'publisher'])->get();
🎜🎜Persatuan Polimorfik
🎜Persatuan polimorfik membenarkan model sasaran menjadi subordinat kepada berbilang model dengan satu perkaitan. 🎜🎜🎜🎜🎜Satu-dengan-satu (polimorfik)🎜< div name="03a0d2" data-unique="03a0d2">🎜🎜Struktur jadual🎜🎜Perkaitan polimorfik satu-dengan-satu adalah serupa dengan perkaitan satu-dengan-satu yang ringkas walau bagaimanapun, model sasaran boleh dimiliki oleh berbilang model; satu persatuan. Sebagai contoh, blog Post
dan User
mungkin berkongsi hubungan dengan model Imej
. Menggunakan perkaitan polimorfik satu-dengan-satu membolehkan penggunaan senarai imej yang unik untuk kedua-dua catatan blog dan akaun pengguna. Mari kita lihat struktur jadual dahulu: 🎜$books = App\Book::with('author.contacts')->get();
🎜Beri perhatian khusus pada lajur imageable_id
dan imageable_type
pada jadual images
. Lajur imageable_id
mengandungi nilai siaran atau ID pengguna, manakala lajur imageable_type
mengandungi nama kelas model induk. Eloquent menggunakan lajur imageable_type
untuk menentukan "jenis" model induk apabila mengakses imageable
. 🎜🎜🎜🎜Struktur model🎜🎜Seterusnya, mari lihat definisi model untuk mewujudkan persatuan: 🎜$users = App\Book::with('author:id,name')->get();
🎜🎜Mendapatkan persatuan
Setelah jadual dan model ditakrifkan, persatuan ini boleh diakses melalui model. Contohnya, untuk mendapatkan imej artikel, anda boleh menggunakan atribut dinamik imej
: image
动态属性:
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
还可以通过访问执行 morphTo
调用的方法名来从多态模型中获知父模型。在这个例子中,就是 Image
模型的 imageable
方法。所以,我们可以像动态属性那样访问这个方法:
$users = App\User::with(['posts' => function ($query) {
$query->orderBy('created_at', 'desc');
}])->get();
Image
模型的 imageable
关联将返回 Post
或 User
实例,其结果取决于图片属性哪个模型。
一对多(多态)
表结构
一对多多态关联与简单的一对多关联类似;不过,目标模型可以在一个关联中从属于多个模型。假设应用中的用户可以同时 「评论」 文章和视频。使用多态关联,可以用单个 comments
表同时满足这些情况。我们还是先来看看用来构建这种关联的表结构:
$books = App\Book::all();
if ($someCondition) {
$books->load('author', 'publisher');
}
模型结构
接下来,看看构建这种关联的模型定义:
$books->load(['author' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 comments
动态属性访问文章的全部评论:
public function format(Book $book){
$book->loadMissing('author');
return [
'name' => $book->name,
'author' => $book->author->name
];
}
还可以通过访问执行 morphTo
调用的方法名来从多态模型获取其所属模型。在本例中,就是 Comment
模型的 commentable
方法:
<?php
use Illuminate\Database\Eloquent\Model;
class ActivityFeed extends Model{
/**
* Get the parent of the activity feed record.
*/
public function parentable()
{
return $this->morphTo();
}
}
Comment
模型的 commentable
关联将返回 Post
或 Video
实例,其结果取决于评论所属的模型。
多对多(多态)
表结构
多对多多态关联比 morphOne
和 morphMany
关联略微复杂一些。例如,博客 Post
和 Video
模型能够共享关联到 Tag
模型的多态关系。使用多对多多态关联允许使用一个唯一标签在博客文章和视频间共享。以下是多对多多态关联的表结构:
$activities = ActivityFeed::with('parentable')
->get()
->loadMorph('parentable', [
Event::class => ['calendar'],
Photo::class => ['tags'],
Post::class => ['author'],
]);
模型结构
接下来,在模型上定义关联。Post
和 Video
模型都有调用 Eloquent 基类上 morphToMany
方法的 tags
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);
Anda juga boleh mendapatkan model induk daripada model polimorfik dengan mengakses nama kaedah yang melaksanakan morphTo
panggilan. Dalam kes ini, ini ialah kaedah imageable
model Image
. Jadi, kita boleh mengakses kaedah ini seperti sifat dinamik: $post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);
Imej Perkaitan imageable
model akan mengembalikan sama ada Post
atau User Contoh < /code>, hasilnya bergantung pada model mana atribut imej itu. 🎜🎜🎜🎜Satu-ke-banyak (polimorfik) < /h3>🎜🎜Struktur jadual🎜🎜Perkaitan polimorfik satu-ke-banyak adalah serupa dengan perkaitan satu-ke-banyak yang mudah, walau bagaimanapun, model sasaran boleh bawahan kepada banyak dalam satu model persatuan. Anggapkan bahawa pengguna dalam aplikasi boleh "mengulas" pada artikel dan video pada masa yang sama. Menggunakan perkaitan polimorfik, anda boleh memenuhi kedua-dua situasi ini dengan satu jadual ulasan
. Mari kita lihat struktur jadual yang digunakan untuk membina persatuan ini: 🎜$post = App\Post::find(1);
$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';$post->push();
🎜🎜Struktur model🎜🎜Seterusnya, mari lihat model yang membina persatuan ini Definisi : 🎜$post = App\Post::find(1);
$comment = $post->comments()->create([
'message' => 'A new comment.',
]);
🎜🎜Dapatkan perkaitan 🎜🎜Setelah jadual dan model pangkalan data ditakrifkan, perkaitan itu boleh diakses melalui model. Sebagai contoh, anda boleh mengakses semua ulasan untuk artikel menggunakan atribut dinamik comments
: 🎜$post = App\Post::find(1);$post->comments()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
🎜 Anda juga boleh mendapatkan model yang dimilikinya daripada model polimorfik dengan mengakses nama kaedah yang melaksanakan panggilan morphTo
. Dalam kes ini, kaedah commentable
model Comment
: 🎜$account = App\Account::find(10);
$user->account()->associate($account);$user->save();
🎜 Perkaitan Commentable
model commentable
akan mengembalikan Siarkan
atau Video
, hasilnya bergantung pada model yang menjadi milik ulasan. 🎜🎜🎜🎜Many-to-many (polimorfik) < /h3>🎜🎜Struktur jadual🎜🎜Perkaitan polimorfik banyak-ke-banyak adalah lebih kompleks sedikit daripada morphOne
dan morphMany
persatuan Beberapa. Contohnya, model Blog Post
dan Video
boleh berkongsi hubungan polimorfik dengan model Tag
. Menggunakan perkaitan polimorfik banyak-ke-banyak membolehkan perkongsian antara catatan blog dan video menggunakan teg unik. Berikut ialah struktur jadual perkaitan polimorfik banyak-ke-banyak: 🎜$user->account()->dissociate();$user->save();
🎜🎜Struktur model🎜🎜Seterusnya, tentukan perkaitan pada model. Kedua-dua model Post
dan Video
mempunyai kaedah tag
yang memanggil kaedah morphToMany
pada kelas asas Eloquent: 🎜/**
* 获取帖子的作者。
*/
public function user(){
return $this->belongsTo('App\User')->withDefault();
}
🎜🎜Tentukan hubungan perkaitan terbalik
Seterusnya, anda perlu menentukan kaedah untuk setiap model perkaitan pada model Tag
. Dalam contoh ini, kami akan mentakrifkan kaedah siaran dan kaedah video: Tag
模型上为每个关联模型定义一个方法。在这个示例中,我们将会定义 posts
方法和 videos
方法:
/**
* 获取帖子的作者。
*/
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';
});
}
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 tags
动态属性访问文章的所有标签:
$user = App\User::find(1);
$user->roles()->attach($roleId);
还可以访问执行 morphedByMany
方法调用的方法名来从多态模型获取其所属模型。在这个示例中,就是 Tag
模型的 posts
或 videos
方法。可以像动态属性一样访问这些方法:
$user->roles()->attach($roleId, ['expires' => $expires]);
自定义多态类型
默认情况下, Laravel 使用完全限定类名存储关联模型类型。在上面的一对多示例中, 因为 Comment
可能从属于一个 Post
或一个 Video
,默认的 commentable_type
就将分别是 AppPost
或 AppVideo
。不过,你可能希望数据库与应用的内部结构解耦。在这种情况下,可以定义一个 「morph 映射」 来通知 Eloquent 使用自定义名称代替对应的类名:
// 移除用户的一个角色...
$user->roles()->detach($roleId);
// 移除用户的所有角色...
$user->roles()->detach();
可以在 AppServiceProvider
的 boot
函数中注册 morphMap
,或者创建一个单独的服务提供者。
查询关联
由于 Eloquent 关联的所有类型都通过方法定义,你可以调用这些方法,而无需真实执行关联查询。另外,所有 Eloquent 关联类型用作 查询构造器,允许你在数据库上执行 SQL 之前,持续通过链式调用添加约束。
例如,假设一个博客系统的 User
模型有许多关联的 Post
模型:
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([
1 => ['expires' => $expires],
2 => ['expires' => $expires]
]);
你可以查询 posts
$user->roles()->sync([1, 2, 3]);
Dapatkan perkaitan
Setelah jadual dan model pangkalan data ditakrifkan, perhubungan boleh diakses melalui model. Sebagai contoh, anda boleh menggunakan atribut dinamik tag
untuk mengakses semua teg artikel: $user->roles()->sync([1 => ['expires' => true], 2, 3]);
Anda juga boleh mengakses nama kaedah yang melaksanakan panggilan kaedah morphedByMany
untuk mendapatkan model yang dimilikinya daripada model polimorfik. Dalam contoh ini, kaedah siaran
atau video
model Tag
. Kaedah ini boleh diakses seperti sifat dinamik:
$user->roles()->syncWithoutDetaching([1, 2, 3]);
🎜🎜Jenis polimorfik tersuai h3>🎜Secara lalai, Laravel menyimpan jenis model yang berkaitan menggunakan nama kelas yang layak sepenuhnya. Dalam contoh satu-ke-banyak di atas, memandangkan Ulasan
mungkin tergolong dalam Catatan
atau Video
, lalai commentable_type kod > akan menjadi AppPost
atau AppVideo
masing-masing. Walau bagaimanapun, anda mungkin mahu memisahkan pangkalan data daripada struktur dalaman aplikasi anda. Dalam kes ini, anda boleh mentakrifkan "pemetaan morf" untuk memberitahu Eloquent supaya menggunakan nama tersuai dan bukannya nama kelas yang sepadan: 🎜$user->roles()->toggle([1, 2, 3]);
🎜Boleh dilakukan dalam fungsi boot
AppServiceProvider< /code> Daftar morphMap
, atau buat pembekal perkhidmatan yang berasingan. 🎜🎜🎜🎜🎜Hubungan pertanyaan
🎜Oleh kerana semua jenis hubungan Eloquent ditakrifkan melalui kaedah , anda boleh memanggil kaedah ini tanpa benar-benar melaksanakan pertanyaan berkaitan. Selain itu, semua jenis hubungan Eloquent bertindak sebagai pembina pertanyaan, membolehkan anda menambah kekangan secara berterusan melalui rangkaian panggilan sebelum melaksanakan SQL pada pangkalan data. 🎜🎜Sebagai contoh, katakan model User
sistem blog mempunyai banyak model Post
yang berkaitan: 🎜App\User::find(1)->roles()->save($role, ['expires' => $expires]);
🎜Anda boleh menanyakan perkaitan posts
dan menyediakannya menambah kekangan tambahan: 🎜$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
🎜 Anda boleh menggunakan mana-mana kaedah pembina pertanyaan pada perkaitan, sila rujuk dokumentasi pembina pertanyaan untuk mengetahui kaedah yang mungkin berguna kepada anda. 🎜🎜🎜🎜🎜🎜🎜Kaedah Perhubungan Vs. Sifat Dinamik
Jika anda tidak perlu menambah kekangan tambahan pada pertanyaan perhubungan Eloquent anda, anda boleh mengakses perhubungan seperti harta. Sebagai contoh, terus menggunakan model contoh User
dan Post
, anda boleh mengakses semua siaran pengguna seperti ini: User
和 Post
示例模型,可以这样访问用户的全部文章:
<?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');
}
}
动态属性是「懒加载」的,这意味着它们仅在你真实访问关联数据时才被载入。因此,开发者经常使用 预加载 预先加载那些他们确知在载入模型后将访问的关联。对载入模型关联中必定被执行的 SQL 查询而言,预加载显著减少了查询的执行次数。
查询已存在的关联
在访问模型记录时,可能希望基于关联的存在限制查询结果。比如想要获取至少存在一条评论的所有文章,可以通过给 has
和 orHas
方法传递关联名称来实现:
$comment = App\Comment::find(1);
$comment->text = 'Edit to this comment!';
$comment->save();
还可以指定运算符和数量进一步自定义查询:
rrreee还可以用 「点」语法构造嵌套的 has
语句。比如,可以获取拥有至少一条评论和投票的文章:
rrreee如果需要更多功能,可以使用 whereHas
和 orWhereHas
方法将「where」 条件放到 has
查询上。这些方法允许你向关联加入自定义约束,比如检查评论内容:
rrreee查询不存在的关联
在访问模型记录时,可能希望基于关联不存在来限制查询结果。假设想要获取不存在任何评论的文章,可以通过向 doesntHave
和 orDoesntHave
方法传递关联名称来实现:
rrreee如果需要更多功能,可以使用 whereDoesntHave
和 orWhereDoesntHave
方法将「where」 条件加到 doesntHave
rrreee
Sifat dinamik adalah "lazy loaded", yang bermakna ia hanya dimuatkan apabila Data yang berkaitan dimuatkan hanya apabila anda benar-benar mengaksesnya. Oleh itu, pembangun sering menggunakan eger-loading untuk pramuat perhubungan tersebut yang mereka tahu akan mereka akses selepas memuatkan model. Untuk pertanyaan SQL yang mesti dilaksanakan semasa memuatkan perkaitan model, pemuatan yang bersemangat mengurangkan bilangan pelaksanaan pertanyaan dengan ketara.
Soal perhubungan sedia ada🎜Apabila mengakses rekod model, anda mungkin mahu berdasarkan hubungan Kewujudan menghadkan hasil pertanyaan. Contohnya, jika anda ingin mendapatkan semua artikel dengan sekurang-kurangnya satu ulasan, anda boleh menghantar nama persatuan kepada kaedah has
dan orHas
: 🎜rrreee🎜Anda juga boleh menentukan operator dan kuantiti untuk pertanyaan tersuai selanjutnya: 🎜rrreee🎜 Anda juga boleh menggunakan sintaks "titik" untuk membina penyataan mempunyai
bersarang. Sebagai contoh, anda boleh mendapatkan artikel dengan sekurang-kurangnya satu ulasan dan undi: 🎜rrreee🎜Jika anda memerlukan lebih banyak fungsi, anda boleh menggunakan kaedah whereHas
dan orWhereHas
untuk meletakkan " di mana" keadaan dalam < code>mempunyai pertanyaan. Kaedah ini membolehkan anda menambah kekangan tersuai pada perhubungan, seperti menyemak kandungan ulasan: 🎜rrreee🎜🎜🎜🎜🎜 Pertanyaan untuk perhubungan yang tidak wujud🎜🎜Apabila mengakses rekod model, anda mungkin mahu mengehadkan hasil pertanyaan berdasarkan ketiadaan perhubungan. Katakan anda ingin mendapatkan artikel yang tidak mempunyai ulasan Anda boleh melakukannya dengan menghantar nama persatuan kepada kaedah doesntHave
dan orDoesntHave
: 🎜 rrreee🎜Jika diperlukan Untuk lebih banyak fungsi, anda boleh menggunakan kaedah whereDoesntHave
dan orWhereDoesntHave
untuk menambah keadaan "where" pada pertanyaan doesntHave
. Kaedah ini membolehkan anda menambah sekatan tersuai pada perkaitan, seperti mengesan kandungan ulasan: 🎜rrreee🎜Anda juga boleh menggunakan sintaks "titik" untuk melaksanakan pertanyaan perkaitan bersarang. Sebagai contoh, pertanyaan berikut digunakan untuk mendapatkan artikel dengan ulasan daripada pengarang yang tidak dilarang: 🎜rrreee🎜🎜🎜🎜🎜🎜Kiraan model perhubungan
Jika anda hanya mahu mengira bilangan statistik hasil perkaitan tanpa benar-benar memuatkannya, anda boleh menggunakan kaedah withCount
, yang akan diletakkan dalam {relation}_count < daripada model hasil /kod> lajur. Contohnya adalah seperti berikut: withCount
方法,它将放在结果模型的 {relation}_count
列。示例如下:
rrreee可以像给查询添加限制一样为多个关系添加「计数」:
rrreee还可以给关联计数结果起别名,这允许你在同一关联上添加多个计数:
rrreee如果将 withCount
和 select
查询组装在一起,请确保在 select
方法之后调用 withCount
:
rrreee预加载
当以属性方式访问 Eloquent 关联时,关联数据「懒加载」。这着直到第一次访问属性时关联数据才会被真实加载。不过 Eloquent 能在查询父模型时「预先载入」子关联。预加载可以缓解 N + 1 查询问题。为了说明 N + 1 查询问题,考虑 Book
模型关联到 Author
的情形:
rrreee现在,我们来获取所有的书籍及其作者:
rrreee此循环将执行一个查询,用于获取全部书籍,然后为每本书执行获取作者的查询。如果我们有 25 本书,此循环将运行 26 个查询:1 个用于查询书籍,25 个附加查询用于查询每本书的作者。
谢天谢地,我们能够使用预加载将操作压缩到只有 2 个查询。在查询时,可以使用 with
方法指定想要预加载的关联:
rrreee在这个例子中,仅执行了两个查询:
rrreee预加载多个关联
有时,你可能需要在单一操作中预加载几个不同的关联。要达成此目的,只要向 with
方法传递多个关联名称构成的数组参数:
rrreee嵌套预加载
可以使用 「点」 语法预加载嵌套关联。比如在一个 Eloquent 语句中预加载所有书籍作者及其联系方式:
rrreee预加载指定列
并不是总需要获取关系的每一列。在这种情况下,Eloquent 允许你为关联指定想要获取的列:
rrreee{note} 在使用这个特性时,一定要在要获取的列的列表中包含 id
rrreee
Anda boleh menambah "kiraan" pada berbilang perhubungan sama seperti menambahkan sekatan pada pertanyaan:
rrreee Anda juga boleh alias hasil kiraan perhubungan, yang membolehkan anda menambah berbilang kiraan pada perhubungan yang sama: rrreeeJika Untuk memasang pertanyaan withCount
dan select
bersama-sama, pastikan untuk memanggil withCount
selepas kaedah select
:
rrreee< a name="eager-loading">🎜🎜Eager loading
🎜Apabila mengakses Eloquent associations sebagai atribut, data adalah "malas" memuatkan". Dengan cara ini, data yang berkaitan sebenarnya tidak akan dimuatkan sehingga kali pertama harta itu diakses. Walau bagaimanapun, Eloquent boleh "memuat pramuat" perhubungan anak apabila menanyakan model induk. Pemuatan yang bersemangat boleh mengurangkan masalah pertanyaan N+1. Untuk menggambarkan masalah pertanyaan N + 1, pertimbangkan kes di mana model Book
dikaitkan dengan Author
: 🎜rrreee🎜Sekarang, mari dapatkan semua buku dan pengarangnya: 🎜 rrreee🎜Ini Gelung akan melaksanakan pertanyaan untuk mendapatkan semua buku, dan kemudian untuk setiap buku, laksanakan pertanyaan untuk mendapatkan pengarang. Jika kita mempunyai 25 buku, gelung ini akan menjalankan 26 pertanyaan: 1 untuk menanyakan buku dan 25 pertanyaan tambahan untuk menanyakan pengarang setiap buku. 🎜🎜Syukurlah kami dapat memendekkan operasi kepada hanya 2 pertanyaan menggunakan pemuatan yang bersemangat. Pada masa pertanyaan, anda boleh menggunakan kaedah with
untuk menentukan perkaitan yang anda mahu pramuat: 🎜rrreee🎜Dalam contoh ini, hanya dua pertanyaan telah dilaksanakan: 🎜rrreee🎜Pramuat berbilang persatuan
🎜Kadangkala, anda mungkin perlu pramuat beberapa persatuan berbeza dalam satu operasi. Untuk mencapai ini, hanya hantar parameter tatasusunan yang terdiri daripada berbilang nama yang berkaitan kepada kaedah dengan
: 🎜rrreee🎜Pemuatan pratetap bersarang
🎜Anda boleh menggunakan sintaks "titik" untuk pramuat perkaitan bersarang. Sebagai contoh, pramuat semua pengarang buku dan maklumat hubungan mereka dalam satu pernyataan Eloquent: 🎜rrreee🎜Pramuat lajur yang ditentukan
🎜 tidak selalu diperlukan Dapatkan setiap lajur perhubungan. Dalam kes ini, Eloquent membenarkan anda untuk menentukan lajur yang anda ingin dapatkan untuk perkaitan: 🎜rrreee🎜{note} Apabila menggunakan ciri ini, pastikan anda memasukkan id dalam senarai lajur untuk mendapatkan . kod> lajur. 🎜🎜🎜🎜🎜🎜🎜🎜Menambah kekangan untuk pramuat
Kadangkala, anda mungkin mahu pramuat perhubungan sambil menambah syarat pertanyaan tambahan pada pertanyaan pramuat, seperti contoh berikut:
rrreeeDalam contoh ini, Eloquent hanya akan pramuat Artikel yang tajuknya< Lajur /code> mengandungi kata kunci first
. Anda juga boleh memanggil kaedah pembina pertanyaan lain untuk menyesuaikan lagi operasi pramuat: title
列包含 first
关键词的文章。也可以调用其它的 查询构造器 方法进一步自定义预加载操作:
rrreee{note} 在约束预加载时,不能使用 limit
和 take
查询构造器方法。
预加载
有可能你还希望在模型加载完成后在进行渴求式加载。举例来说,如果你想要动态的加载关联数据,那么 load
方法对你来说会非常有用:
rrreee如果你想要在渴求式加载的查询语句中进行条件约束,你可以通过数组的形式去加载,键为对应的关联关系,值为 Closure
闭包函数,该闭包的参数为一个 query
实例:
rrreee当关联关系没有被加载时,你可以使用 loadMissing
方法:
rrreee嵌套延迟加载 & morphTo
如果希望快速加载 morphTo
关系,以及该关系可能返回的各种实体上的嵌套关系,可以使用 loadMorph
方法。
这个方法接受 morphTo
关系的名称作为它的第一个参数,第二个参数接收模型数组、关系数组。为了帮助说明这个方法,可以看一下以下模型例子:
rrreee在这个例子中,让我们假设 Event
、Photo
和 Post
模型可以创建 ActivityFeed
模型。此外,让我们假设 Event
模型属于 Calendar
模型,Photo
模型与 Tag
模型相关联,Post
模型属于 Author
模型。
使用这些模型定义和关系,我们可以检索 ActivityFeed
模型实例,并立即加载所有 parentable
rrreee
{note} Apabila mengekang pramuat, anda tidak boleh menggunakan had
dan take
Pembina pertanyaan kaedah.
PreloadingMungkin anda juga mahu selesai memuatkan model tersebut melakukan pemuatan bersemangat. Sebagai contoh, jika anda ingin memuatkan data berkaitan secara dinamik, maka kaedah load
akan sangat berguna untuk anda: Apabila perkaitan tidak dimuatkan, anda boleh menggunakan kaedah loadMissing
: rrreeeNested lazy loading& morphTo< /code>
🎜Jika anda ingin memuatkan perhubungan morphTo
dengan cepat, serta perhubungan bersarang pada pelbagai entiti yang mungkin dikembalikan oleh perhubungan itu, anda boleh menggunakan loadMorph
kaedah. 🎜🎜Kaedah ini menerima nama perhubungan morphTo
sebagai parameter pertamanya dan parameter kedua menerima tatasusunan model dan tatasusunan perhubungan. Untuk membantu menggambarkan pendekatan ini, lihat contoh model berikut: 🎜rrreee🎜Dalam contoh ini, mari kita anggap Acara
, Foto
dan Post
Model boleh membuat model ActivityFeed
. Tambahan pula, mari kita anggap bahawa model Acara
tergolong dalam model Kalendar
, model Foto
dikaitkan dengan Tag
model dan model Post
tergolong dalam model Author
. 🎜🎜Dengan menggunakan definisi dan perhubungan model ini, kami boleh mendapatkan semula contoh model ActivityFeed
dan memuatkan semua model parentable
dan perhubungan bersarang masing-masing sekaligus: 🎜rrreee🎜🎜🎜🎜 🎜 🎜🎜Masukkan & kemas kini model yang berkaitan🎜🎜🎜🎜🎜🎜🎜Kaedah simpan
Eloquent menyediakan cara yang mudah untuk menambah persatuan pada model baharu. Sebagai contoh, mungkin anda perlu menambah Ulasan
baharu pada model Post
. Anda tidak perlu menetapkan atribut post_id
secara manual dalam Comment
, anda boleh terus menggunakan kaedah save
model yang berkaitan untuk menyimpan Komen
secara langsung Sisipkan: Comment
到一个 Post
模型中。你不用在 Comment
中手动设置 post_id
属性,就可以直接使用关联模型的 save
方法将 Comment
直接插入:
rrreee需要注意的是,我们并没有使用动态属性的方式访问 comments
关联。相反,我们调用 comments
方法来获得关联实例。save
方法将自动添加适当的 post_id
值到 Comment
模型中。
如果你需要保存多个关联模型,你可以使用 saveMany
方法:
rrreee递归保存模型和关联数据
如果你想 save
你的模型及其所有关联数据,你可以使用 push
方法:
rrreee新增方法
除了 save
和 saveMany
方法外,你还可以使用 create
方法。它接受一个属性数组,同时会创建模型并插入到数据库中。 还有, save
方法和 create
方法的不同之处在于, save
方法接受一个完整的 Eloquent 模型实例,而 create
则接受普通的 PHP 数组:
rrreee{tip} 在使用 create
方法前,请务必确保查看过本文档的 批量赋值 章节。
你还可以使用 createMany
方法去创建多个关联模型:
rrreee你还可以使用 findOrNew
、firstOrNew
、firstOrCreate
和 updateOrCreate
方法来 创建和更新关系模型.
更新 belongsTo
关联
当更新 belongsTo
关联时,可以使用 associate
方法。此方法将会在子模型中设置外键:
rrreee当移除 belongsTo
关联时,可以使用 dissociate
方法。此方法会将关联外键设置为 null
rrreee
Perlu diambil perhatian bahawa kami tidak menggunakan atribut dinamik untuk mengakses perkaitan ulasan
. Sebaliknya, kami memanggil kaedah ulasan
untuk mendapatkan contoh yang berkaitan. Kaedah save
akan menambah nilai post_id
secara automatik pada model Comment
. Jika anda perlu menyimpan berbilang model yang berkaitan, anda boleh menggunakan kaedah saveMany
: rrreee
🎜Simpan model dan data yang berkaitan secara rekursif
🎜Jika anda ingin simpan
model anda dan semua data yang berkaitan, anda boleh menggunakan push< / kod> Kaedah:🎜rrreee🎜🎜🎜🎜🎜Kaedah baharu🎜🎜Kecuali simpan Selain kaedah kod> dan saveMany
, anda juga boleh menggunakan kaedah create
. Ia menerima pelbagai sifat, mencipta model dan memasukkannya ke dalam pangkalan data. Selain itu, perbezaan antara kaedah save
dan kaedah create
ialah kaedah save
menerima contoh model Eloquent yang lengkap, manakala create
menerima tatasusunan PHP biasa: 🎜rrreee🎜{tip} Sebelum menggunakan kaedah create
, sila pastikan anda menyemak bab tugasan kelompok dokumen ini. 🎜
🎜Anda juga boleh menggunakan kaedah createMany
untuk mencipta berbilang model yang berkaitan: 🎜rrreee🎜Anda juga boleh menggunakan findOrNew
, firstOrNew
, kaedah firstOrCreate
dan updateOrCreate
untuk mencipta dan mengemas kini model perhubungan.🎜🎜🎜🎜🎜🎜Kemas kini persatuan belongsTo
🎜🎜Apabila mengemas kini persatuan belongsTo
, anda boleh menggunakan kaedah associate
. Kaedah ini akan menetapkan kunci asing dalam model anak: 🎜rrreee🎜Apabila mengalih keluar perkaitan belongsTo
, anda boleh menggunakan kaedah dissociate
. Kaedah ini akan menetapkan kunci asing yang berkaitan kepada null:🎜rrreee🎜🎜🎜🎜🎜🎜Model Lalai
Perhubungan milik
membolehkan anda menentukan model lalai Apabila perhubungan yang diberikan adalah null, model lalai akan dikembalikan. Corak ini dipanggil Null Object Pattern dan boleh mengurangkan semakan yang tidak perlu dalam kod anda. Dalam contoh di bawah, jika pengarang siaran yang diterbitkan tidak ditemui, perhubungan user
akan mengembalikan model AppUser
kosong: belongsTo
关系允许你指定默认模型,当给定关系为 null
时,将会返回默认模型。 这种模式被称作 Null 对象模式 ,可以减少你代码中不必要的检查。在下面的例子中,如果发布的帖子没有找到作者, user
关系会返回一个空的 AppUser
模型:
rrreee如果需要在默认模型里添加属性, 你可以传递数组或者回调方法到 withDefault
中:
rrreee多对多关联
附加 / 分离
Eloquent 也提供了一些额外的辅助方法,使相关模型的使用更加方便。例如,我们假设一个用户可以拥有多个角色,并且每个角色都可以被多个用户共享。给某个用户附加一个角色是通过向中间表插入一条记录实现的,可以使用 attach
方法完成该操作:
rrreee在将关系附加到模型时,还可以传递一组要插入到中间表中的附加数据:
rrreee当然,有时也需要移除用户的角色。可以使用 detach
移除多对多关联记录。detach
方法将会移除中间表对应的记录;但是这 2 个模型都将会保留在数据库中:
rrreee为了方便,attach
和 detach
也允许传递一个 ID 数组:
rrreee同步关联
你也可以使用 sync
方法构建多对多关联。sync
方法接收一个 ID 数组以替换中间表的记录。中间表记录中,所有未在 ID 数组中的记录都将会被移除。所以该操作结束后,只有给出数组的 ID 会被保留在中间表中:
rrreee你也可以通过 ID 传递额外的附加数据到中间表:
rrreee如果你不想移除现有的 ID,可以使用 syncWithoutDetaching
方法:
rrreee切换关联
多对多关联也提供了 toggle
rrreee
Jika anda perlu menambah atribut kepada model lalai, Anda boleh menghantar tatasusunan atau kaedah panggil balik kepada withDefault
: rrreeePersatuan banyak-ke-banyak
Attach/DetachEloquent juga menyediakan beberapa kaedah tambahan tambahan, menjadikan penggunaan model berkaitan lebih mudah. Sebagai contoh, mari kita anggap bahawa pengguna boleh mempunyai berbilang peranan dan setiap peranan boleh dikongsi oleh berbilang pengguna. Melampirkan peranan kepada pengguna dicapai dengan memasukkan rekod ke dalam jadual perantaraan Operasi ini boleh dicapai menggunakan kaedah attach
: 🎜rrreee🎜Apabila melampirkan perhubungan pada model, anda juga boleh menghantar a. set keperluan Data tambahan dimasukkan ke dalam jadual perantaraan: 🎜rrreee🎜 Sudah tentu, kadangkala ia juga perlu untuk mengalih keluar peranan pengguna. Rekod berkaitan banyak-ke-banyak boleh dialih keluar menggunakan cabut
. Kaedah detach
akan mengalih keluar rekod yang sepadan dengan jadual perantaraan tetapi kedua-dua model ini akan kekal dalam pangkalan data: 🎜rrreee🎜Untuk kemudahan, attach
dan detach<; /code> juga membenarkan menghantar pelbagai ID: 🎜rrreee🎜🎜Perkaitan segerak🎜🎜Anda juga boleh menggunakan kaedah sync
untuk membina berbilang persatuan Satu-ke-banyak. Kaedah sync
menerima tatasusunan ID untuk menggantikan rekod jadual perantaraan. Antara rekod jadual perantaraan, semua rekod yang tiada dalam tatasusunan ID akan dialih keluar. Jadi selepas operasi, hanya ID tatasusunan yang diberikan akan dikekalkan dalam jadual perantaraan: 🎜rrreee🎜 Anda juga boleh menghantar data tambahan tambahan kepada jadual perantaraan dengan ID: 🎜rrreee🎜 Jika anda tidak mahu mengalih keluar yang sedia ada ID, Anda boleh menggunakan kaedah syncWithoutDetaching
: 🎜rrreee🎜🎜Togol persatuan 🎜🎜Many-to-many association juga menyediakan togol
Kaedah yang digunakan untuk "togol" keadaan dilampirkan tatasusunan ID yang diberikan. Jika ID yang diberikan telah dilampirkan dalam jadual perantaraan, maka ia akan dialih keluar, begitu juga jika ID yang diberikan telah dialih keluar, ia akan ditambahkan: 🎜rrreee🎜🎜🎜Simpan pada jadual perantaraan Data tambahan🎜🎜Apabila berurusan dengan banyak -kepada-banyak perhubungan, kaedah simpan menerima tatasusunan data tambahan sebagai parameter kedua: 🎜rrreee🎜🎜Kemas kini rekod jadual perantaraan
Jika anda perlu mengemas kini rekod sedia ada dalam jadual perantaraan, anda boleh menggunakan updateExistingPivot
. Kaedah ini menerima kunci asing jadual perantaraan dan tatasusunan data yang akan dikemas kini untuk kemas kini: updateExistingPivot
。此方法接收中间表的外键与要更新的数据数组进行更新:
rrreee更新父级时间戳
当一个模型属 belongsTo
或者 belongsToMany
另一个模型时, 例如 Comment
属于 Post
,有时更新子模型导致更新父模型时间戳非常有用。例如,当 Comment
模型被更新时,您要自动「触发」父级 Post
模型的 updated_at
时间戳的更新。Eloquent 让它变得简单。只要在子模型加一个包含关联名称的 touches
属性即可:
rrreee现在,当你更新一个 Comment
时,对应父级 Post
模型的 updated_at
字段同时也会被更新,使其更方便得知何时让一个 Post
rrreee
rrreee🎜Sekarang, apabila anda mengemas kini Ulasan
, ibu bapa yang sepadan Post The Medan updated_at
model> juga akan dikemas kini, menjadikannya lebih mudah untuk mengetahui masa untuk membatalkan cache model Post
: 🎜rrreee🎜Artikel ini mula-mula muncul pada 🎜 Laman web LearnKu.com🎜. 🎜🎜
Laman web PHP Cina