用远程一对多关联的前提
如果模型 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 为 1 的商品详情以及它的评论
商品 Goods 控制器
<?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);
halt($detail);
}
}
商品表 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 方法输出
array(7) {
["goods_id"] => int(10001)
["goods_name"] => string(12) "桂味荔枝"
["stock_total"] => int(0)
["status"] => int(10)
["sort"] => int(0)
["is_delete"] => int(0)
["comments"] => object(think\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) {
}
}
}
}
}
关联方法名 comments 作为键名,关联查询结果集对象 Collection 作为键值。
获取当前商品的评论,访问 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);
halt($detail->comments);
}
}
输出
object(think\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();
halt($goodsList);
}
}
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\Collection)#43 (1) {
["items":protected] => array(1) {
[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\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) {
}
}
}
}
}
}
}
}
每个商品模型的 relation (关联数组)属性保存着关联模型,关联方法名 comments 作为键名,结果集对象作为键值,结果集对象的 items 属性(数组)保存着关联查询结果。
获取每个商品的分类,访问 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){
dump($value->comments);
}
}
}
Goods 控制器 list 方法输出
object(think\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) {
}
}
}
}