Laravel - EloquentORM - Relationships

# Introduction

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。



# Defining Relationships

# One To One

在 Laravel relationship 當中, 如何建立一個 one to one relation?
<?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');
}
}

Laravel hasOne relationship 當中, 預設 foreign key 的條件是什麼?

model name

Laravel hasOne relationship 當中, 如果我要自定義 foreign key, 我可以怎麼做?
<?php
return $this->hasOne('App\Phone', 'foreign_key');
Laravel hasOne relationship 當中, 預設 foreign key 的值需要對應 parent table 上的哪一個 column 的值?

id

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
  • Answer:
    自定義要使用哪個 owner table 與 foreign table 上的 key 來做連結, local_key 代表在 owner table, 即 $this, 上的 column name, foreign_key 代表在 ‘App\Phone’ table 上的 column

# Defining The Inverse Of The Relationship

Laravel one to one relationship 中, 如何定義反向的存取?
<?php

namespace 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');
}
}
Laravel one to one relationship 中, 預設定義 belongsTo 的 foreign key 的規則是?

根據 belongsTo method 的名稱, 在 method 名稱後加上 _id

Laravel one to one relationship 中, 如何自訂義 foreign key?
<?php
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User', 'foreign_key');
}
Laravel one to one relationship 當中, 在 belongsTo method 當中, 如果我的 parent table 不是使用 id 作為 primary key, 而我想要自定義, 我可以怎麼做?
<?php
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}

# One To Many

Laravel one to many relationship 中, 如果我要建立一個 one to many 的 relation, 我可以怎麼做?
<?php

namespace 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');
}
}
以下的 relation 中, foreign key 預設是什麼?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Post extends Model
    {
    public function comments()
    {
    return $this->hasMany('App\Comment');
    }
    }
  • Answer:
    post_id, 預設, Laravel 會在擁有者 model 使用 “snake_case”, 並在最後加上 _id
Laravel one to many relationship 中, 如何取得 relation?
<?php
$comments = App\Post::find(1)->comments;

foreach ($comments as $comment) {
//
}
Laravel one to many relationship 中, 如何取得 relation 的 query builder?
<?php
$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    return $this->hasMany('App\Comment', 'foreign_key');

    return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
  • Answer:
    定義 one to many relation 時, 指定 foreign_key 以及 local_key

# One To Many (Inverse)

Laravel one to many relation 中, 如何定義一個反向的 relation?
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
Laravel one to many relationship 中, 如何自訂義 foreign key 以及 primary key?
<?php
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}

# Many To Many

Laravel Relationship 中, 當我要建立一個 many to many 的中間表格, 表格的命名是什麼規格?

alphabetical

Laravel Relationship 中, 當我要建立一個 users, roles 的 many to many 的中間表格, 中間表格必須至少有什麼 column?

user_id, role_id

Laravel Relationship 中, 當我要建立一個 users, roles 的 many to many 的 relationship, 在 User 的 model 中, 我可以怎麼做?
<?php

namespace 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');
}
}
承上面 Laravel 程式碼, 在 Laravel Relationship 中, 如果我已經在 User 跟 Role model 之間建立了 many to many relationship, 當我想要從 user model 取 roles, 我可以怎麼做?
<?php
$user = App\User::find(1);

foreach ($user->roles as $role) {
//
}
承上面 Laravel 程式碼, 在 Laravel Relationship 中, 如果我已經在 User 跟 Role model 之間建立了 many to many relationship, 當我想要取 roles 並 chain query 時, 我可以怎麼做?
<?php
$roles = App\User::find(1)->roles()->orderBy('name')->get();
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    public function roles()
    {
    return $this->belongsToMany('App\Role', 'table_name');
    }
    }
  • Answer:
    定義 User belongsTo Role relation, 並指定 pivot table 為 ‘table_name’
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    public function roles()
    {
    return $this->belongsToMany('App\Role', 'role_user', 'currentModel', 'joiningToModel');
    }
    }
  • Answer:
    定義 pivot table name, pivot table 上代表 current model 的 column 以及 foreign model 上的 column
在 Laravel many to many relationship 中, 如果我想要自定義中間表格中 column 的名稱, 我可以怎麼做?

# Retrieving Intermediate Table Columns

在 Laravel many to many relationship 中, 如果我想要取得中間表格的資料, 我可以怎麼做?
<?php
$user = App\User::find(1);

foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}

會哦

model key

<?php

namespace 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')->withPivot('column1', 'column2');
}
}
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    public function roles()
    {
    return $this->belongsToMany('App\Role')->withTimestamps();
    }
    }
  • Answer:
    使用 withTimestamps method, Model User 與 Model Role 的 many to many relationship 的 pivot table 上的 created_at 以及 updated_at 會被自動維護

# Customizing The pivot Attribute Name

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    public function roles()
    {
    return $this->belongsToMany('App\Podcast')
    ->as('subscription')
    ->withTimestamps();
    }
    }
  • Answer:
    定義 pivot table name 為 subscription, 且自動維護 pivot table 的 created_at 以及 updated_at
呈上, 如何存取這個 subscription 中間表格?
<?php
$users = User::with('podcasts')->get();

foreach ($users->flatMap->podcasts as $podcast) {
echo $podcast->subscription->created_at;
}

# Filtering Relationships Via Intermediate Table Columns

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    return $this->belongsToMany('App\Role')->wherePivot('approved', 1);

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

    return $this->belongsToMany('App\Role')->wherePivotNotIn('priority', [1, 2]);
  • Answer:
    <?php
    // 定義了 $this 與 'App\Role' 的 belongsToMany relationship
    // 除了 primary key 與 foreign key 條件符合之外
    // 還需 wherePivot('approved', 1) 的條件滿足, 才算是此 relationship 的範圍
    return $this->belongsToMany('App\Role')->wherePivot('approved', 1);

    // 還需 wherePivotIn('priority', [1, 2]) 的條件滿足, 才算是此 relationship 的範圍
    return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);

    // 還需 wherePivotNotIn('priority', [1, 2]) 的條件滿足, 才算是此 relationship 的範圍
    return $this->belongsToMany('App\Role')->wherePivotNotIn('priority', [1, 2]);


# Defining Custom Intermediate Table Models

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Role extends Model
    {
    public function users()
    {
    return $this->belongsToMany('App\User')->using('App\RoleUser');
    }
    }
  • Answer:
    在定義 many to many relation 的同時, 指定 pivot Model
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Role extends Model
    {
    public function users()
    {
    return $this->belongsToMany('App\User')
    ->using('App\RoleUser')
    ->withPivot([
    'created_by',
    'updated_by',
    ]);
    }
    }
  • Answer:
    在定義 Role belongsToMany User 的 relation 的同時, 指定 pivot table, 且指定 pivot table 上預設載入 ‘created_by’, 以及 ‘updated_by’ column
Laravel many to many relation 中, pivot model 可以使用 SoftDeletes trait 嗎?

不行哦


# Custom Pivot Models And Incrementing IDs

Laravel many to many relation 中, 為了讓 table 中的 primary key 運作正常, pivot model 中需要加什麼屬性?
<?php
/**
* Indicates if the IDs are auto-incrementing.
*
* @var bool
*/
public $incrementing = true;

# Has One Through

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Supplier extends Model
    {
    public function userHistory()
    {
    return $this->hasOneThrough('App\History', 'App\User');
    }
    }
  • Answer:
    Supplier hasOne User, 而 User hasOne History, 第一個參數為 目標 model, 第二個參數為 中間 model, 定義好後可從 Supplier 直接取得 History model
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    Supplier extends Model
    {
    public function userHistory()
    {
    return $this->hasOneThrough(
    'App\History',
    'App\User',
    'supplier_id', // Foreign key on users table...
    'user_id', // Foreign key on history table...
    'id', // Local key on suppliers table...
    'id' // Local key on users table...
    );
    }
    }
  • Answer:
    使用 hasOneThrough relation, 並定義 local key 以及 foreign key

# Has Many Through

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Country extends Model
    {
    public function posts()
    {
    return $this->hasManyThrough('App\Post', 'App\User');
    }
    }
  • Answer:
    Country hasOne User, 而 User hasOne Post, 第一個參數為 目標 model, 第二個參數為 中間 model, 定義好後可從 Country 直接取得 Post model
在 Laravel one to many through method 中, 如果我要自定義 foreign key 以及 local key, 我可以怎麼做?
<?php
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // Foreign key on users table...
'user_id', // Foreign key on posts table...
'id', // Local key on countries table...
'id' // Local key on users table...
);
}
}


# Polymorphic Relationships

# One To One (Polymorphic)

# Table Structure

在 Laravel 中, 如果說我有一個 image model, 而 user model 跟 post model 都跟 image 有 one to one 的關係, 那我可以使用什麼樣的 relation?

One To One (Polymorphic)

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Post extends Model
    {
    public function image()
    {
    return $this->morphOne('App\Image', 'imageable');
    }
    }
  • Answer:
    每個 Post 都有一個 Image, 而其他的 model 也可能會用到 Image, 因此使用 polymorphic one to one relation
Laravel 中, 假設我的 Post model 有一個 Image model, 而 User model 也有一個 Image model, 現在我要定義 one to one (polymorphic) relation, 若要在 Post model 中定義與 Image model 的關係, 可以怎麼做?
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class User extends Model
    {
    public function image()
    {
    return $this->morphOne('App\Image', 'imageable');
    }
    }
  • Answer:
    User hasOne Image, 而其他 model 也有 hasOne Image relationship, 這樣就可以使用 morph relation, 可以共用一個 images table, Image model 的不同 relation 會在 ‘imageable_type’ 做區分, 例如 ‘App\User’ 或是 ‘App\Post’
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Image extends Model
    {
    public function imageable()
    {
    return $this->morphTo();
    }
    }
  • Answer:
    定義一個 polymorphic one to one 的 relation, Image model 可同時 belongs to 一個以上的 model
以下的 Laravel one to one (Polymorphic) relation table structure 當中, imageable_id 跟 imageable_type 分別代表什麼?
  • Example:
    posts
    id - integer
    name - string

    users
    id - integer
    name - string

    images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string
  • Answer:

imageable_id: user_id 或 post_id
imageable_type: user model name 或 post model name


# Retrieving The Relationship

在 Laravel one to one (Polymorphic) relation 當中, 假設以下為我的 relation 定義, 如果我要從 parent model 拿到 child model, 那我可以怎麼做?
  • Relation 定義:
    <?php
    class Post extends Model
    {
    public function image()
    {
    return $this->morphOne('App\Image', 'imageable');
    }
    }
  • 取得 relation:
    <?php
    $post = App\Post::find(1);

    $image = $post->image;
在 Laravel one to one (Polymorphic) relation 當中, 假設以下為我的 relation 定義, 如果我要從 child model 取得 parent model, 我可以怎麼做?
  • Relation 定義:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Image extends Model
    {
    /**
    * Get the owning imageable model.
    */
    public function imageable()
    {
    return $this->morphTo();
    }
    }
  • 取得 relation
    <?php
    $image = App\Image::find(1);

    $imageable = $image->imageable;

# One To Many (Polymorphic)

# Table Structure

Laravel 當中, 如果說在我的應用中的 user 可以同時在 video 以及 post 中留下 comments, 那我可以使用怎麼樣的 relation?

one to many (Polymorphic)

Laravel one to many (Polymorphic) 當中, 以下的 table structure 中的 commentable_id 以及 commentable_type 代表什麼?
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
  • commentable_id: 代表 foreign key
  • commentable_type: 代表 relation 的 model name

# Model Structure

Laravel 當中, 假設每一個 Video model 以及 Post model 都有多個 Comment model, 現在我要定義一個 one to many (polymorphic) relation, 若要從 Video model 中定義與 Comment model 的 relation, 可以怎麼做?
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
/**
* Get all of the video's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
Laravel 當中, 假設每一個 Video model 以及 Post model 都有多個 Comment model, 現在我要定義一個 one to many (polymorphic) relation, 若要從 Post model 中定義與 Comment model 的 relation, 可以怎麼做?
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
/**
* Get all of the post's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Comment extends Model
    {
    public function commentable()
    {
    return $this->morphTo();
    }
    }
  • Answer:
    Comment model 同時與一個以上的 model 有 belongsTo 的 relation, 所以可以使用 polymorphic relation, 當使用 commentable relation 時, 會經由 commentable_type 以及 commentable_id 取得相對應的 relational model 以及 id

# Retrieving The Relationship

Laravel one to many (Polymorphic) relation 當中, 如果我要從 parent model 取得 child model, 我可以怎麼做? 假設以下為我的 relation 定義
  • Relation 定義:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Comment extends Model
    {
    /**
    * Get the owning commentable model.
    */
    public function commentable()
    {
    return $this->morphTo();
    }
    }

    class Post extends Model
    {
    /**
    * Get all of the post's comments.
    */
    public function comments()
    {
    return $this->morphMany('App\Comment', 'commentable');
    }
    }

    class Video extends Model
    {
    /**
    * Get all of the video's comments.
    */
    public function comments()
    {
    return $this->morphMany('App\Comment', 'commentable');
    }
    }
  • 取得 relation
    <?php
    $post = App\Post::find(1);

    foreach ($post->comments as $comment) {
    //
    }
在 Laravel one to many (Polymorphic) relation 當中, 假設以下為我的 relation 定義, 現在我要從 child model 取得 parent model, 那我可以怎麼做?
  • relation 定義:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Comment extends Model
    {
    /**
    * Get the owning commentable model.
    */
    public function commentable()
    {
    return $this->morphTo();
    }
    }

    class Post extends Model
    {
    /**
    * Get all of the post's comments.
    */
    public function comments()
    {
    return $this->morphMany('App\Comment', 'commentable');
    }
    }

    class Video extends Model
    {
    /**
    * Get all of the video's comments.
    */
    public function comments()
    {
    return $this->morphMany('App\Comment', 'commentable');
    }
    }
  • 取得 relation
    <?php
    $comment = App\Comment::find(1);

    $commentable = $comment->commentable;

# Many To Many (Polymorphic)

# Table Structure

在 Laravel many to many (Polymorphic) relation 當中, 假如說我有 video 跟 post model, 而兩者都跟 tag model 有 many to many 的關係, 那我可以怎樣定義我的 table?
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

# Model Structure

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Post extends Model
    {
    public function tags()
    {
    return $this->morphToMany('App\Tag', 'taggable');
    }
    }
  • Answer:
    定義 Post model 跟 Tag model 之間 polymorphic many to many relation
    試想, 一篇 post 可以有多個 tags, 而我也可以經由一個 tag 取得多個 posts, 這樣就構成 many to many relationship
    同時, 一部 video 可以有多個 tags, 而我也可以經由一個 tag 取得多部 video, 這樣也構成 many to many relationship
    那我需要建立兩個 tags table 以及兩個 pivot table 嗎? 可以使用 polyMorphic many to many relation, 這樣只需要一個 tags table 以及一個 pivot table 就夠了

# Defining The Inverse Of The Relationship

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    class Tag extends Model
    {
    public function posts()
    {
    return $this->morphedByMany('App\Post', 'taggable');
    }

    public function videos()
    {
    return $this->morphedByMany('App\Video', 'taggable');
    }
    }
  • Answer:
    定義 tags 分別與 videos 以及 posts table 之間的 polymorphic many to many relationship
    試想, 一篇 post 可以有多個 tags, 而我也可以經由一個 tag 取得多個 posts, 這樣就構成 many to many relationship
    同時, 一部 video 可以有多個 tags, 而我也可以經由一個 tag 取得多部 video, 這樣也構成 many to many relationship
    那我需要建立兩個 tags table 以及兩個 pivot table 嗎? 可以使用 polyMorphic many to many relation, 這樣只需要一個 tags table 以及一個 pivot table 就夠了
在 Laravel many to many polymorphic relation 當中, 假如我有 Post 跟 Video model, 而兩者都與 Tag model 有 many to many 的 relationship, 現在我要在 Tag 定義 many to many polymorphic relation, 我可以怎麼做?

# Retrieving The Relationship

Laravel many to many polymorphic relationship 當中, 如果我的 relation 定義如下, 現在我要從 Post model 取得 Tag relation, 我該怎麼做?
  • Relation 定義:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Post extends Model
    {
    /**
    * Get all of the tags for the post.
    */
    public function tags()
    {
    return $this->morphToMany('App\Tag', 'taggable');
    }
    }
  • Answer:
    <?php
    $post = App\Post::find(1);

    foreach ($post->tags as $tag) {
    //
    }

Laravel many to many polymorphic relationship 當中, 如果我的 relation 定義如下, 現在我要從 Tag model 取得 Post relation, 我該怎麼做?
  • Relation 定義:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Tag extends Model
    {
    /**
    * Get all of the posts that are assigned this tag.
    */
    public function posts()
    {
    return $this->morphedByMany('App\Post', 'taggable');
    }

    /**
    * Get all of the videos that are assigned this tag.
    */
    public function videos()
    {
    return $this->morphedByMany('App\Video', 'taggable');
    }
    }
  • Answer:
    <?php
    $tag = App\Tag::find(1);

    foreach ($tag->videos as $video) {
    //
    }

# Custom Polymorphic Types

在 Laravel polymorphic relationship 當中, 預設 commentable_type 的內容會是像什麼樣的?

model 的名稱, 像是 App\Post 或是 App\Video

在 Laravel polymorphic relationship 當中, polymorphic 關係的對應預設是依照 polymorphic type column 中的值來對應的, 格式預設是 App/ModelName, 如果我不想要使用這個預設格式, 我想要變更的話, 我可以在什麼地方變更?

AppServiceProviderboot function 內

在 Laravel polymorphic relationship 當中, 如果我要在 AppServiceProvider 當中自定義 polymorphic table 中的 type column 的值, 我可以怎麼做?
<?php
use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
在 Laravel polymorphic relationship 當中, 如果我在 AppServiceProvider 當中自定義 polymorphic table 中的 type column 的值之後, 原本的 App\Post 形式的 model 名稱需要依照自定義的名稱做變更嗎?

需要哦



# Querying Relations

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

    $user->posts()
    ->where(function (Builder $query) {
    return $query->where('active', 1)
    ->orWhere('votes', '>=', 100);
    })
    ->get();

    // select * from posts
    // where user_id = ? and (active = 1 or votes >= 100)
  • Answer:
    使用 where function, 在其 closure 內限制 where constraints 的範圍

# Querying Relationship Existence

在 Laravel relationship 當中, 假如我的 Post model 與 Comment model 關聯, 我只要取得至少有一個 Comment 的 Post, 那我可以怎麼做?
<?php
// Retrieve all posts that have at least one comment...
$posts = App\Post::has('comments')->get();
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $posts = App\Post::has('comments', '>=', 3)->get();
  • Answer:
    取得有 3 個以上 (含 3 個) 的 Post model
在 Laravel relationship 當中, 假如我的 Post model 與 Comment model 關聯, 我只要取得有至少一個以上 Comment 的 Post, 且這個 comment 的 content 要含有 ‘foo’, 那我可以怎麼做?
<?php
// Retrieve posts with at least one comment containing words like foo%...
$posts = App\Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'foo%');
})->get();
在 Laravel relationship 當中, 假如我的 Post model 與 Comment model 關聯, 我只要取得有十個以上 Comment 的 Post, 且 10 個 Comment 的 content 都要含有 ‘foo’, 那我可以怎麼做?
<?php
// Retrieve posts with at least ten comments containing words like foo%...
$posts = App\Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'foo%');
}, '>=', 10)->get();

# Querying Relationship Absence

在 Laravel relationship 當中, 假如我的 Post model 與 Comment model 關聯, 我要取得沒有任何 comments 的 post, 那我可以怎麼做?
<?php
$posts = App\Post::doesntHave('comments')->get();
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

    $posts = App\Post::whereDoesntHave('comments', function (Builder $query) {
    $query->where('content', 'like', 'foo%');
    })->get();
  • Answer:
    取得 Post models, 其 comment relation model 的 content 不包含 ‘foo%’
在 Laravel relationship 中, 假設我有 post, comment, 以及 author Model, 現在我要取得 comment 的 author 未被 banned 的 post (以 post 的 comment 的 author 為條件 query), 那我可以怎麼做?
<?php
use Illuminate\Database\Eloquent\Builder;

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

# Querying Polymorphic Relationships

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

    // Retrieve comments associated to posts or videos with a title like foo%...
    $comments = App\Comment::whereHasMorph(
    'commentable',
    ['App\Post', 'App\Video'],
    function (Builder $query) {
    $query->where('title', 'like', 'foo%');
    }
    )->get();
  • Answer:
    取得 polymorphic many to many relation 的 Post, Video relation, 並從中篩選 title 含有 ‘foo%’ 的 model
在 Laravel polymorphic relationship 當中, 假如 Post 與 Video Model 都有多個 Comment Model, 現在我要取得 comment, 所屬的 video 或 post 的 title 含有 foo%, 那我可以怎麼做?
Laravel 中, 如果今天我的 Comment model 與 video 以及 post 有 polymorphic 的 relation, 那我想要取得 comment, 且該 comment 所屬的 post 的 title 不可含有 foo, 那我可以怎麼做?
<?php
// Retrieve comments associated to posts with a title not like foo%...
$comments = App\Comment::whereDoesntHaveMorph(
'commentable',
'App\Post',
function (Builder $query) {
$query->where('title', 'like', 'foo%');
}
)->get();
Laravel 中, 假如 Post model, Video model 與 Comment model 有 polymorphic 的關係, 現在我想要取得某些 Comment, 條件是 Video 的 title 必須含有 foo, 而 Post 的 title 或 content 必須含有 foo, 那我可以怎麼做?
<?php
use Illuminate\Database\Eloquent\Builder;

$comments = App\Comment::whereHasMorph(
'commentable',
['App\Post', 'App\Video'],
function (Builder $query, $type) {
$query->where('title', 'like', 'foo%');

if ($type === 'App\Post') {
$query->orWhere('content', 'like', 'foo%');
}
}
)->get();
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

    $comments = App\Comment::whereHasMorph('commentable', '*', function (Builder $query) {
    $query->where('title', 'like', 'foo%');
    })->get();
  • Answer:
    一次性取得所有的 morph model, 不管我有幾個, 並且從這些 relation 當中搜尋任何 title 含有 foo 的 comment

# Counting Relate Models

Laravel relationship 中, 假設今天我的 Post model 有很多 Comment model, 我想要拿到每個 Post model 下有幾個 Comment model, 那我可以怎麼做?
<?php
$posts = App\Post::withCount('comments')->get();

foreach ($posts as $post) {
echo $post->comments_count;
}
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

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

    echo $posts[0]->votes_count;
    echo $posts[0]->comments_count;
  • Answer:
    取出 Post model 的 relation model ‘Votes’, 以及 ‘Comments’ 的數量, 並且, 針對 Comments model 有特別篩選, 條件為 where(‘content, ‘like’, ‘foo%’)
    載入後, 可在每一個 Post model 使用 ‘votes_count’ 以及 ‘comments_count’
Laravel relationship 中, 當我使用了 withCount method, Laravel 會在取得的 model 中加入哪一個欄位?

{relation}_count

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Builder;

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

    echo $posts[0]->comments_count;

    echo $posts[0]->pending_comments_count;
  • Answer:
    取得兩種 Post model 的 relation Comment model count, 一個有加特定 constraints, 並 alias 為 pending_comments_count
Laravel relationship 中, 假設今天我的 Post model 有 comments 的 relationships, 假如現在我要取得每個 Post 有幾個 comment, 以及我要自定義一個 comment 叫做 pending_comments_count, 條件是該 comment 的 approved 必須是 false, 那我可以怎麼做?
Laravel Query Builder 當中, 如果我要同時使用 select 以及 withCount, 哪一種需排在前面?

select

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $posts = App\Post::select(['title', 'body'])->withCount('comments')->get();

    echo $posts[0]->title;
    echo $posts[0]->body;
    echo $posts[0]->comments_count;
  • Answer:
    使用 select() 取得 title, body column
    使用 withCount() 取得 comments relation 的數量
Laravel 當中, 如果我的 Book model 有很多 genres model relation, 現在我已取得特定的那一個 Book model, 我要再取得所屬的 genres 的數量, 那我可以怎麼做?
<?php
$book = App\Book::first();

$book->loadCount('genres');
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $book->loadCount(['reviews' => function ($query) {
    $query->where('rating', 5);
    }])
  • Answer:
    取得 $book 的 Reviews relation model 的數量, 並針對 Reviews model 使用 where('rating', 5) 做篩選


# Eager Loading

以下的 Laravel 程式碼中, author 為 book model 的 relation, 假設 $books 有 25 個 book model, 那以下的程式碼共會 query 幾次?
  • 程式碼:
    <?php
    $books = App\Book::all();

    foreach ($books as $book) {
    echo $book->author->name;
    }
  • answer:
    26 次, 取所有的 book model 共花一次, 取各個 model 的 author relation 再花 25 次
Laravel 中, 假設以下為我的原始程式碼, 我要如何使用 eager loading 將所有的 author relation 一次取出?
  • 原始程式碼
    <?php
    $books = App\Book::all();

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

    foreach ($books as $book) {
    echo $book->author->name;
    }
以下的 Laravel 程式碼中, 實際上下的 MySQL query 是哪兩句?
  • 程式碼
    <?php
    $books = App\Book::with('author')->get();

    foreach ($books as $book) {
    echo $book->author->name;
    }
  • query 語法:
    select * from books
    select * from authors where id in (1, 2, 3, 4, 5, ...)

# Eager Loading Multiple Relationships

在以下的 Laravel 程式碼中, 我如果想要一次性的 eager load relations authorpublisher, 我可以怎麼做?
  • 程式碼
    <?php
    $books = App\Book::all();
    foreach ($books as $book) {
    echo $book->author->name;
    }
  • Answer:
    <?php
    $books = App\Book::with(['author', 'publisher'])->get();

# Nested Eager Loading

以下的 Laravel example code 的意思是?
  • Example
    <?php
    $books = App\Book::with('author.contacts')->get();
  • Answer:
    eager load Book model 的 relation author, 以及 author 的 relation contacts

# Nested Eager Loading morphTo Relationships

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    use Illuminate\Database\Eloquent\Relations\MorphTo;

    $activities = ActivityFeed::query()
    ->with(['parentable' => function (MorphTo $morphTo) {
    $morphTo->morphWith([
    Event::class => ['calendar'],
    Photo::class => ['tags'],
    Post::class => ['author'],
    ]);
    }])->get();
  • Answer:

ActivityFood morphTo Event
ActivityFood morphTo Photo
ActivityFood morphTo Post
Event has relation with calendar
Photo has relation with tags
Post has relation with author
一次性的從 ActivityFeed eager loading 上面的六個 relationships


# Eager Loading Specific Columns

在以下的 Laravel 程式碼中, 如果我只想要 eager load author relation 中的 id 以及 name columns, 我可以怎麼做?
  • 程式碼:
    <?php
    $books = App\Book::all();

    foreach ($books as $book) {
    echo $book->author->name;
    }
  • Answer:
    <?php
    $books = App\Book::with('author:id,name')->get();
在 Laravel 當中, 如果說我今天使用 eager loading 來取得部份的 column, 有哪一個 column 是必須的?

id


# Eager Loading By Default

在以下的 Laravel relation definition 當中, 如果說我想要預設 eager load author 這一個 relation, 那我可以怎麼做?
  • Relation definition:
    <?php

    namespace 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');
    }
    }
  • Answer:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Book extends Model
    {
    /**
    * The relationships that should always be loaded.
    *
    * @var array
    */
    protected $with = ['author'];

    /**
    * Get the author that wrote the book.
    */
    public function author()
    {
    return $this->belongsTo('App\Author');
    }
    }
在以下的 Laravel relation definition 當中, 如果說我想要從某次的 query 當中移除 $with 所賦予的 default eager loading 效果, 那我可以怎麼做?
  • Relation definition:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Book extends Model
    {
    protected $with = ['author'];

    public function author()
    {
    return $this->belongsTo('App\Author');
    }
    }
  • Answer:
    <?php
    $books = App\Book::without('author')->get();

# Constraining Eager Loads

在以下的 Laravel eager loading 範例程式碼中, 如果我想要指定 eager load title 含有 firstposts model, 那我可以怎麼做?
  • 範例程式碼:
    <?php
    $users = App\User::with('posts')->get();
  • Answer:
    <?php
    $users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');
    }])->get();
在以下的 Laravel 範例程式碼中, 我可以加入額外的 query builder method 嗎?
  • 範例程式碼:
    <?php
    $users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');
    }])->get();
  • Answer:
    可以
Laravel eager loading constrain 當中, 像是以下的 Laravel 範例程式碼, 有哪些 query builder method 不適用?
  • 範例:
    <?php
    $users = App\User::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc');
    }])->get();
  • Answer:
    limittake

# Lazy Eager Loading

假如我的 Book model 有 author 以及 publisher 的 relation, 但我想要在特定的條件下才 eager load relation 如以下的範例程式碼, 那我可以怎麼做?
  • 範例程式碼:
    <?php
    $books = App\Book::all();

    if ($someCondition) {
    // eager load here
    }
  • Answer:
    <?php
    $books = App\Book::all();

    if ($someCondition) {
    $books->load('author', 'publisher');
    }
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $author->load(['books' => function ($query) {
    $query->orderBy('published_date', 'asc');
    }]);
  • Answer:
    eager load author 的 books relation model, 並且針對 books model 做 orderBy 排序
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    public function format(Book $book)
    {
    $book->loadMissing('author');

    return [
    'name' => $book->name,
    'author' => $book->author->name,
    ];
    }
  • Answer:
    假設我們在一開頭就取出了 User model 的 Author relation model ‘$user = User::with(‘author)’
    然而, $user 後面又新增了 Author relation model ‘$user->authors()->attach($newAuthor)’
    這時 $user 上原本載入的 Author model 就沒有這個新的 $newAuthor, 這時就可以使用 loadMissing()

# Nested Lazy Eager Loading & morphTo

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $activities = ActivityFeed::with('parentable')
    ->get()
    ->loadMorph('parentable', [
    Event::class => ['calendar'],
    Photo::class => ['tags'],
    Post::class => ['author'],
    ]);
  • Answer:
    先透過 with() eager load parentable relation, 在使用 loadMorph eager load 所有 parentable model 各自對應的 relations
Laravel 中, 假設我有一個 ActivityFeed Model, 它跟 Event, Photo, Post Model 有 morphTo 的關係, 如下面範例。 而 Event 又與 Calendar 有關, PhotoTag 有關, 而 PostAuthor 有關。 現在我要先 eager load ActivityFeed 的 morphTo 關係, 再使用 lazy eager loading 取得以上 morphTo 各自的 relationship, 我可以怎麼做?
  • 範例 relation:
    <?php

    use Illuminate\Database\Eloquent\Model;

    class ActivityFeed extends Model
    {
    /**
    * Get the parent of the activity feed record.
    */
    public function parentable()
    {
    return $this->morphTo();
    }
    }
  • Answer:


# The save method

以下的 Laravel example code 的意思是?
  • 範例程式碼:
    <?php
    $comment = new App\Comment(['message' => 'A new comment.']);
    $post = App\Post::find(1);
    $post->comments()->save($comment);
  • Answer:
    使用帶入 model 的方式來新增 relation
在 Laravel 當中, 在以下的範例程式碼當中, 我要如何一次儲存複數的 model?
  • 範例程式碼:
    <?php
    $comment = new App\Comment(['message' => 'A new comment.']);

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

    $post->comments()->save($comment);
  • Answer:
    <?php
    $post = App\Post::find(1);

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

# Recursively Saving Models & Relationships

以下的 Laravel 程式碼代表什麼意思?
  • 程式碼:
    <?php
    $post = App\Post::find(1);

    $post->comments[0]->message = 'Message';
    $post->comments[0]->author->name = 'Author Name';

    $post->push();
  • Answer:
    指定 post 的 comment relation 的第一個 model 的 message 為 ‘Message’
    指定 post 的 comment relation 的第一個 model 的 author relation 的 name 為 ‘Author Name’
Laravel 當中, 如果我的 relation 是 Post->hasMany->comment, 現在我要變更第一個 comment 的 message 欄位為 ‘Message’, 以及 comment 的 author relation 的 name 欄位為 ‘Author Name’, 我可以怎麼做?
<?php
$post = App\Post::find(1);

$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';

$post->push();

# The create Method

Laravel relationship 當中, save 跟 create method 的差別在於?
  • save 接受的參數為 model
  • create 接受的參數為 array
以下的 Laravel 程式碼代表什麼意思?
  • 程式碼:
    <?php
    $post = App\Post::find(1);

    $comment = $post->comments()->create([
    'message' => 'A new comment.',
    ]);
  • Answer:
    使用 array 內的資料來建立一筆 Post 與 Comment 的關係
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $post = App\Post::find(1);

    $comment = $post->comments()->create([
    'message' => 'A new comment.',
    ]);
  • Answer:
    使用 create(), 帶入 array 來建立 Post hasMany Comment relation
以下的 Laravel 程式碼中, 該怎麼儲存 post 與 comment 的 relation?
  • 程式碼:
    <?php
    $post = App\Post::find(1);
    $comment = ['message' => 'A new comment.'];
  • Answer:
    <?php
    $post = App\Post::find(1);
    $comment = ['message' => 'A new comment.'];
    $comment = $post->comments()->create($comment);
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $post = App\Post::find(1);
    $post->comments()->createMany([$comment1, $comment2]);
  • Answer:
    使用 createMany(), 帶入多個 array 來建立多個 Comments model 並儲存於資料庫, Post model hasMany Comment model
如果我要使用多個 array 來建立 relation, 我可以使用哪一個 method?

createMany


# Belongs To Relationships

以下的 Laravel 程式碼是什麼意思?
  • 程式碼:
    <?php
    $account = App\Account::find(10);

    $user->account()->associate($account);

    $user->save();
  • Answer:
    取得目標 account
    在該 user 的 account relation 中新增上面取得的 account model
以下的 Laravel 程式碼是什麼意思?
  • 程式碼:
    <?php
    $manager = auth()->user();
    $sub_account->manager()->dissociate();
    $sub_account->save();
  • Answer:
    sub_account belongs to manager
    將 sub_account 的 foreign key 設為 null
以下的 Laravel 程式碼是什麼意思?
  • 程式碼:
    <?php
    $manager = auth()->user();
    $sub_account->manager()->associate($manager);
    $sub_account->save();
  • Answer:
    sub_account belongs to manager
    將 sub_account 的 foreign key 設為 $manager
以下的 Laravel 程式碼中, $manager 可以是什麼?
  • 程式碼:
    <?php
    $manager = auth()->user();
    $sub_account->manager()->associate($manager);
    $sub_account->save();
  • Answer:
    Eloquent Model
    也可以是任意字元, 會儲存在 foreign key
Laravel relation 當中, 如果我要更新 belongs to 的 relation, subAccount belongs to Manager, 如下面的程式碼中, 我已取得 manager 的 model, 除了直接使用 update method 去更新該 table 之外, 我可以使用哪個 method?
  • 程式碼:
    <?php
    $manager = App\Manager::find(10);
  • Answer:
    <?php
    $manager = App\Manager::find(10);
    $sub_account->manager()->associate($manager);
    $sub_account->save();
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $sub_account->manager()->dissociate();
    $sub_account->save();
  • Answer:
    從 $sub_account 的 belongsTo relation manager model 中, 移除 foreign key, 即移除彼此的 relation

# Default Models

Laravel 當中, 哪些種類的 relation 可以定義 default model?

belongsTo
hasOne
hasOneThrough
morphOne

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    public function user()
    {
    return $this->belongsTo('App\User')->withDefault([
    'name' => 'Guest Author',
    ]);
    }

    // or

    public function user()
    {
    return $this->belongsTo('App\User')->withDefault(function ($user, $post) {
    $user->name = 'Guest Author';
    });
    }
  • Answer:
    給該 relation 定義 default model, 當 Post 沒有 relational user 時, 回傳 default relational model
以下的 Laravel relation definition, 如果該 relation 不存在, 會回傳什麼?
  • 範例 relation definition:
    <?php
    /**
    * Get the author of the post.
    */
    public function user()
    {
    return $this->belongsTo('App\User')->withDefault([
    'name' => 'Guest Author',
    ]);
    }
  • Answer:
    {
    "name": "Guest Author"
    }

# Many To Many Relationships

# Attaching / Detaching

Laravel many to many relation 中, 如果我要單純新增一筆 relation 紀錄, 我可以怎麼做?
<?php
$user = App\User::find(1);

$user->roles()->attach($roleId);
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user->roles()->attach($roleId, ['expires' => $expires]);
  • Answer:
    為 $user model 新增指定的一筆 $roldId many to many relation, 並且額外指定要新增到 pivot table 中的 column/value
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user->roles()->detach($roleId);
  • Answer:
    在 many to many relation 中, 移除該 User model 指定的一筆 Role relation model
Laravel many to many relation 中, 如果我要單純的移除多筆筆 relation 紀錄, 我可以怎麼做?
<?php
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user->roles()->detach();
  • Answer:
    移除 $user 的 many to many relation Role 所有的 records, 相當於移除 pivot table 中所有 $user 的 role relation model
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user = App\User::find(1);
    $user->roles()->attach([
    1 => ['expires' => $expires],
    2 => ['expires' => $expires],
    ]);
  • Answer:
    新增多筆 relation records, 並 insert $expires to expires column
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user->roles()->sync([1, 2, 3]);
  • Answer:
    在 many to many relation 中, 可使用 sync method, 資料庫會同步帶入的 parameters, 在此 example 中, 資料庫內如果沒有 1, 2, 3 則會新增, 並刪除除了 1, 2, 3 之外的資料
Laravel many to many relation 中, 帶入一筆或多筆 relation 紀錄, 資料庫內需與帶入的資料完全符合, 沒有的新增, 多的刪除, 我還要再額外的欄位新增資訊, 那我可以怎麼做?
<?php
$user->roles()->sync([1 => ['expires' => true], 2, 3]);
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user->roles()->syncWithoutDetaching([1, 2, 3]);
  • Answer:
    如果資料庫並不存在 array 內的資料, 則新增
    如果資料庫已存在 array 內的資料, 則保留

# Toggling Associations

Laravel many to many relation 中, 如果我要帶入一組 relation 紀錄, 資料庫裡頭, 若沒有則則新增, 若有的話則移除, 那我可以怎麼做?
<?php
$user->roles()->toggle([1, 2, 3]);

# Saving Additional Data On A Pivot Table

Laravel many to many relation 中, 如果我要新增一筆 relation 紀錄, 同時如果此 relation 的對象不存在的話則建立, 再建立 relation 紀錄, 那我可以怎麼做?
<?php
App\User::find(1)->roles()->save($role, ['expires' => $expires]);

# Updating A Record On A Pivot Table

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $user = App\User::find(1);
    $user->roles()->updateExistingPivot($roleId, $attributes);
  • Answer:
    更新 many to many relation 的 pivot table, $attribute 為帶有 column/value 的 array


# Touching Parent Timestamps

以下的 Laravel example code 的意思是?
  • Example:
    <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class Comment extends Model
    {
    protected $touches = ['post'];

    public function post()
    {
    return $this->belongsTo('App\Post');
    }
    }
  • Answer:
    使用 $touches property, 這樣當我更新 pivot table 時, 也會一併的更新 Post model 中的 timestamp

# Additional

解釋以下的 Laravel example
  • Example:
    <?php
    public function scopeOf(Builder $query, ...$models)
    {
    foreach ($models as $model) {
    /** @var $model Model */
    $query->where($model->getForeignKey(), $model->getKey());
    }
    }
  • Answer:
    <?php
    // 可帶入多個 model
    public function scopeOf(Builder $query, ...$models)
    {
    // loop 每個 model
    foreach ($models as $model) {
    /** @var $model Model */
    // 取得該 model 的 `foreign key name`, 以及 `primary key value`
    // 所以可以在目標 model 使用其他 model 為條件來 query
    $query->where($model->getForeignKey(), $model->getKey());
    }
    }
一下子敏感, 一下子不敏感, Git 你搞得我好亂啊 使用 Spinnaker 在 Kubernetes Engine 中實作持續交付管道

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×