laravel之Eloquent关联

定义

  • 模型 用对象表示的表实例,负责与数据库的交互逻辑构建
  • 关联模型 要连接到的最终模型
  • 关联方法 返回一个关联关系的方法
  • 关联属性 $with属性 由关联方法名组成的数组,通常用于渴求式加载
  • 连接表 又称中间表,通常用于多对多关系
  • 主键 模型的唯一标识符
  • 外键 模型对外的通路
  • 正向 模型主键匹配关联模型外键
  • 反向 模型外键匹配关键模型主键
  • 父级模型 拥有下属分支的模型,典型的一对多关系,一则为父级模型
  • 子级模型 作为某一模型的后继模型,该模型对象对前驱模型有依赖
  • 默认模型

关联关系

  • 一对一 (正向 A->B)
    hasOne('App\Phone','foreign_key','local_key')
    hasOne 方法的第一个参数 是最终想到达的关联模型的类名,
    Eloquent 会基于当前模型名+_id决定关联模型外键名称
    第三个参数,为当前模型的非id以外的自定义关联外键名

  • 一对一(反向 B->A)
    belongsTo('App\User', 'foreign_key', 'other_key')
    第一个参数 要访问的模型类名,俗称关联模型
    第二个参数,默认关联方法名+_id为模型的外键名
    第三个参数,指定父级数据表自定义键 父级模型没有使用id为主键,或者希望使用不同的字段来连接子模型

  • 默认模型
    *空对象模式,传递数组或闭包给withDefault方法

        belongsTo('App\User')->withDefault();  
        belongsTo('App\User')->withDefault(['name' => '游客',]);  
        belongsTo('App\User')->withDefault(function($user){$user->name = '游客'});
    
  • 一对多(正向)
    Eloquent 使用父级模型名的「snake case」形式、加上 _id 后缀名作为外键字段
    所有的关联还可以作为查询语句构造器使用, 可通过传递额外参数来覆盖默认使用的外键与本地键。
    hasMany(‘App\Comment’)
    hasMany(‘App\Comment’, ‘foreign_key’)
    hasMany(‘App\Comment’, ‘foreign_key’, ‘local_key’)

    反向关联
    获得一篇文章的所有评论,接着再定义一个通过评论获得所属文章的关联
    hasMany 关联的反向关联,在子级模型中使用 belongsTo 方法定义

    //comment.php
    
    //Get the post that owns the comment.
    public function post()
    {
    return $this->belongsTo('App\Post');
    }

    示例: 父级模型,子级模型,外键,主键
    上述默认,子级模型comment的外键是post+_id (关联名+_id),父级模型post使用id作为主键

  • 多对多(连接表)
    users roles role_user
    belongsToMany('App\Role', 'role_user', 'user_id', 'role_id')
    第一个参数 目标关联模型类名
    第二个参数连接表名 由关联的两个模型名按照字母顺序确定
    第三个参数 定义此关联的模型在连接表里的外键名
    第四个参数 另一个模型在连接表里的外键名

    定义反向关联
    定义多对多关联的反向关联,在对方模型里再次调用 belongsToMany 方法即可。

    获取中间表字段
    每个 Role 模型对象,代表中间表的一个模型对象
    默认情况下,pivot 对象只包含两个关联模型的键。

        belongsToMany('App\Role')->withPivot('column1', 'column2')
        belongsToMany('App\Role')->withTimestamps()
        belongsToMany('App\Podcast')->as('subscription') ->withTimestamps() //自定义 pivot 属性名称  

关联操作

  • 一对多 belongsTo关联
    注意需要使用save方法持久化存储
    associate 方法在子模型中设置外键
    dissociate 方法 当移除 belongsTo 关联时, 将关联外键设置为 null:

        $account = App\Account::find(10);
        $user->account()->associate($account);
        $user->save();
    
        $user->account()->dissociate();
        $user->save();
    
  • 多对多关联 belongsToMany 中间表
    允许传递一个ID数组
    attach 向中间表插入一条记录
    detach 移除多对多关联记录

        $user = App\User::find(1);
        $user->roles()->attach($roleId);
    
        // 添加附加数据
        $user->roles()->attach($roleId, ['expires' => $expires]);
    
        // 移除用户的一个角色...
        $user->roles()->detach($roleId);
        // 移除用户的所有角色...
        $user->roles()->detach();
    
        $user = App\User::find(1);
        $user->roles()->detach([1, 2, 3]);
    
        $user->roles()->attach([
            1 => ['expires' => $expires],
            2 => ['expires' => $expires]
        ]);

    同步关联
    sync 所有未在 ID 数组中的记录都将会被移除

        $user->roles()->sync([1, 2, 3]);  
        //传递额外数据  
        $user->roles()->sync([1 => ['expires' => true], 2, 3]);  
        //不移除现有的 ID  
        $user->roles()->syncWithoutDetaching([1, 2, 3]);

    切换关联
    toggle 方法用于「切换」给定 ID 数组的附加状态。

        $user->roles()->toggle([1, 2, 3]);

    在中间表上保存额外的数据
    当处理多对多关联时,save 方法接收一个额外的数据数组作为第二个参数

        `App\User::find(1)->roles()->save($role, ['expires' => $expires]);`  

    更新中间表记录
    updateExistingPivot此方法接收中间表的外键与要更新的数据数组进行更新

        $user = App\User::find(1);
        $user->roles()->updateExistingPivot($roleId, $attributes);
  • 更新父级时间戳
    在子模型加一个包含关联名称的 touches
    当一个模型属 belongsTo 或者 belongsToMany 另一个模型时

        namespace App;
    
        use Illuminate\Database\Eloquent\Model;
    
        class Comment extends Model
        {
            /**
            * 要触发的所有关联关系。
            *
            * @var array
            */
            protected $touches = ['post'];
    
            /**
            * 评论所属文章。
            */
            public function post()
            {
                return $this->belongsTo('App\Post');
            }
        }

    使用场景
    更新子模型导致更新父模型时间戳,在子模型加一个包含关联名称的 touches 属性即可。
    当 Comment 模型被更新时,您要自动「触发」父级 Post 模型的 updated_at 时间戳的更新。

  • 特例
    通常多对多形式 A->B->C
    但也有 A->B->A 粉丝与粉主
    更有 A<->A 多态‘中间表’维护在单张表内

猜你喜欢

转载自blog.csdn.net/u011584949/article/details/80800926
今日推荐