2017-08-29 51 views
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, '[email protected]', '', '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 s的这一刻是在usersjoin表上运行,而不是 - 每https://laravel.com/docs/5.4/queries#joins(高级加入条款),他们需要的是内部join为它工作(每@ DarkMukke的答案)

+0

应该不是你的'drivers'表加入'users'表太在'users_meta'的连接中使用'users.id'之前? –

+0

@ChinLeung - 对不起,这是一个错字;今天重新访问了代码,它应该是'users' there – eithed

+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); 
        }); 
       }) 
     ] 
    ]; 
} 
+0

第一个作品,虽然遵循Builder查询(其中'$ query'是实例),但它应该没有区别,因为join应该被链接(而不是作为闭包传递)。第二个我以前试过,它给出了一个'调用未定义的方法Illuminate \ Validation \ Rules \ Exists :: join()' – eithed

+0

检查我的编辑,因为你可以有多个连接条件,首先在哪里。你可以向我们展示它生成的SQL,因为连接在你的问题中根本就没有。 – DarkMukke

+0

呃..'join'就在我的问题中 - '$ query-> join('users_meta','users.id', '=','users_meta.user_id')'。第三个是第一个变体,并且它也会起作用(事实上,它会加快特定数据的速度,而不是将连接的行限制到特定集合),因此增加了 – eithed

相关问题