PHP的ORM模型关联(tp6)总结

发布于:2024-05-18 ⋅ 阅读:(180) ⋅ 点赞:(0)

一对一关联

表:用户表和资料表

  • 用户表:user。主要字段:id, …
  • 资料:profile。主要字段:id, user_id, …

hasOne (一对一关联)

// 用户模型
class User extends Model
{
    public function profile()
    {
        // hasOne('关联模型类名', '外键', '主键');
        // 关联模型(必须):关联模型类名
        // 外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id ,例如user_id
        // 主键:当前模型主键,默认会自动获取也可以指定传入
        return $this->hasOne(Profile::class, 'user_id', 'id');
    }
}

belongsTo(相对关联)

// 资料模型
class Profile extends Model 
{
    public function user()
    {
        // belongsTo('关联模型','外键', '关联主键');
        // 关联模型(必须):关联模型类名
        // 外键:当前模型外键,默认的外键名规则是关联模型名+_id
        // 关联主键:关联模型主键,一般会自动获取也可以指定传入
        return $this->belongsTo(User::class, 'user_id', 'id');
    }
}

一对多关联

表:文章和评论。

  • 文章表:article。字段:id,…
  • 评论表:comment。字段:id,article_id,…
// 文章模型
class Article extends Model
{
    public function comments()
    {
        // hasMany('关联模型','外键','主键');
        // 关联模型(必须):关联模型类名
        // 外键:关联模型外键,默认的外键名规则是当前模型名+_id
        // 主键:当前模型主键,一般会自动获取也可以指定传入
        return $this->hasMany(Comment::class, 'article_id', 'id');
        
		// 为关联加条件 comment.is_cancelled=0
		// return $this->hasMany(Comment::class, 'article_id', 'id')->where('is_cancelled', Consts::NO);
    }
}

反之,查评论所属的文章,就要使用belongsTo()这个一对一的方法。

远程关联

用远程一对多关联的前提
如果模型 A  想远程一对多关联模型 C,前提是中间模型 B 对应的数据库表必须有模型 A 对应的数据表的外键,模型 C 对应的数据库表必须有模型 B 对应数据库表的外键。(套娃)
参考:[ThinkPHP 远程一对多关联](https://blog.csdn.net/weixin_44161401/article/details/131685949)

表:商品表,订单商品表,订单商品评论表

  • 商品表:goods。字段:id,…
  • 订单商品记录表(中间表):order_goods。字段:id,goods_id,…
  • 订单商品评论表(关联表):order_goods_comment。字段:id,order_goods_id,…

远程一对多

class Goods extends Model
{
    // 远程一对多关联获取商品的所有评论
    public function comments()
    {   
        // hasManyThrough('关联模型', '中间模型', '中间表关联主键', '关联表关联主键','当前模型主键','中间模型主键');
        // 1.关联表模型(必须):关联模型类名
        // 2.中间表模型(必须):中间模型类名
        // 3.中间表关联主键:当前模型在中间模型的外键,默认的外键名规则是当前模型名+_id(OrderGoods.goods_id)
        // 4.关联表关联主键:中间模型在关联模型的外键,默认的外键名规则是中间模型名+_id(OrderGoodsComment.order_goods_id)
        // 5.当前模型主键:当前模型主键,一般会自动获取也可以指定传入(Goods.id)
        // 6.中间模型主键:一般会自动获取也可以指定传入(OrderGoods.id)
        return $this->hasManyThrough(OrderGoodsComment::class, OrderGoods::class, 'goods_id', 'order_goods_id', 'id', 'id');
    }
}

执行的SQL:

SELECT * FROM `goods` WHERE  `id` = 1 LIMIT 1
SELECT * FROM `order_goods` WHERE  `goods_id` = 1
SELECT * FROM `order_goods_comment` WHERE  `order_goods_id` = 1

远程一对一

class Goods extends Model
{
    public function comment()
    {
        // hasOneThrough('关联模型', '中间模型', '中间表关联主键', '关联表关联主键','当前模型主键','中间模型主键');
        // 1.关联表模型(必须):关联模型类名
        // 2.中间表模型(必须):中间模型类名
        // 3.中间表关联主键:当前模型在中间模型的外键,默认的外键名规则是当前模型名+_id(OrderGoods.goods_id)
        // 4.关联表关联主键:中间模型在关联模型的外键,默认的外键名规则是中间模型名+_id(OrderGoodsComment.order_goods_id)
        // 5.当前模型主键:当前模型主键,一般会自动获取也可以指定传入(Goods.id)
        // 6.中间模型主键:一般会自动获取也可以指定传入(OrderGoods.id)
        return $this->hasOneThrough(OrderGoodsComment::class, OrderGoods::class, 'goods_id', 'order_goods_id', 'id', 'id');
    }
}

执行的SQL:

SELECT * FROM `goods` WHERE  `id` = 1 LIMIT 1
SELECT * FROM `order_goods` WHERE  `goods_id` = 1
SELECT * FROM `order_goods_comment` WHERE  `order_goods_id` = 1

多对多关联

表:管理员,角色,管理员角色关联表

  • 管理员表:admin。字段:id, …
  • 角色表:admin_role。字段:id, …
  • 关联表(中间表):admin_role_elation。字段:id, onwer_id(管理员ID=admin_id), role_id

** 中间表要继承 Pivot **

class Admin extends Model
{
    public function roles()
    {
        // belongsToMany('关联模型','中间表','外键','关联键');
        // 关联模型(必须):关联模型类名
        // 中间表:默认规则是当前模型名+_+关联模型名 (可以指定模型名)
        // 外键:中间表的当前模型外键,默认的外键名规则是关联模型名+_id
        // 关联键:中间表的当前模型关联键名,默认规则是当前模型名+_id
        return $this->belongsToMany(AdminRole::class, AdminRoleRelation::class, 'role_id', 'owner_id');

        // 为中间表指定条件
        // return $this->belongsToMany(AdminRole::class, AdminRoleRelation::class, 'role_id', 'owner_id')->wherePivot('relation_type', 1);
    }
}

多态关联

表:文章表,书籍表,评论表。

article(文章表)
    id - integer
    title - string
    content - text

book(书籍表)
    id - integer
    title - string

comment(评论表)
    id - integer
    content - text
    commentable_id - integer
    commentable_type - string

多态一对多关联

class Article extends Model
{
    // 多态关联
    public function comments()
    {
        // morphMany('关联模型','多态字段','多态类型');
        // 关联模型(必须):关联的模型类名
        // 多态字段(可选):支持两种方式定义
        //     - 如果是字符串:表示多态字段的前缀,多态字段使用 “多态前缀_type”和“多态前缀_id”。
        //     - 如果是数组:表示使用['多态类型字段名','多态ID字段名']。
        //     - 默认为当前的关联方法名作为字段前缀。
        // 多态类型(可选):当前模型对应的多态类型(字段的值)。默认为当前模型名,可以使用模型名(如Article)或者完整的命名空间模型名(如app\index\model\Article)。

        // 1.多太字段为字符串:commentable_type(关联类型,值默认为当前模型名:Model\\Article), commentable_id(关联表ID,值为:Article.id)
        // return $this->morphMany(Comment::class, 'commentable');

        // 2.多太字段为数组:commentable_type(关联类型,值默认为当前模型名:Model\\Article), commentable_id(关联表ID,值为:Article.id)
        // return $this->morphMany(Comment::class, array('commentable_type', 'commentable_id'));

        // 3.指定多太类型:明确指定类型值为当前类的命名空间
        return $this->morphMany(Comment::class, 'commentable', self::class);
    }
}

多态一对一关联

表:文章表,书籍表,评论表。
** 使用以上表结构,假设文章和书籍都只能有一条评论。 **

class Article extends Model
{
    public function comment()
    {
        // morphOne('关联模型','多态字段','多态类型');
        // 关联模型(必须):关联的模型类名。
        // 多态字段(可选):支持两种方式定义 
        //     - 如果是字符串表示多态字段的前缀,多态字段使用 多态前缀_type和多态前缀_id。
        //     - 如果是数组,表示使用['多态类型字段名','多态ID字段名']。
        //     - 默认为当前的关联方法名作为字段前缀。
        // 多态类型(可选):当前模型对应的多态类型,默认为当前模型名,可以使用模型名(如Member)或者完整的命名空间模型名(如app\index\model\Member)。
        return $this->morphOne(Comment::class, 'commentable');
    }
}

获取所有者模型

class Comment extends Model
{
    // 获取评论对应的多态模型(返回评论所有者)
    public function commentable()
    {
        // morphTo('多态字段',['多态类型'=>'模型类名', ...]);
        // 多态字段(可选):支持两种方式定义
        //     - 如果是字符串表示多态字段的前缀,多态字段使用 多态前缀_type和多态前缀_id,
        //     - 如果是数组,表示使用['多态类型字段名','多态ID字段名'],
        //     - 默认为当前的关联方法名作为字段前缀
        // 多态类型别名(可选):数组方式定义,类型对应的模型类名(可以相对或绝对)。如果类型值就是模型名,可以不传这个数组。
        return $this->morphTo('commentable', array(
            Article::class => 'Article', // 相对命名空间
            Book::class => 'Model\Book', // 绝对命名空间
        ));
    }
}

$comment = Comment::find(1);
$article = $comment->commentable; // 文章模型

网站公告

今日签到

点亮在社区的每一天
去签到