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

Laravel Eloquent:不同类型产品(书籍/电影)的数据库关联建模咨询

Laravel Eloquent 多类型产品属性建模方案

一、数据库结构设计

按照需求,需建立4张核心表:

  • products:存储产品基础信息
    字段:id, title, description, price, product_type_id, created_at, updated_at
  • product_types:存储产品类型(Book/Movie)
    字段:id, name(值为book或movie), created_at, updated_at
  • book_product_properties:存储书籍专属属性,与products一对一关联
    字段:id, product_id, author, num_of_pages, created_at, updated_at
  • movie_product_properties:存储电影专属属性,与products一对一关联
    字段:id, product_id, director, runtime, created_at, updated_at

二、Eloquent模型定义

1. Product 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Product extends Model
{
    protected $fillable = ['title', 'description', 'price', 'product_type_id'];

    // 关联产品类型
    public function type(): BelongsTo
    {
        return $this->belongsTo(ProductType::class, 'product_type_id');
    }

    // 关联书籍属性
    public function bookProperties(): HasOne
    {
        return $this->hasOne(BookProductProperty::class);
    }

    // 关联电影属性
    public function movieProperties(): HasOne
    {
        return $this->hasOne(MovieProductProperty::class);
    }

    // 自定义访问器:统一获取对应类型的属性
    public function getPropertiesAttribute()
    {
        return match($this->type?->name) {
            'book' => $this->bookProperties,
            'movie' => $this->movieProperties,
            default => null,
        };
    }

    // 本地作用域:按产品类型筛选
    public function scopeOfType($query, string $typeName)
    {
        return $query->whereHas('type', fn($q) => $q->where('name', $typeName));
    }
}

2. ProductType 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class ProductType extends Model
{
    protected $fillable = ['name'];

    public function products(): HasMany
    {
        return $this->hasMany(Product::class);
    }
}

3. BookProductProperty 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class BookProductProperty extends Model
{
    protected $fillable = ['product_id', 'author', 'num_of_pages'];

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }
}

4. MovieProductProperty 模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class MovieProductProperty extends Model
{
    protected $fillable = ['product_id', 'director', 'runtime'];

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }
}

三、便捷查询实现

1. 按类型查询产品及属性

// 查询所有书籍及属性
$books = Product::ofType('book')->with('bookProperties')->get();

// 查询所有电影及属性
$movies = Product::ofType('movie')->with('movieProperties')->get();

2. 获取全部产品并自动加载对应属性

如果需要一次性获取所有类型的产品并加载对应属性,可通过集合处理:

$allProducts = Product::with('type')
    ->get()
    ->map(function ($product) {
        $typeName = $product->type?->name;
        if ($typeName === 'book') {
            $product->load('bookProperties');
        } elseif ($typeName === 'movie') {
            $product->load('movieProperties');
        }
        return $product;
    });

// 直接通过访问器获取属性
foreach ($allProducts as $product) {
    dump($product->properties); // 自动返回书籍或电影的属性
}

3. 关联创建产品及属性

// 获取书籍类型ID
$bookTypeId = ProductType::where('name', 'book')->value('id');

// 创建书籍产品并关联属性
$bookProduct = Product::create([
    'title' => 'Laravel从入门到精通',
    'description' => '全面讲解Laravel框架的开发指南',
    'price' => 79.9,
    'product_type_id' => $bookTypeId,
]);

$bookProduct->bookProperties()->create([
    'author' => '张三',
    'num_of_pages' => 450,
]);

四、额外优化建议

  • 在product_type_id、book_product_properties.product_id、movie_product_properties.product_id字段上添加索引,提升关联查询速度
  • 若后续新增产品类型,只需新增对应属性表及模型关联,扩展性强
  • 可通过模型观察者,在创建产品时自动初始化对应属性表的空记录,避免属性查询时出现null

内容的提问来源于stack exchange,提问作者0xbee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:00:04