【再读lara】Eloquent: Relationship 关联

一对一

用户和文章

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  public function post()
  {
    return $this->hasOne('App\Phone');
  }
}

在当前场景下,Eloquent 会假设 Phone 模型有一个外间 user_id
$phone = User::find(1)->post;


反向关联
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  public function user()
  {
    return $this->belongsTo('App\User');
  }
}

空对象模型, user 关联如果没有找到文章的作者,就会返回一个空的 App\User 模型。
可以理解返回一个默认值,还没有具体实践过
class Post extends Model
{

  // 数组形式
  public function user()
  {
    return $this->belongsTo('App\User')->withDefault([
      'name' => '游客'
    ]);
  }

    // 闭包形式
    public function user() 
    {
      return $this->belongsTo('App\User')->withDefault(function($user) {
        $user->name = '游客';
      });
    }
}

一对多

文章和评论

文章
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  public function comments()
  {
    return $this->hasMany('App\Comment');
  }
}


评论
namespace App

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
  public function post()
  {
    return $this->belongsTo('App\Post');
  }
}

多对多

用户和角色
一个用户可以拥有多个角色,一个角色下面可以有多个用户
users, roles, role_user 三张表
role_user 表是以相关联的两个模型数据表、依照字母顺序排列命名的,并且包含 user_id 和 role_id 字段。

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  public function roles()
  {
    return $this->belongsToMany('App\Role');
  }
}


namespace App;

use Illuminate\Databese\Eloquent\Model

class Role extends Model
{
  public function users()
  {
    return $this->belongsToMany('App\User');
  }
}


自定义中间表的场景
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
  public function users()
  {
    return $this->belongsToMany('App\User')->using('App\RoleUser');
  }
}

namespace App;
use Illuminate\Database\Relationships\Pivot;
class RoleUser extends Pivot
{
   
}

远层一对多

一个 Country 模型可以通过中间的 User 模型获得多个 Post 模型

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string


hasManyThrough 方法的第一个参数是我们最终希望访问的模型名称,而第二个参数是中间模型的名称。
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
  // 默认
  public function posts()
  {
    return $this->hasManyThrough('App\Post', 'App\User');
  }

  // 自定义
  第三个参数表示中间模型的外键名,第四个参数表示最终模型的外键名。
  第五个参数表示本地键名,而第六个参数表示中间模型的本地键名:
  public function posts()
  {
    return $this->hasManyThrough(
      'App\Post', 
      'App\User',
      'country_id',    // 用户表外键
      'user_id',         // 文章表外键
      'id',                  // 国家表
      'id'                   //
    );
  }
}

多态关联

用户可以「评论」文章和视频

commentable_id 用来保存文章或者视频的 ID 值
commentable_type 用来保存所属模型的类名 (post, video)
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


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');
  }
}


$commentable = App\Comment::find(1)->commtable();
返回 commentable 的 Post 或 Video 实例

多对多多态关联

Post 和 Video 两个模型都有一个 tags 方法,方法内部都调用了 Eloquent 类自身的 morphToMany 方法

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


namespace App;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  public function tags()
  {
    return $this->morphToMany('App\Tag', 'taggable');
  }
}


反向关联
class Tag extends Model
{
  public function posts()
  {
    return $this->morphedByMany('App\Post', 'taggable');
  }

  public function videos() 
  {
    return $this->morphedByMany('App\Video', 'taggable');
  }
}

$tags = Post::find(1)->tags;

或者
$tag = Tag::find(1);
$videos = $tag->videos;

Dynamic properties allow you to access relationship methods as if they were properties defined on the model
模型中定义的关联,叫做 dynamic property(动态属性)

你可能感兴趣的:(【再读lara】Eloquent: Relationship 关联)