ThinkPHP 远程一对多关联

16 篇文章 1 订阅
13 篇文章 0 订阅

用远程一对多关联的前提

如果模型 A  想远程一对多关联模型 C,前提是中间模型 B 对应的数据库表必须有模型 A 对应的数据表的外键,模型 C 对应的数据库表必须有模型 B 对应数据库表的外键。(套娃)

举例,商品获取商品评论

数据表结构如下

// 商品表
goods
    goods_id - integer // 商品主键
    goods_name - varchar // 商品名称



// 订单商品记录表
order_goods
    order_goods_id - integer  // 订单商品主键
    goods_id - integer // 商品主键
    goods_name varchar // 商品名称



// 订单商品评论表
order_goods_comment
    order_goods_comment_id - integer // 订单商品评论表
    order_goods_id - integer // 订单商品主键
    comment - varchar // 订单商品评论 

订单商品评论表有订单商品记录表的主键,订单商品记录表有商品表的主键,这样,商品就可以远程一对多获取商品的评论。(有点像我们所说的套娃)

远程一对多关联定义

商品表 goods 模型:

<?php

namespace app\api\model;

class Goods extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'goods_id';

    protected $hidden = ['create_time', 'update_time'];


    // 获取商品详情以及商品的评论
    // 第二个参数是所用到的关联方法的方法名
    public static function getDetail($goods_id)
    {
        return self::get($goods_id, 'comments');
    }


    // 远程一对多关联获取商品的所有评论
    public function comments()
    {   
        return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods');
        // 完整写法
        // return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods', 'goods_id', 'order_goods_id', 'goods_id');
    }
}

hasManyThrough 方法的参数如下:

hasManyThrough('关联模型', '中间模型',  '外键1',  '外键2',  '主键');

  • 关联模型(必须):模型名或者模型类名
  • 中间模型(必须):模型名或者模型类名
  • 外键1:当前模型在中间模型的外键,默认的外键名规则是当前模型名+_id
  • 外键2:中间模型在关联模型的外键,默认的外键名规则是中间模型名+_id
  • 主键:当前模型主键,一般会自动获取也可以指定传入

订单商品表(中间表) order_goods 模型

<?php
namespace app\api\model;

class OrderGoods extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_id';
}

订单商品评论表  order_goods_comment 模型

<?php

namespace app\api\model;

class OrderGoodsComment extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_comment_id';
}

实例演示

shop_goods 表

 

shop_order_goods 表

 

shop_order_goods_comment 表

 

演示1

获取 goods_id 为 10001 的商品详情以及它的评论

商品 Goods 控制器

<?php

namespace app\api\controller;

use app\api\model\Goods as GoodsModel;

class Goods extends Base
{
    // 获取 goods_id = 10001 的商品详情以及商品评论
    public function detail()
    {
        $goods_id = 10001;

        $detail = GoodsModel::getDetail($goods_id);
        
        echo '<pre>';

        var_dump($detail);

        echo '</pre>';

    }
}

商品表 goods 模型

<?php

namespace app\api\model;

class Goods extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'goods_id';

    protected $hidden = ['create_time', 'update_time'];


    public static function getDetail($goods_id)
    {
        // 获取商品详情以及商品评论
        // 第二个参数是所用到的关联方法的方法名
        return self::get($goods_id, 'comments');
    }


    // 远程一对多获取商品的所有评论
    public function comments()
    {   
        return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods');
        // 完整写法
        // return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods', 'goods_id', 'order_goods_id', 'goods_id');
    }
}

订单商品表(中间表) order_goods 模型

<?php
namespace app\api\model;

class OrderGoods extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_id';
}

订单商品评论表  order_goods_comment 模型

<?php

namespace app\api\model;

class OrderGoodsComment extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_comment_id';
}

Goods 控制器  detail 方法输出

object(app\api\model\Goods)#41 (2) {
  ["data"]=>
  array(8) {
    ["goods_id"]=>
    int(10001)
    ["goods_name"]=>
    string(12) "桂味荔枝"
    ["stock_total"]=>
    int(0)
    ["status"]=>
    int(10)
    ["sort"]=>
    int(0)
    ["is_delete"]=>
    int(0)
    ["create_time"]=>
    int(1688696518)
    ["update_time"]=>
    int(1688696518)
  }
  ["relation"]=>
  array(1) {
    ["comments"]=>
    object(think\model\Collection)#47 (1) {
      ["items":protected]=>
      array(2) {
        [0]=>
        object(app\api\model\OrderGoodsComment)#50 (2) {
          ["data"]=>
          array(6) {
            ["order_goods_comment_id"]=>
            int(1)
            ["order_goods_id"]=>
            int(1)
            ["comment"]=>
            string(24) "桂味荔枝非常好吃"
            ["user_id"]=>
            int(1)
            ["create_time"]=>
            int(1689670979)
            ["update_time"]=>
            int(1689670979)
          }
          ["relation"]=>
          array(0) {
          }
        }
        [1]=>
        object(app\api\model\OrderGoodsComment)#51 (2) {
          ["data"]=>
          array(6) {
            ["order_goods_comment_id"]=>
            int(2)
            ["order_goods_id"]=>
            int(2)
            ["comment"]=>
            string(36) "桂味荔枝很甜,一点都不酸"
            ["user_id"]=>
            int(2)
            ["create_time"]=>
            int(1689732500)
            ["update_time"]=>
            int(1689732500)
          }
          ["relation"]=>
          array(0) {
          }
        }
      }
    }
  }
}

当条查询输出的是 Goods 模型实例,Goods 模型实例的 relation 属性(关联数组)保存着关联模型,在该关联数组中,关联方法名 comments 作为键名,结果集对象作为键值,结果集对象的 items 属性(索引数组)保存着关联查询结果。

所用的 SQL 如下

SELECT * FROM `shop_goods` WHERE `goods_id` = 10001 LIMIT 1

SELECT * FROM `shop_order_goods` WHERE `goods_id` = 10001

SELECT * FROM `shop_order_goods_comment` WHERE `order_goods_id` IN (1,2)

获取当前商品的所有评论,访问 comments(关联方法名) 属性即可,如下

<?php

namespace app\api\controller;

use app\api\model\Goods as GoodsModel;

class Goods extends Base
{
    // 显示商品评论
    public function detail()
    {
        $goods_id = 1;

        $detail = GoodsModel::getDetail($goods_id);
        
        echo '<pre>';
        
        var_dump($detail->comments);

        echo '</pre>';

    }
}

输出结果集对象,结果集对象的 items 属性(数组)保存着当前商品的所有评论,如下

object(think\model\Collection)#47 (1) {
  ["items":protected]=>
  array(2) {
    [0]=>
    object(app\api\model\OrderGoodsComment)#50 (2) {
      ["data"]=>
      array(6) {
        ["order_goods_comment_id"]=>
        int(1)
        ["order_goods_id"]=>
        int(1)
        ["comment"]=>
        string(24) "桂味荔枝非常好吃"
        ["user_id"]=>
        int(1)
        ["create_time"]=>
        int(1689670979)
        ["update_time"]=>
        int(1689670979)
      }
      ["relation"]=>
      array(0) {
      }
    }
    [1]=>
    object(app\api\model\OrderGoodsComment)#51 (2) {
      ["data"]=>
      array(6) {
        ["order_goods_comment_id"]=>
        int(2)
        ["order_goods_id"]=>
        int(2)
        ["comment"]=>
        string(36) "桂味荔枝很甜,一点都不酸"
        ["user_id"]=>
        int(2)
        ["create_time"]=>
        int(1689732500)
        ["update_time"]=>
        int(1689732500)
      }
      ["relation"]=>
      array(0) {
      }
    }
  }
}

演示2

获取所有的商品详情以及它的评论

Goods 控制器

<?php
 
namespace app\api\controller;
 
use app\api\model\Goods as GoodsModel;
 
class Goods extends Base
{
    // 获取所有商品
    public function list()
    {
        $goodsList = GoodsModel::getList();

        echo '<pre>';

        var_dump($goodsList);

        echo '</pre>';
    }
}

Goods 模型

<?php

namespace app\api\model;

class Goods extends Base
{

    protected $pk = 'goods_id';

    protected $hidden = ['create_time', 'update_time'];

    public static function getList(array $param)
    {
        // 获取全部商品的详情与评论
        // 第二个参数是所用到的关联方法的方法名
        return self::with('comments')->select();
    }



    // 获取商品的所有评论
    public function comments()
    {   
        return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods');
        // 完整写法
        // return $this->hasManyThrough('OrderGoodsComment', 'OrderGoods', 'goods_id', 'order_goods_id', 'goods_id');
    }
}

订单商品表(中间表) order_goods 模型

<?php
namespace app\api\model;

class OrderGoods extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_id';
}

订单商品评论表  order_goods_comment 模型

<?php

namespace app\api\model;

class OrderGoodsComment extends Base
{
    // 不是默认主键名称记得定义 pk 属性
    protected $pk = 'order_goods_comment_id';
}

Goods 控制器  list 方法输出

object(think\model\Collection)#42 (1) {
  ["items":protected]=>
  array(2) {
    [0]=>
    object(app\api\model\Goods)#41 (2) {
      ["data"]=>
      array(8) {
        ["goods_id"]=>
        int(10001)
        ["goods_name"]=>
        string(12) "桂味荔枝"
        ["stock_total"]=>
        int(0)
        ["status"]=>
        int(10)
        ["sort"]=>
        int(0)
        ["is_delete"]=>
        int(0)
        ["create_time"]=>
        int(1688696518)
        ["update_time"]=>
        int(1688696518)
      }
      ["relation"]=>
      array(1) {
        ["comments"]=>
        object(think\model\Collection)#49 (1) {
          ["items":protected]=>
          array(2) {
            [0]=>
            object(app\api\model\OrderGoodsComment)#52 (2) {
              ["data"]=>
              array(6) {
                ["order_goods_comment_id"]=>
                int(1)
                ["order_goods_id"]=>
                int(1)
                ["comment"]=>
                string(24) "桂味荔枝非常好吃"
                ["user_id"]=>
                int(1)
                ["create_time"]=>
                int(1689670979)
                ["update_time"]=>
                int(1689670979)
              }
              ["relation"]=>
              array(0) {
              }
            }
            [1]=>
            object(app\api\model\OrderGoodsComment)#53 (2) {
              ["data"]=>
              array(6) {
                ["order_goods_comment_id"]=>
                int(2)
                ["order_goods_id"]=>
                int(2)
                ["comment"]=>
                string(36) "桂味荔枝很甜,一点都不酸"
                ["user_id"]=>
                int(2)
                ["create_time"]=>
                int(1689732500)
                ["update_time"]=>
                int(1689732500)
              }
              ["relation"]=>
              array(0) {
              }
            }
          }
        }
      }
    }
    [1]=>
    object(app\api\model\Goods)#43 (2) {
      ["data"]=>
      array(8) {
        ["goods_id"]=>
        int(10002)
        ["goods_name"]=>
        string(15) "妃子笑荔枝"
        ["stock_total"]=>
        int(0)
        ["status"]=>
        int(10)
        ["sort"]=>
        int(0)
        ["is_delete"]=>
        int(0)
        ["create_time"]=>
        int(1690166322)
        ["update_time"]=>
        int(1690166322)
      }
      ["relation"]=>
      array(1) {
        ["comments"]=>
        object(think\model\Collection)#57 (1) {
          ["items":protected]=>
          array(1) {
            [0]=>
            object(app\api\model\OrderGoodsComment)#54 (2) {
              ["data"]=>
              array(6) {
                ["order_goods_comment_id"]=>
                int(3)
                ["order_goods_id"]=>
                int(3)
                ["comment"]=>
                string(27) "妃子笑荔枝酸甜可口"
                ["user_id"]=>
                int(1)
                ["create_time"]=>
                int(1690166563)
                ["update_time"]=>
                int(1690166563)
              }
              ["relation"]=>
              array(0) {
              }
            }
          }
        }
      }
    }
  }
}

多条查询输出的是 Collection(结果集) 对象,Collection 对象的 item 属性保存着每个 Goods 模型实例, 每个 Goods 模型实例的 relation 属性(关联数组)属性保存着关联模型,关联方法名 comments 作为键名,因为关联方法 comments 是对多关联,所以结果集对象作为键值,结果集对象的 items 属性(索引数组)保存着关联查询结果。

所用到的 SQL 如下

SELECT * FROM `shop_goods` 

SELECT * FROM `shop_order_goods` WHERE `goods_id` IN (10001,10002) 

SELECT * FROM `shop_order_goods_comment` WHERE `order_goods_id` IN (1,2,3)

获取每个商品的评论,访问 comments(关联方法名) 属性即可,如下

<?php
 
namespace app\api\controller;
 
use app\api\model\Goods as GoodsModel;
 
class Goods extends Base
{
    public function list()
    {
        $goodsList = GoodsModel::getList();
        foreach ($goodsList as $value) {
            echo '<pre>';
            var_dump($value->comments);
            echo '</pre>';
        }
 
    }
 
}

Goods 控制器 list 方法输出

object(think\model\Collection)#49 (1) {
  ["items":protected]=>
  array(2) {
    [0]=>
    object(app\api\model\OrderGoodsComment)#52 (2) {
      ["data"]=>
      array(6) {
        ["order_goods_comment_id"]=>
        int(1)
        ["order_goods_id"]=>
        int(1)
        ["comment"]=>
        string(24) "桂味荔枝非常好吃"
        ["user_id"]=>
        int(1)
        ["create_time"]=>
        int(1689670979)
        ["update_time"]=>
        int(1689670979)
      }
      ["relation"]=>
      array(0) {
      }
    }
    [1]=>
    object(app\api\model\OrderGoodsComment)#53 (2) {
      ["data"]=>
      array(6) {
        ["order_goods_comment_id"]=>
        int(2)
        ["order_goods_id"]=>
        int(2)
        ["comment"]=>
        string(36) "桂味荔枝很甜,一点都不酸"
        ["user_id"]=>
        int(2)
        ["create_time"]=>
        int(1689732500)
        ["update_time"]=>
        int(1689732500)
      }
      ["relation"]=>
      array(0) {
      }
    }
  }
}
object(think\model\Collection)#57 (1) {
  ["items":protected]=>
  array(1) {
    [0]=>
    object(app\api\model\OrderGoodsComment)#54 (2) {
      ["data"]=>
      array(6) {
        ["order_goods_comment_id"]=>
        int(3)
        ["order_goods_id"]=>
        int(3)
        ["comment"]=>
        string(27) "妃子笑荔枝酸甜可口"
        ["user_id"]=>
        int(1)
        ["create_time"]=>
        int(1690166563)
        ["update_time"]=>
        int(1690166563)
      }
      ["relation"]=>
      array(0) {
      }
    }
  }
}

如果觉得作者写得好,请帮我点个赞,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThinkPHP6中,实现一对多关联查询的方法是使用hasMany模式。具体设置方式如下: 1. 在主表的模型中使用hasMany方法进行关联设置: ``` public function 附表名() { return $this->hasMany(附表模型::class, '外键字段', '主键字段'); } ``` 例如: ``` public function profile() { return $this->hasMany(Profile::class, 'user_id', 'id'); } ``` 2. 进行一对多关联查询: ``` $user = UserModel::find(主表记录的id); return json($user->附表关联方法名); ``` 例如: ``` $user = UserModel::find(19); return json($user->profile); ``` 3. 进行数据筛选查询: ``` $user->附表关联方法名->where('条件字段', '条件操作符', '条件值'); ``` 例如: ``` $user->profile->where('id', '>=', 10); ``` 4. 使用has()方法查询满足条件的主表记录: ``` UserModel::has('附表关联方法名', '条件操作符', '条件值')->select(); ``` 例如: ``` UserModel::has('profile', '>=', 2)->select(); ``` 5. 使用together()方法,在删除主表记录时,同时删除关联的附表记录: ``` $user = UserModel::with('附表关联方法名')->find(主表记录的id); $user->together(['附表关联方法名'])->delete(); ``` 例如: ``` $user = UserModel::with('profile')->find(22); $user->together(['profile'])->delete(); ``` 以上就是在ThinkPHP6中实现一对多关联查询的方法。希望对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值