Relations on databases,
$user->posts()->where('active', 1)->get();
如果我們想要使用這種方式去關聯其他table的話
需要再User Class使用方法
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
這樣Eloquent Dynamic binding自動會幫我們抓取資料,上述範例就可以讓我們使用$user->phone(); 取得phone.
一個user 僅有一個phone,預備機制,phone tables內要有user_id,(FK)這樣就會自動綁定,
return $this->hasOne('App\Phone', 'foreign_key');
另外加參數可以附加FK,這樣的機制下,我們會拿user_id去phone裡面找user_id是否吻合,並取出資料。
class Phone extends Model
{
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
反向關系 Inverse relations, 在Phone裡面使用belongsTo(),變相表示phone屬於user. 上述例子eloquent會取抓phone裡面的user_id去跟User table的id比對
預設上Eloquent會抓取method name加上_id 當成FK,上面看到method 是 user() 所以user + _id 這樣就會是拿Phone裡面的user_id,假設今天你的Phone FK不叫作
user_id,名字是userforeignkey_id,那上面的範例就要從user()改成userforeignkey(),或者是你直接在方法內給第二個參數名稱,就會使用該參數當作FK了ˊ!!
$this->belongsTo('App\User', 'foreign_key');
假設你的user model不是使用id當作FK,那你就必須使用第三個參數,來代表你user table的Primary Key了!
public function user()
{
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}
One To Many
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
A Post can have infinite number of comments. use hasMany.
一樣eloquent預設會使用model name 加上 _id,所以會去Post找post_id (預設的情況下)
$comments = App\Post::find(1)->comments;
定義完就可以使用這個方法拉! A collection
$comments = App\Post::find(1)->comments;
foreach ($comments as $comment) {
//
}
使用foreach去尋訪
$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();
you can retrieved comments and use builder to chain methods.
使用builder pattern去chainning.
return $this->hasMany('App\Comment', 'foreign_key');
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
一樣可以去override foreign key(in comment table)和 local key (post table)
Inverse()
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
從comment回抓post
$comment = App\Comment::find(1);
echo $comment->post->title;
$comment->post->attributes or $comment->posts()->attibutes;
一般來說會使用model name+上_id去尋找child table的foreign key
但是在inverse relation 則是使用method name + _id去尋找該Model中的 foreign key
Many To Many
Many to many 通常會使用到三個表,代表有個單純 join 用的table, => intermediate table
範例是Users、Roles、role_user,而role_user上有user_id、role_id
class User extends Model
{
/**
* The roles that belong to the user.
*/
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
inverse relation ,user belongsToMany() Role,User可以扮演多個腳色
$user = App\User::find(1);
foreach ($user->roles as $role) {
//
}
使用$user->roles or $user->roles(); 去作巡迴的查找
同樣的你可以透過builder pattern繼續Channing
$roles = App\User::find(1)->roles()->orderBy('name')->get();
當使用上述方法時,Eloquent是怎麼跑的呢? Eloqunet會透過joinning table將兩個table join起來,並且會照著 alphabetical order
當然你可以串改第二個參數,來指定要使用的join table,如下
return $this->belongsToMany('App\Role', 'role_user');
另外你也可以明確指示在joinning table所使用的key
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
user_id是指當前的Model指向另一個Model的FK,以上述例子代表我們是在Role裡面使用這行, 我們拿 User table內的user_id當foreign key 比對role_user,第四個argument Role table則是使用role_id,
pivot table,樞紐分析表,在多對多的特殊關係下的應用,
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
return $this->belongsToMany('App\Podcast')
->as('subscription')
->withTimestamps();
$users = User::with('podcasts')->get();
foreach ($users->flatMap->podcasts as $podcast) {
echo $podcast->subscription->created_at;
}
當有pivot這個功能時,你可以使用with('podcast'),代表某個使用者訂閱了那些podcasts.
上面pivot不太詳細,請看下面的案例
今天有country、post、user的model,而country是user的一部分,你可以透過關聯找到某個國家的所有posts.
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
Though posts
does not contain a country_id
column, the hasManyThrough
relation provides access to a country's posts via $country->posts
. To perform this query, Eloquent inspects the country_id
on the intermediate users
table. After finding the matching user IDs, they are used to query the posts
table.
這樣就可以直接使用$country->posts 間接存取country的posts.
但是你必須在country model define.
class Country extends Model
{
/**
* Get all of the posts for the country.
*/
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
Country透過User 可以拿到很多Post. First argument is the name of the final model we wish to access
while the second argument is the name of the intermediate model.
未完待續....