Laravel 4 预先加载约束

Laravel 4 Eager Loading Constraint

假设我有两个模型:

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

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

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

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

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

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

为什么?我应该怎么做才能以降序列出其 FacultyName 显示的所有教授?

谢谢!

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;

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

为了能够对相关字段进行排序,您需要 ->join table 来创建一个 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;

这更像是一个手动过程,但可以在一定程度上进行概括。我建议在您的模型上创建一个范围,并使用模型和关系上可用的方法来替换硬编码值。但是,在开始所有这些之前,请确保您可以让它工作并了解它是如何工作的。