Laravel 4 Eager Loading Constraint

时间:2015-01-14 02:36:46

标签: php laravel

假设我有两个模型:

class Faculty {
    $primaryKey = 'FacultyID';

    public function professors()
    {
        return $this->hasMany('Professor', 'FacultyID', 'FacultyID');
    }
}

class Professor {
    $primaryKey = 'ProfessorID';

    public function faculty()
    {
        return $this->belongsTo('Faculty', 'FacultyID', 'FacultyID');
    }
}
教授有很多教授,教授只属于一个教师。

Faculty中的数据:

FacultyID | FacultyName

    1         Engineering
    2         Business

Professor中的数据:

ProfessorID | FacultyID | ProfessorName

       1         1         A
       2         1         B
       3         1         C
       4         2         D

我有一个页面列出了表格中的所有教授(连续显示教师姓名,教授姓名等) 我还想让用户按教师名称对表格进行排序。因此,我编写以下代码:

$professors = Professor::with(array('faculty' => function($query) {
    $query->orderBy('FacultyName', 'desc');
}));

但是,排序不正确。 所以我尝试通过将闭包替换为以下来调试,看看上面的约束是否正确:

$query->where('FacultyID', '=', '2');

根据表格中的数据,我希望看到结果中只有一位教授。 但结果是它仍然列出了所有教授。

为什么呢?我应该怎么做才能列出所有教授的FacultyName按降序排列?

谢谢!

1 个答案:

答案 0 :(得分:1)

with方法急切地加载您关系中的记录。它是使用从主查询检索的ID运行的第二个查询。它不执行连接。

因此,当你执行Professor::with('faculty')->get()时,它正在运行两个sql语句。您的尝试产生了以下近似SQL查询:

Professor::with('faculty')->get();
// select * from professors;
// select * from faculties where FacultyID in (?);

Professor::with(array('faculty' => function($query) {
    $query->orderBy('FacultyName', 'desc');
}));
// select * from professors;
// select * from faculties where FacultyID in (?) order by FacultyName desc;

Professor::with(array('faculty' => function($query) {
    $query->where('FacultyID', '=', '2');
}));
// select * from professors;
// select * from faculties where FacultyID in (?) and FacultyID = 2;

如您所见,关系的条件根本不会影响父表的查询。

为了能够对相关字段进行排序,您需要->join表创建一个可以订购的SQL语句:

$professors = Professor::join('faculties', 'professors.FacultyID', '=', 'faculties.FacultyID`)
    ->orderBy('faculties.FacultyName', 'desc')
    ->get();
// select * from professors
// inner join faculties
// on professors.FacultyID = faculties.FacultyID
// order by FacultyName desc;

这是一个手动过程,但它可以有点概括。我建议在模型上创建一个范围,并使用模型和关系上可用的方法来替换硬编码值。但是,确保你能够在完成所有工作之前让它工作并理解它是如何工作的。