ThinkPHP 多对多关联

用多对多关联的前提

如果模型 A 多对多关联模型 C,必须存在一张中间表 B 记录着双方的主键,因为就是靠着这张中间表 B 记录着模型 A 与模型 C 的关系。

举例,数据表结构如下

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

// 分类表
category
    category_id - integer // 分类主键
    name - varchar // 分类名称


// 商品分类关系表
goods_category_rel
    id - integer // 主键
    goods_id - integer // 商品表主键的外键
    category_id - integer // 分类表主键的外键

如果按以前的数据表设计,商品表与分类表不是这样设计的,而是 goods 表有一个 category_id 字段,该字段保存 category 表的 category_id,这样每个商品都对应着一个分类,比如荔枝的分类是水果,但这样的设计缺点也是显而易见的,一个商品只能有一个分类,比如荔枝的分类只能是水果,但如果把数据库设计成上面这样的结构,荔枝的分类就可以有多个,比如除了水果,还能是特价产品,或者是其它分类等等。

多对多关联定义

商品表模型:

belongsToMany('Category', 'GoodsCategoryRel');
        // 完整写法
        // return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_id');
    }


}

 belongsToMany 方法的参数如下:

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

  • 关联模型(必须):模型名或者模型类名
  • 中间模型:默认规则是当前模型名+_+关联模型名 (可以指定模型名)
  • 外键1:关联模型在中间表的外键,默认的外键名规则是关联模型名+_id
  • 外键2:当前模型在中间表的外键,默认规则是当前模型名+_id

中间表模型

分类表模型

实例演示

shop_goods 表

 shop_category 表

ThinkPHP 多对多关联_第1张图片

shop_goods_category_rel 表

ThinkPHP 多对多关联_第2张图片

演示1

获取 goods_id 为 1 的商品详情以及它的分类

Goods 控制器

Goods 模型

belongsToMany('Category', 'GoodsCategoryRel');
        // 完整写法
        // return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_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)
  ["category"] => object(think\Collection)#50 (1) {
    ["items":protected] => array(2) {
      [0] => object(app\api\model\Category)#41 (2) {
        ["data"] => array(8) {
          ["category_id"] => int(6)
          ["name"] => string(12) "新鲜水果"
          ["parent_id"] => int(1)
          ["image_id"] => int(0)
          ["status"] => int(1)
          ["sort"] => int(0)
          ["create_time"] => int(1688454738)
          ["update_time"] => int(1688454738)
        }
        ["relation"] => array(1) {
          ["pivot"] => object(think\model\Pivot)#51 (2) {
            ["data"] => array(5) {
              ["id"] => int(1001)
              ["goods_id"] => int(10001)
              ["category_id"] => int(6)
              ["create_time"] => int(1688696518)
              ["update_time"] => int(1688696518)
            }
            ["relation"] => array(0) {
            }
          }
        }
      }
      [1] => object(app\api\model\Category)#47 (2) {
        ["data"] => array(8) {
          ["category_id"] => int(10)
          ["name"] => string(12) "特价产品"
          ["parent_id"] => int(1)
          ["image_id"] => int(0)
          ["status"] => int(1)
          ["sort"] => int(0)
          ["create_time"] => int(1688454870)
          ["update_time"] => int(1688454870)
        }
        ["relation"] => array(1) {
          ["pivot"] => object(think\model\Pivot)#52 (2) {
            ["data"] => array(5) {
              ["id"] => int(1002)
              ["goods_id"] => int(10001)
              ["category_id"] => int(10)
              ["create_time"] => int(1688795635)
              ["update_time"] => int(1688795635)
            }
            ["relation"] => array(0) {
            }
          }
        }
      }
    }
  }
}

关联方法名 category 作为键名,关联查询结果集对象 Collection 作为键值。

获取当前商品的分类,访问 category(关联方法名) 属性即可,如下

category;

        halt($categories);

    }
}

输出

object(think\Collection)#47 (1) {
  ["items":protected] => array(2) {
    [0] => object(app\api\model\Category)#41 (2) {
      ["data"] => array(8) {
        ["category_id"] => int(6)
        ["name"] => string(12) "新鲜水果"
        ["parent_id"] => int(1)
        ["image_id"] => int(0)
        ["status"] => int(1)
        ["sort"] => int(0)
        ["create_time"] => int(1688454738)
        ["update_time"] => int(1688454738)
      }
      ["relation"] => array(1) {
        ["pivot"] => object(think\model\Pivot)#50 (2) {
          ["data"] => array(5) {
            ["id"] => int(1001)
            ["goods_id"] => int(10001)
            ["category_id"] => int(6)
            ["create_time"] => int(1688696518)
            ["update_time"] => int(1688696518)
          }
          ["relation"] => array(0) {
          }
        }
      }
    }
    [1] => object(app\api\model\Category)#46 (2) {
      ["data"] => array(8) {
        ["category_id"] => int(10)
        ["name"] => string(12) "特价产品"
        ["parent_id"] => int(1)
        ["image_id"] => int(0)
        ["status"] => int(1)
        ["sort"] => int(0)
        ["create_time"] => int(1688454870)
        ["update_time"] => int(1688454870)
      }
      ["relation"] => array(1) {
        ["pivot"] => object(think\model\Pivot)#51 (2) {
          ["data"] => array(5) {
            ["id"] => int(1002)
            ["goods_id"] => int(10001)
            ["category_id"] => int(10)
            ["create_time"] => int(1688795635)
            ["update_time"] => int(1688795635)
          }
          ["relation"] => array(0) {
          }
        }
      }
    }
  }
}

演示2

获取所有的商品详情以及它的分类

Goods 控制器

Goods 模型

select();
    }

    // 多对多获取商品分类
    public function category()
    {
        return $this->belongsToMany('Category', 'GoodsCategoryRel');
        // 完整写法
        // return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_id');
    }
}

输出

object(think\Collection)#40 (1) {
  ["items":protected] => array(1) {
    [0] => object(app\api\model\Goods)#42 (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) {
        ["category"] => object(think\Collection)#50 (1) {
          ["items":protected] => array(2) {
            [0] => object(app\api\model\Category)#41 (2) {
              ["data"] => array(8) {
                ["category_id"] => int(6)
                ["name"] => string(12) "新鲜水果"
                ["parent_id"] => int(1)
                ["image_id"] => int(0)
                ["status"] => int(1)
                ["sort"] => int(0)
                ["create_time"] => int(1688454738)
                ["update_time"] => int(1688454738)
              }
              ["relation"] => array(1) {
                ["pivot"] => object(think\model\Pivot)#51 (2) {
                  ["data"] => array(5) {
                    ["id"] => int(1001)
                    ["goods_id"] => int(10001)
                    ["category_id"] => int(6)
                    ["create_time"] => int(1688696518)
                    ["update_time"] => int(1688696518)
                  }
                  ["relation"] => array(0) {
                  }
                }
              }
            }
            [1] => object(app\api\model\Category)#47 (2) {
              ["data"] => array(8) {
                ["category_id"] => int(10)
                ["name"] => string(12) "特价产品"
                ["parent_id"] => int(1)
                ["image_id"] => int(0)
                ["status"] => int(1)
                ["sort"] => int(0)
                ["create_time"] => int(1688454870)
                ["update_time"] => int(1688454870)
              }
              ["relation"] => array(1) {
                ["pivot"] => object(think\model\Pivot)#52 (2) {
                  ["data"] => array(5) {
                    ["id"] => int(1002)
                    ["goods_id"] => int(10001)
                    ["category_id"] => int(10)
                    ["create_time"] => int(1688795635)
                    ["update_time"] => int(1688795635)
                  }
                  ["relation"] => array(0) {
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

每个商品模型的 relation (关联数组)属性保存着关联模型,关联方法名 category 作为键名,结果集对象作为键值,结果集对象的 items 属性(数组)保存着关联查询结果。

获取每个商品的分类,访问 category(关联方法名) 属性即可,如下

category);
        }

    }

}

Goods 模型 getList 方法输出

object(think\Collection)#50 (1) {
  ["items":protected] => array(2) {
    [0] => object(app\api\model\Category)#41 (2) {
      ["data"] => array(8) {
        ["category_id"] => int(6)
        ["name"] => string(12) "新鲜水果"
        ["parent_id"] => int(1)
        ["image_id"] => int(0)
        ["status"] => int(1)
        ["sort"] => int(0)
        ["create_time"] => int(1688454738)
        ["update_time"] => int(1688454738)
      }
      ["relation"] => array(1) {
        ["pivot"] => object(think\model\Pivot)#51 (2) {
          ["data"] => array(5) {
            ["id"] => int(1001)
            ["goods_id"] => int(10001)
            ["category_id"] => int(6)
            ["create_time"] => int(1688696518)
            ["update_time"] => int(1688696518)
          }
          ["relation"] => array(0) {
          }
        }
      }
    }
    [1] => object(app\api\model\Category)#47 (2) {
      ["data"] => array(8) {
        ["category_id"] => int(10)
        ["name"] => string(12) "特价产品"
        ["parent_id"] => int(1)
        ["image_id"] => int(0)
        ["status"] => int(1)
        ["sort"] => int(0)
        ["create_time"] => int(1688454870)
        ["update_time"] => int(1688454870)
      }
      ["relation"] => array(1) {
        ["pivot"] => object(think\model\Pivot)#52 (2) {
          ["data"] => array(5) {
            ["id"] => int(1002)
            ["goods_id"] => int(10001)
            ["category_id"] => int(10)
            ["create_time"] => int(1688795635)
            ["update_time"] => int(1688795635)
          }
          ["relation"] => array(0) {
          }
        }
      }
    }
  }
}

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

你可能感兴趣的:(数据库,php,ThinkPHP)