Database 如何设计数据库以存储;“违约”;项目

Database 如何设计数据库以存储;“违约”;项目,database,laravel,laravel-5,database-design,Database,Laravel,Laravel 5,Database Design,我正在拉威尔开发一个应用程序。我有一个叫Account和ShippingAddress的模型。一个帐户可以有一个或多个ShippingAddress,但ShippingAddress只能有一个帐户。所以我用的是一对多的关系 现在我想实现一个功能,将发货地址标记为“默认”,每个“帐户”只能有一个“默认发货地址”。我已经确定了两种可能的解决方案: 在ShippingAddress表中添加“is_default”列 创建一个“default\u shipping\u address”透视表,我将在其中

我正在拉威尔开发一个应用程序。我有一个叫Account和ShippingAddress的模型。一个帐户可以有一个或多个ShippingAddress,但ShippingAddress只能有一个帐户。所以我用的是一对多的关系

现在我想实现一个功能,将发货地址标记为“默认”,每个“帐户”只能有一个“默认发货地址”。我已经确定了两种可能的解决方案:

  • 在ShippingAddress表中添加“is_default”列
  • 创建一个“default\u shipping\u address”透视表,我将在其中存储“account\u id”和“shipping\u address\u id”

  • 你认为哪一个是最好的解决方案?为什么?对于第二个问题:如何通过透视表实现Laravel中的一对一关系?

    考虑到一个
    发货地址只属于一个
    帐户,使用透视表似乎有点多余,第一个解决方案看起来更干净

    顺便说一句,您可以通过以下方式设计
    模型

    类帐户扩展模型
    {
    公共功能发送地址()
    {
    返回$this->hasMany('App\ShippingAddress');
    }
    公共函数默认值\发货\地址()
    {
    返回$this->hasOne('App\ShippingAddress')->where('is_default',true);
    }
    }
    类ShippingAddress扩展模型
    {
    公共职能账户()
    {
    返回$this->belongsTo('App\Account');
    }
    }
    
    这样,当您检索
    帐户
    模型时,您可以
    “配送地址”
    或仅
    “默认配送地址”
    ,例如:

    $account=account::with('shipping_addresses')->find($id);
    $account=account::with('default\u shipping\u address')->find($id);
    
    显然,您不需要将这两个关系都
    立即加载
    ,因为
    发货地址
    已经包含了defaut发货地址


    您只需使用validation()或database或两者检查代码中是否只有一个默认发货地址。

    我个人的观点是,对于单个收藏夹地址,使用透视表,尽管从形式上看可能更正确,只会给查询增加复杂性。相反,通过在地址中添加一个标志列来确定它的收藏时间,这将使查询更容易

    现在,如果要使用数据透视表,应使用以下函数在帐户模型中建立关系:

    public function defaultShippingAddress()
        {
          return $this->hasOneThrough('App\Models\AccountShippingAddress', 'App\Models\ShippingAddress');
        }
    
    在这里,您可以阅读有关它的全部文档


    问候

    我会选择选项1,因为它更简单,没有缺点。为了确保每个
    帐户只有一个默认
    ShippingAddress
    您可以监听
    saving
    事件,并执行如下验证:

    class ShippingAddress extends Model
    {
        // ... other code
    
        public function boot()
        {
            parent::boot();
    
            static::saving(function (ShippingAddress $shippingAddress) {
                if (! $shippingAddress->is_default) {
                    return;
                }
    
                $defaultAlreadyExists = static::where([
                    ['account_id', '=', $shippingAddress->account_id],
                    ['id', '!=', $shippingAddress->id],
                    ['is_default', '=', true],
                ])->exists();
    
                if ($defaultAlreadyExists) {
                    throw new YourCustomException("Account with id {$shippingAddress->account_id} already has a default shipping address");
                }
            });
        }
    
        // ... other code
    
    }
    

    我想探索这个答案,但我不太明白。我将按如下方式设计我的数据库:
    帐户[id,…]
    发货地址[id,帐户id,…]
    默认发货地址[account\u id,发货地址\u id]
    。现在,我创建了一个
    DefaultShippingAddress
    ,它扩展了
    illumb\Database\Eloquent\Relations\Pivot
    ,因为阅读文档听起来是正确的做法。然后我通过反转参数来实现您建议的方法。但是如果我尝试执行该方法,它将返回一个
    QueryException
    :它无法检索
    shipping\u addresses.id
    。我做错了什么?让我试着实现你的模型,我会回来给出更好的解释。