如何在Laravel Sushi模型间实现无中间表的静态多对多关系?
解决Laravel Sushi模型多对多关联问题
方案一:使用Sushi中间表模型(推荐)
默认的belongsToMany关联会尝试查询真实数据库中的中间表,而Sushi模型基于静态数据,我们可以创建一个Sushi驱动的中间表模型来模拟关联数据,无需创建真实数据库表。
1. 创建中间表模型
新建App/Models/CategoryProduct.php:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Sushi\Sushi; class CategoryProduct extends Model { use Sushi; // 关联数据,可替换为getRows()方法从外部请求获取 protected $rows = [ ['product_id' => 1, 'category_id' => 10], ['product_id' => 2, 'category_id' => 10], ['product_id' => 2, 'category_id' => 11], ]; }
2. 修改Product模型关联
更新App/Models/Product.php的categories方法:
/** @return BelongsToMany<Category> */ public function categories(): BelongsToMany { // 指定使用Sushi中间表模型对应的表名 return $this->belongsToMany(Category::class, 'category_product'); }
3. 修改Category模型关联
更新App/Models/Category.php的products方法:
/** @return BelongsToMany<Product> */ public function products(): BelongsToMany { return $this->belongsToMany(Product::class, 'category_product'); }
方案二:直接通过模型自带的关联ID数组实现关联
如果不想创建中间表模型,可以利用模型自身的关联ID数组,自定义关联查询逻辑:
1. 更新Product模型数据与关联
class Product extends Model { use Sushi; protected function getRows(): array { // 从外部请求获取的产品数据,包含关联分类ID数组 return [ [ 'id' => 1, 'name' => 'Product 1', 'category_ids' => [10], ], [ 'id' => 2, 'name' => 'Product 2', 'category_ids' => [10, 11], ], ]; } /** @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function categories() { // 通过分类ID数组匹配关联模型 return Category::query()->whereIn('id', $this->category_ids); } }
2. 更新Category模型数据与关联
class Category extends Model { use Sushi; protected function getRows(): array { return [ [ 'id' => 10, 'name' => 'Category 1', 'product_ids' => [1,2], ], [ 'id' => 11, 'name' => 'Category 2', 'product_ids' => [2], ], ]; } /** @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function products() { return Product::query()->whereIn('id', $this->product_ids); } }
注意:方案二的关联无法使用
load()批量预加载,若需要批量加载功能,优先选择方案一。
测试验证
执行测试代码:
$product = Product::find(1); $product->load('categories'); dd($product->toJson());
可得到期望输出:
{ "id": 1, "name": "Product 1", "categories": [{"id":10,"name":"Category 1"}] }
内容的提问来源于stack exchange,提问作者Dayan Bravo Fraga
相关产品推荐
相关产品推荐

