我想要做的是通过多个关系(数据透视表)检索数据。 我有三个数据库表
users
,cities
和jobs
。
他们是这样构建的(他们不是,只是为了让你一瞥)
用户表
id int(11) PK, Autoincrement
,
name varchar(255)
城市表
id int(11) PK, Autoincrement
,
name varchar(255)
工作表
id int(11) PK, Autoincrement
,
name varchar(255)
现在我有了数据透视表,因为它们是多对多的关系。我得到了表city_user
和job_user
。
CityUser表
city_id int(11)
,
user_id int(11)
JobUser表
job_id int(11)
,
user_id int(11)
在每个班级(User
,City
,Job
)中,我获得了使用belongsToMany
方法定义的关系。
城市类
/**
* Defines the relation between the city and its users
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users()
{
return $this->belongsToMany(User::class, 'city_user');
}
用户类
/**
* Defines the relation between the user and its cities
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function cities()
{
return $this->belongsToMany(City::class, 'city_user');
}
就业表也是如此。我现在想要做的是让所有特定城市的用户都有一份特定的工作。
假设我想查询所有居住在城市且ID为5的用户,并拥有ID为10的作业。
寻找一个关系非常容易
$users = City::find(5)->users;
或
$users = Job::find(10)->users;
。
但是,在这种情况下,如何实现多种关系呢?我试着这样做
$users = City::find(10)->with(['users' => function($query) use ($jobId) {
// Here I'm stuck. I wouldn't know how to query further? Maybe like this
return $query->with('jobs')->whereJobId($jobId);
}]);
但是,当我这样做的时候,我得到的结果是0,所以一定有错。有什么想法吗?
我收到了错误
致命错误:未捕获的异常' PDOException'消息' SQLSTATE [42S22]:未找到列:1054未知列' job_id'在' where子句''在
我也尝试过这样的事情(在with(['consultants'])
内)
$query->with(['jobs' => function ($query) use ($jobId) {
$query->whereJobId($jobId);
}]);
但这看起来并不正确。我还得到Collection
Cities
,但我需要一个Users
。
然后我就这样累了(暂时)
$users = User::with(['cities' => function ($query) use($cityId) {
/** @var \Illuminate\Database\Eloquent\Relations\BelongsToMany $query */
$query->wherePivot('city_id', $cityId);
}])->get();
但是,我得到了所有用户,而不仅仅是那些用户,这更令人困惑,因为文档说
有时您可能希望加载关系,但也为热切加载查询指定其他查询约束。这是一个例子:
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
在此示例中,如果帖子的标题列首先包含单词,则Eloquent将只会加载帖子。当然,您可以调用其他查询构建器来进一步自定义预先加载操作:
但为什么它不起作用?
答案 0 :(得分:1)
您可以通过这种方式解决致命错误:
$users = City::find(10)->with(['users.jobs', function($query) use ($jobId) {
$query->whereJobId($jobId);
});
}]);
但是这不会过滤用户的特定作业ID。例如,我们有两个ID为1
和#2
的用户。用户1
与作业10
相关,而用户2
则不然。上面的代码将为您提供$jobId = 10
的两个用户,因为用户查询将首先执行而不会有任何作业过滤器,并且在用户查询后将执行作业查询。
您必须使用查询构建器的join()
方法:
$users = User::join('job_user', 'users.id', '=', 'job_user.user_id')
->join('city_user', 'users.id', '=', 'city_user.user_id')
->where('job_user.job_id', $jobId)
->where('city_user.city_id', $cityId)
->get();