2017-08-29 5 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))なエラーになっています。

どうすればこの問題を解決できますか?

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'); 


私は自分のバリデータ要求パー


、here'reスキーマクエリデフォルト Laravelのロジックを使用して答えを探している、というよりも書いています


クエリはOPに存在しましたが、リクエストごとにSQLクエリが追加されましたクエリログから取ら生成されます

それについての詳細を考える
select count(*) as aggregate from `users` where `id` = 7011 and (`users_meta`.`key` = supplier_id and `users_meta`.`value` = 6897) 

それは働いていない理由、それはすべて完璧に理にかなって - 内部joinは、その上に任意の条件を持っていない(それはそれことをまだ奇妙ですクエリログには表示されません。おそらく、selectではなくwhereのテーブルを不必要に結合しないようにLaravelによって行われた最適化です。この時点で、内部where sがusers上で実行し、ないテーブルの上にjoinからされている - とhttps://laravel.com/docs/5.4/queries#joinsあたり(高度なJOIN句)、彼らはそれが(DarkMukkeの答え@あたりに)動作するためにjoin内である必要が

+0

あなた 'drivers'テーブルがあまりにも' users'テーブルに参加すべきではないことで、少ないデータを結合してより速くそれを作ることができます'users_meta'のためにあなたのjoinで' users.id'を使う前に? –

+0

@ChinLeung - 申し訳ありませんが、それはタイプミスでした。今日のコードを再訪しました。そこには 'users'があったはずです – 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 'はチェーンされている(代わりにクロージャとして渡される)ので、違いはありません。私が前に試した2つ目は、未定義のメソッドIlluminate \ Validation \ Rules \ Exists :: join()の呼び出しです。 – eithed

+0

は、複数の結合条件を持つことができるため、編集をチェックします。どこにいたのか。あなたの質問には全く参加していないので、私たちが生成するSQLを表示することができます – DarkMukke

+0

うん.. 'join 'は私の質問にあります - ' $ query-> join(' users_meta '、' users.id ' '='、 'users_meta.user_id') '。 3番目のものは最初のバリエーションであり、afaikも同様に機能します(結合された行を特定のセットに限定するのではなく、特定のデータを結合するほど実際に高速になります) – eithed

関連する問題