定义连接时进行验证

时间:2017-08-29 14:12:03

标签: php laravel-5.3

我正在尝试定义验证,仅包括符合特定条件的用户 - 主要是考虑其元数据(存储在另一个表中)具有特定值的字段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)。目前,内部whereusers上运行,而不在join - 以及每https://laravel.com/docs/5.4/queries#joins(高级加入条款)的桌面上,它们需要在内部join让它发挥作用(根据@ DarkMukke的回答)

1 个答案:

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