使用Laravel的ORM Eloquent

时间:2015-12-11 11:07:17

标签: php mysql laravel eloquent relationship

我想要做的是通过多个关系(数据透视表)检索数据。 我有三个数据库表

userscitiesjobs

他们是这样构建的(他们不是,只是为了让你一瞥)

用户表
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_userjob_user

CityUser表
city_id int(11)
user_id int(11)

JobUser表
job_id int(11)
user_id int(11)

在每个班级(UserCityJob)中,我获得了使用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将只会加载帖子。当然,您可以调用其他查询构建器来进一步自定义预先加载操作:

但为什么它不起作用?

1 个答案:

答案 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();