質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • PHP

    20407questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5872questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • CentOS

    2716questions

    CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

  • Laravel 5

    1896questions

    Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

  • Vagrant

    1192questions

    Vagrantは、VirtualBox上の仮想マシンを コマンドラインから作成してくれるソフトウェアです。 ビルド環境など容易に構築が可能です。

Laravel5.5でのFormRequestを使った複合ユニークでの重複チェック

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 394

sabamiso

score 8

 実現したいこと

前提
タスクリストモデルとタスクモデルが存在し、タスクリスト(1)がタスク(多)のリレーションを設定している。

データ構造

mysql> show columns from task_lists;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| list_name  | varchar(191)     | NO   |     | NULL    |                |
| created_at | timestamp        | YES  |     | NULL    |                |
| updated_at | timestamp        | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
mysql> show columns from tasks;
+--------------+------------------+------+-----+---------+----------------+
| Field        | Type             | Null | Key | Default | Extra          |
+--------------+------------------+------+-----+---------+----------------+
| id           | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| task_list_id | int(10) unsigned | NO   | MUL | NULL    |                |
| task_name    | varchar(191)     | NO   |     | NULL    |                |
| limit        | date             | NO   |     | NULL    |                |
| done         | tinyint(1)       | NO   |     | 0       |                |
| created_at   | timestamp        | YES  |     | NULL    |                |
| updated_at   | timestamp        | YES  |     | NULL    |                |
+--------------+------------------+------+-----+---------+----------------+


モデル

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class TaskList extends Model
{
    protected $fillable = ['list_name'];

    public function tasks(){
        return $this->hasMany('App\Task');
    }
}
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    protected $fillable = ['task_name', 'limit'];

    public function tasklist(){
        return $this->belongsTo('App/TaskList');
    }
}

viewのタスク追加フォーム

    <form method="post" action="{{ action('TaskController@store', $list) }}" >
      {{ csrf_field() }}
      <div class="form-group">
        <label for="nameInput">タスク名</label>
        <input type="text" class="form-control" id="nameInput" name="task_name">
        <input type="date" class="form-control" id="limitInput" name="limit">
      </div>
      <button type="submit" class="btn btn-primary">新規追加</button>
    </form>

実現したいこと

タスクリスト内のタスクを追加する際、タスクリスト内でのみタスク名の重複を禁止したい。
(MySQLでいう、複合ユニークキーの実現)

ex)
タスクリスト1内に、タスク1が存在し、タスク1を登録する→禁止
タスクリスト1内に、タスク1が存在する状況で、タスクリスト2内にタスク1を登録する->許可

 発生している問題・エラーメッセージ

複合ユニークキーの設定方法がわかりません。
下記のバリデーションルールであれば、タスク名が重複する段階でバリデーションされてしまう

 該当のソースコード

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;


class TaskRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'task_name' => 'required|min:1|max:31|unique:tasks,task_name'. $this->id. ',id,task_list_id'. $this->task_list_id,
        ];
    }
}

 試したこと

下記の記事等を参考にさせていただきましたが、実現できませんでした。
http://tdsen.blog.jp/archives/33449990.html

初歩的な質問なのかもしれませんが、有識者の方、何卒お力添えをよろしくお願いいたします。

 補足情報

下記のバリデーションを設定した場合、エラーが発生しました。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use App\Http\Requests\TaskRequest;

class TaskRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
       return [
            Validator::make($data, [
                'task_name' =>[
                    Rule::unique('tasks')->where(function ($query){
                        return $query->where('task_list_id', $data['task_list_id']);
                    })
                ],
            ]->validate();
        ];
    }
ReflectionException
Class App\Http\Requests\TaskRequest does not exist
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

とりあえず、「,」 が沢山足りていないようですが、

'task_name' => 
                                            ↓ここ              ↓ここ
'required|min:1|max:31|unique:tasks,task_name,'. $this->id. ',id,task_list_id,'. $this->task_list_id,

質問掲載時の、書き間違いでしょうか??


追記します。

uniqueの後ろに指定できるのは、「ユニークチェック対象から除外する」条件です'task_name' =>  'required|min:1|max:31|unique:tasks,task_name,'. $this->id. ',id,task_list_id,'. $this->task_list_id 上記だと、・idが一致する・task_list_id が一致するのどちらかを満たす場合に除外されます。本来は、・idが一致する・task_list_id が一致しないのどちらかを満たす場合に、除外したいはず・・ですよね?なので、php'task_name' =>                                                                             //↓これでnot条件に'required|min:1|max:31|unique:tasks,task_name,'. $this->id. ',id,task_list_id,!'. $this->task_list_id, が、設定すべき内容なのではないかと思われます。

書き直しますね・・・

uniqueの後ろに指定できるのは、「ユニークチェック」条件ですね!

1つめは条件一致で除外、2個目以降は条件一致で対象となります。

'task_name' => 
'required|min:1|max:31|unique:tasks,task_name,'. $this->id. ',id,task_list_id,'. $this->task_list_id

つまり

・idが一致しない
・$this->task_list_idが一致する

の双方を満たすものからユニークチェックを行います。

で、新規作成時の話ですが、

$this->idは何か入っていますか??

-1とか0とか入っていれば大丈夫そうですが、nullの場合、想定の通りに動くのか謎です。
(やったことないので)

もし$this->id がnullなのであれば、バリデーションを

'task_name' => 

'required|min:1|max:31|unique:tasks,tasks,task_name,'. intval($this->id). ',id,task_list_id,'. $this->task_list_id

のようにすれば、上手く行くかもです。

・・・何度も訂正を書いてしまったので、自分でも信頼性に欠ける回答だなと思っております。
すみません・・・

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/21 12:49

    自分のケアレスミスでありました。
    ご指摘の通り、修正させていただきました。
    しかし、バリデーションチェックでの重複禁止が通らず、重複したデータを追加してしまいます。

    キャンセル

  • 2018/05/21 15:27 編集

    回答追記後に、説明文が間違っていたことに気づきました。。すみません ><;  回答はまるごと訂正させていただきました・・

    キャンセル

  • 2018/05/21 16:24

    丁寧な説明ありがとうございました。
    $this->idは、autoインクリメントであるため、nullになっている思うので、intvalを使用すると、予想通りの挙動をしてくれました!
    ありがとうございます。
    ちなみに、回答修正前の方法も試させていただきましたが、そちらも要望どおりの挙動をしてくれましたので、ご報告させていただきます。

    キャンセル

+1

この様な感じで如何でしょうか?
このサイトの「追加のWHERE節を付け加える」使えそうですが…

Validator::make($data, [
    'task_list_id2' => [
        Rule::unique('tests')->where(function($query) use($data){
            return $query->where("task_list_id",$data["task_list_id"]);
        })
    ],
])->validate();

 追記

私の環境ではこのカスタムリクエストクラスで動かせました。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;

class TaskRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(Request $request)
    {
        return [
            'task_list_id2' => 
                Rule::unique('tests')->where(function($query) use($request){
                    return $query->where("task_list_id",$request->task_list_id);
                })
            ];
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/21 12:57

    ご回答ありがとうございます。
    回答の通りに、コードを組み込ませていただきましたところ、補足のようなエラーが表示されました。
    どのような対応を行えばよろしいでしょうか。
    基礎的な質問で申し訳ありません。

    キャンセル

  • 2018/05/21 13:08

    use App\Http\Requests\TaskRequest;

    いらないんじゃないですか?

    キャンセル

  • 2018/05/21 13:10

    use App\Http\Requests\TaskRequest;
    を削除しましても、エラーは変わらぬままの状況です。
    お手数おかけして申し訳ありません。

    キャンセル

  • 2018/05/21 13:28

    エラー内容は
    App\Http\Requests\TaskRequest does not exist
    なので、これを読めない事がエラーの直接原因だと思いますよ。
    requestではなく、controllerでエラーが起きているのではありませんか?

    このあたりも参考になると思います。
    https://qiita.com/niiyz/items/5b83ef5255a1ec64d9d6

    これにてこずるようでしたら、まずはControllerで直接Validationかけてみては?

    キャンセル

  • 2018/05/21 20:30

    ご丁寧に自環境でも試していただき、ありがとうございます。
    ぜひ、参考にさせていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20407questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    5872questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • CentOS

    2716questions

    CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

  • Laravel 5

    1896questions

    Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

  • Vagrant

    1192questions

    Vagrantは、VirtualBox上の仮想マシンを コマンドラインから作成してくれるソフトウェアです。 ビルド環境など容易に構築が可能です。