【问题标题】:Database Model Design With Laravel Eloquent使用 Laravel Eloquent 进行数据库模型设计
【发布时间】:2020-01-22 16:28:42
【问题描述】:

我们在以一种应有的方式查询我们的数据库时遇到了问题: 表格:

employees <1-n> employee_card_validity <n-1> card <1-n> stamptimes
id              id                           id         id
                employee_id                  no         card_id
                card_id                                 timestamp
                valid_from
                valid_to

Employee 通过具有附加属性的 EmployeeCardValidity Pivot 映射到 Card。 我们重用卡片,这意味着一张卡片在数据透视表中有多个条目。哪张卡是对的,由 valid_from/valid_to 决定。这些属性被限制为不重叠。就像这样,员工与时间戳之间始终存在独特的关系,其中一个员工可以拥有多张卡,而一张卡可以属于多个员工。

我们失败的地方是定义从 Employee 到 Stamptimes 的自定义关系,该关系考虑哪些 Stamptimes 属于 Employee。这意味着当我获取 Stamptime 时,它​​的时间戳被明确分配给卡片,因为它位于其 valid_from 和 valid_to 内。

但是我无法定义一个合适的关系来为我提供给定 Employee 的所有 Stamptimes。到目前为止,我唯一要做的就是在 Employee 中定义一个静态字段,并使用它来限制关系仅获取给定时间的 Stamptimes。

public static $date = '';

public function cardsX() {
    return $this->belongsToMany('App\Models\Tempos\Card', 'employee_card_validity',
        'employee_id', 'card_id')
        ->wherePivot('valid_from', '>', self::$date);
}

那我会在Controller里面说:

\App\Models\Tempos\Employee::$date = '2020-01-20 00:00:00';
$ags = DepartmentGroup::with(['departments.employees.cardsX.stamptimes'])

但我不能像使用 sql 那样根据实际查询结果动态地做到这一点:

SELECT ecv.card_id, employee_id, valid_from, valid_to, s.timestamp 
FROM staff.employee_card_validity ecv 
join staff.stamptimes s on s.card_id = ecv.card_id 
and s.stamptimes between valid_from and coalesce(valid_to , 'infinity'::timestamp)
where employee_id = ?

所以我的问题是:数据库设计是不寻常的,还是 ORM 映射器无法描述这种关系。在这种情况下,我是否必须回退到 QueryBuilder/SQL? 您的数据库模型适合 ORM 还是其他方式?

【问题讨论】:

    标签: database laravel join eloquent relation


    【解决方案1】:

    你可以试试:

    DB::query()->selectRaw('*')->from('employee_card_validity')
        ->join('stamptimes', function($join) {
            return $join->on('employee_card_validity.card_id', '=', 'stamptimes.card_id')
                    ->whereRaw('stamptimes.timestamp between employee_card_validity.valid_from and employee_card_validity.valid_to');
        })->where('employee_id', ?)->get();
    

    如果你的 Laravel 是 x > 5.5,你可以发起模型扩展我相信的 Pivot 类,所以:

    EmployeeCardValidity::join('stamptimes', function($join) {
            return $join->on('employee_card_validity.card_id', '=', 'stamptimes.card_id')
                ->whereRaw('stamptimes.timestamp between employee_card_validity.valid_from and employee_card_validity.valid_to');
    })->where('employee_id', ?)->get();
    

    但上面的代码只是翻译你的sql查询,如果我确切地知道你的用例,我相信我可以写得更好。

    【讨论】:

      猜你喜欢
      • 2021-11-08
      • 2023-03-18
      • 1970-01-01
      • 2017-04-03
      • 2014-08-23
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2016-01-14
      相关资源
      最近更新 更多