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