You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel关联查询:从Product模型获取对应OptionsGroup数据

Laravel中获取产品关联的选项组及选项数据方案

先修正模型关联的细节问题

现有Option模型的关联存在两个小问题:

  1. belongsTo关联对应单个模型,方法名应该用单数optionGroup而非复数optionsGroups
  2. 外键参数末尾多了空格,会导致查询错误

修正后的Option模型关联代码:

public function products()
{
    return $this->belongsToMany(Product::class, "product_options", "option_id", "product_id")->using(ProductOptions::class);
}

public function optionGroup()
{
    return $this->belongsTo(OptionsGroup::class, "option_group_id");
}

预加载关联避免N+1查询

获取产品数据时,通过嵌套预加载options及其关联的optionGroup,确保查询效率:

$product = Product::with('options.optionGroup')->find($productId);

转换为期望的数据结构

可以根据场景选择两种实现方式:

方式一:控制器内直接处理集合

适合简单场景快速实现:

$formattedData = [
    'title' => $product->title,
    'optionGroups' => $product->options
        // 按选项组ID分组,把同组的选项归到一起
        ->groupBy('option_group_id')
        ->map(function ($options) {
            // 获取当前分组对应的选项组模型
            $group = $options->first()->optionGroup;
            return [
                'name' => $group->name,
                'options' => $options->map(function ($option) {
                    return [
                        'name' => $option->name
                        // 需要其他字段可在此添加
                    ];
                })
            ];
        })
        // 重置数组索引,去掉分组的ID键
        ->values()
        ->toArray()
];

return response()->json($formattedData);

方式二:使用API资源(推荐,适合复用场景)

通过Laravel的API资源统一处理数据格式,更易维护:

  1. 创建ProductResource:
// app/Http/Resources/ProductResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class ProductResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'title' => $this->title,
            'optionGroups' => OptionGroupResource::collection(
                $this->options->groupBy('option_group_id')
                    ->map(function ($options) {
                        $group = $options->first()->optionGroup;
                        // 给选项组模型手动绑定对应的选项集合
                        $group->setRelation('options', $options);
                        return $group;
                    })
                    ->values()
            )
        ];
    }
}
  1. 创建OptionGroupResource:
// app/Http/Resources/OptionGroupResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class OptionGroupResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'name' => $this->name,
            'options' => OptionResource::collection($this->whenLoaded('options'))
        ];
    }
}
  1. 创建OptionResource:
// app/Http/Resources/OptionResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class OptionResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'name' => $this->name
            // 按需添加其他选项字段
        ];
    }
}
  1. 控制器中使用资源:
$product = Product::with('options.optionGroup')->find($productId);
return new ProductResource($product);

注意事项

  • 确保数据库中产品表的标题字段为title,选项组表的名称字段为name,选项表的名称字段为name,如果字段名不符,需对应修改代码中的字段引用
  • 始终使用预加载(with方法)避免N+1查询问题,提升接口性能

内容的提问来源于stack exchange,提问作者Ye Ah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:10:58