拉拉维尔商店:结账时存储项目选项的最佳方式


Laravel Store: Best way to store Item options upon checkout

我正在尝试建立一家商店,一切都很顺利。但是我遇到了一个问题,我很难找到最佳选择。

我有一个项目模型:

class Item extends 'Eloquent implements 'Cviebrock'EloquentSluggable'SluggableInterface
{
    protected $table = 'store_items';
    public function options()
    {
        return $this->belongsToMany(''Dcn'Store'Option', 'store_items_options', 'items_id', 'options_id');
    }
}

还有一个期权模型:

class Option extends 'Eloquent implements 'Cviebrock'EloquentSluggable'SluggableInterface
{
    protected $table = 'store_options';
    public function values()
    {
        return $this->belongsToMany(''Dcn'Store'OptionValues', 'store_option_values', 'options_id', 'op-values_id');
    }
}

以及一个选项值模型:

class OptionValues extends 'Eloquent
{
    protected $table = 'store_op-values';
    public function options()
    {
        return $this->belongsToMany(''Dcn'Store'Option', 'store_option_values', 'op-values_id', 'options_id');
    }
}

最后是发票模型:

class Invoice extends 'Eloquent
{
    protected $table = 'store_invoices';
    public function items()
    {
        return $this->belongsToMany(''Dcn'Store'Item', 'store_invoices_items', 'invoice_id', 'item_id');
    }
}

当用户结帐时,我当前创建发票并附加项目,但我需要能够存储发票中每个项目的选项(颜色、大小等(。

我只是不确定在发票中存储项目选项值的最佳方法是什么,因为用户可能有多个只是不同颜色的项目。任何意见将不胜感激。

一种可能的解决方案涉及以下模型/表/关系:

发票

与发票项的一对多关系。

Invoice->hasMany('InvoiceItem')


发票项

此模型包含每张发票的行项目,其中invoice_id(外键(将发票项链接到发票,item_id将发票项链接到库存中的项。(其他订单详细信息也将存储在此处,例如项目的数量等(

InvoiceItem->belongsTo('Invoice')

InvoiceItem->belongsTo('Item')

然后,若要存储为每个发票项选择的选项及其值,与发票项选项存在一对多关系。

InvoiceItem->hasMany('InvoiceItemOption')


发票项选项

对于每个发票项(按invoice_item_id链接(,此模型存储 0、1 或多个选项(通过 option_id 从选项模型链接(和该选项的值(从值模型链接value_id(。

InvoiceItemOption->belongsTo('InvoiceItem')

InvoiceItemOption->belongsTo('Option')

InvoiceItemOption->belongsTo('Value')


项目

这包含您的物品清单,即您的库存。它与发票项具有一对多关系(即每个项目可以出现在许多发票项上,并且每个发票项都有一个项(。每个项目还具有 0、1 或多个可用选项,因此它通过与选项的多对多关系链接。

Item->hasMany('InvoiceItem')

Item->belongsToMany('Option')


item_option

这是一个数据透视表,将每个项目链接到其可用选项(带有item_idoption_id(


选择

所有项目的所有可用选项。每个选项都有 1 个或多个可能的值,并通过与值的多对多关系链接

Option->belongsToMany('Item')

Option->belongsToMany('Value')


option_value

这是一个数据透视表,将每个选项链接到其可用值(带有option_idvalue_id(。


价值

所有选项的所有可用值。

Value->belongsToMany('Option')


对于每个关系,我也定义了反向关系,这将为您提供最大的灵活性。但是,根据您的需要,其中一些反向关系可能是不必要的。


还有另外两种选择,我认为这两种选择都不是好的:

您可以通过多对多关系链接发票和项目(就像您所做的那样(,并将发票行项目信息存储在中间invoice_item数据透视表中。但是,要做到这一点,您需要创建自定义数据透视模型(而不是简单的数据透视表(,因为该模型需要具有hasMany('InvoiceItemOption')关系来存储选定的选项和值。这会在一定程度上限制您与 InvoiceItem 模型交互方式的灵活性,并且此方法实际上没有任何好处。

(但是,如果您对如何设置此类自定义透视模型的良好示例感兴趣,请参阅 https://github.com/laravel/framework/issues/2093#issuecomment-39154456。

第三个甚至不太理想的选择是通过多对多关系链接发票和项目,并以序列化形式将选项和值存储在中间invoice_item数据透视表中,以及任何其他订单详细信息,如数量。为此,您需要在定义发票关系时指定额外的字段:

$this->belongsToMany('Items')->withPivot('quantity', 'options_serialized')->withTimestamps();

但是,这种方法非常不灵活 - 例如,对包含超大绿色衬衫的订单运行查询会很痛苦。