我正在尝试定义验证,仅包括符合特定条件的用户 - 主要是考虑其元数据(存储在另一个表中)具有特定值的字段supplier_id
的用户。因此,我在UpdateXRequest
课程中完成了这项工作:
public function rules()
{
$journey = $this->route()->parameter('journey');
return ['driver_id' => [
Rule::exists('users', 'id')
->where(function($query) use ($journey){
$query->join('users_meta', 'users.id', '=', 'users_meta.user_id')
->where('users_meta.key', 'supplier_id')
->where('users_meta.value', $journey->supplier_id);
})
]
];
}
但是,我收到Column not found: 1054 Unknown column 'users_meta.key' in 'where clause' (SQL: select count(*) as aggregate from users where id = x and (users_meta.key = supplier_id and users_meta.value = y))
错误。
我该如何做到这一点?
我正在寻找使用默认 Laravel逻辑的答案,而不是编写自己的验证器
根据请求,这是架构查询:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(10) unsigned NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`role_id` int(10) unsigned NOT NULL
);
CREATE TABLE IF NOT EXISTS `users_meta` (
`id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`type` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'null',
`key` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`value` text COLLATE utf8_unicode_ci,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL
);
ALTER TABLE `users`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `users_email_unique` (`email`);
ALTER TABLE `users`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT;
ALTER TABLE `users_meta`
ADD PRIMARY KEY (`id`),
ADD KEY `users_meta_user_id_index` (`user_id`),
ADD KEY `users_meta_key_index` (`key`);
ALTER TABLE `users_meta`
MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT;
INSERT INTO `users` (`id`, `email`, `password`, `created_at`, `updated_at`, `role_id`) VALUES (6898, 'a@b.com', '', '2017-08-09 12:15:05', '2017-08-09 13:19:56', 4);
INSERT INTO `users_meta` (`id`, `user_id`, `type`, `key`, `value`, `created_at`, `updated_at`) VALUES (18, 6898, 'string', 'supplier_id', '6897', '2017-08-09 12:15:05', '2017-08-09 12:15:05');
查询存在于OP中,但每个请求添加了从查询日志中生成的SQL查询:
select count(*) as aggregate from `users` where `id` = 7011 and (`users_meta`.`key` = supplier_id and `users_meta`.`value` = 6897)
更多地思考它,这一切都很完美,因为它不起作用 - 内部join
没有任何条件(它仍然很奇怪,它没有出现在查询日志中 - 也许它是一个Laravel完成的优化不会不必要地连接where
的表而不是select
)。目前,内部where
在users
上运行,而不在join
- 以及每https://laravel.com/docs/5.4/queries#joins(高级加入条款)的桌面上,它们需要在内部join
让它发挥作用(根据@ DarkMukke的回答)
答案 0 :(得分:1)
不是100%肯定,但从逻辑上讲,它听起来像你的连接条件应该在关闭中
public function rules()
{
$journey = $this->route()->parameter('journey');
return ['driver_id' => [
Rule::exists('users', 'id')
->where(function($query) use ($journey){
$query->join('users_meta', function ($join) use ($journey) {
$join->on('users.id', '=', 'users_meta.user_id')
->where('users_meta.key', 'supplier_id')
->where('users_meta.value', $journey->supplier_id);
});
})
]
];
}
即便如此,您可能不需要第一个闭包,例如
我错了,其中涉及规则的条件,而不是查询构建器的where条件。
编辑:我没有尝试过这段代码,但根据我的经验,以及文档中的一些双重检查,这应该是正确的。
此外,由于条件都在联接上,您可以通过添加条件来加快数据量,从而加快条件
public function rules()
{
$journey = $this->route()->parameter('journey');
return [
'driver_id' => [
Rule::exists('users', 'id')
->where(function ($query) use ($journey) {
$query->join('users_meta', function ($join) use ($journey) {
$join->on('users.id', '=', 'users_meta.user_id')
->on('users_meta.key', '=', 'supplier_id')
->on('users_meta.value', '=', $journey->supplier_id);
});
})
]
];
}