Laravel4对相关模型的范围,以及它的怪异性

时间:2013-09-06 11:25:47

标签: php pdo laravel laravel-4

我有一个Activity模型,它指的是Type模型。

然后我有Schedule模型,可以引用Activity

所以我可能想要根据活动 type 查询计划(可能是NULL,但这是无关紧要的;我只需要一个LEFT JOIN而不是JOIN .. )。

Laravel4的Eloquent允许我写一个 scoper (这里我想要一个负面 scoper)并写下

Schedule::where(...)->notOfType(myType)->...

试图与eager loading constraints一起使用太尴尬了

Schedule::with(array('activities' => function($query)
{
    $query->where('activity_description', 'like', '%lots of lulz%');
}))->get();

...因为在这里我不会查询Activity的属性,即Schedule的直接相关模型,而是Type的属性。我尝试了几个版本的嵌套with s,然后转向好的'JOINs。

public function scopeNotOfType($query, $type) {
    $query  
    ->leftJoin('activities',     'schedule.activity_id', '=', 'activities.id')
    ->leftJoin('activity_types', 'activities.type_id',   '=', 'activity_types.id')
    ->where('activity_types.name', '!=', $type->name);
}

表示根据activity_id将活动加入计划,然后将类型加入基于type_id的活动。此时,我的选择条件将在类型的名称字段上运行。

没有错误,对于非常非常简单的数据,它甚至可以工作,但随后仔细检查后发现数据都是错误的。执行查询和使用SQL分析器进行的简单(太简单!)检查发现返回了预期的数据,仅从Eloquent模型中消失

第一个提示 - 好吧,更多的是牙齿 - 关于发生的事情是我的种子Schedule,一旦被过滤器检索,似乎有一个描述字段“类型(1)说明“而不是预期的”时间表(1)说明“。

每当一个字段在多个模型中存在同名时,我就会从错误的模型中获取值,而不是从Schedule获取。 阿哈。事实是Laravel4是PHP并按顺序检索SQL字段为,并且由于上面SELECT生成的JOIN是类似的,

+----------------+-------------+---------+-------------+
| schedule_id    | description | type_id | description |
+----------------+-------------+---------+-------------+
| 1              | Sched_Desc  | 1       | Type_Desc   |
| 2              | Sched2_Desc | 7       | Type7_Desc  |
+----------------+-------------+---------+-------------+

...当PDO驱动程序在第四列中检索字段值时,description last 实例,类型的描述,覆盖第二个时间表的描述。

1 个答案:

答案 0 :(得分:1)

解决方案I

显而易见的解决方案是只选择我需要的那些字段。从那以后,我一直在考虑Schedule并且我对相关模型的关注度不高,我只是用Schedule指定了select()个字段:

public function scopeNotOfType($query, $type) {
$query 
    ->leftJoin('activities',     'schedule.activity_id', '=', 'activities.id')
    ->leftJoin('activity_types', 'activities.type_id',   '=', 'activity_types.id')
    ->select('schedule.*')
->where('activity_types.name', '!=', $type->name);
}

...而且,只检索Schedule字段,不再有字段名称冲突。

解决方案II

另一个解决方案是在表字段中对表名进行编码,即有一个名为activity.activity_description的字段,以便activity_description不再与<something-else>_description发生冲突;但这感觉更加尴尬,可能并不总是方便。