LoginSignup
21

More than 5 years have passed since last update.

【Laravel】更新時のユニークチェックで特定の値は対象外としたいときの対応

Posted at

LaravelでWebアプリを作成していて、バリデーションチェックを行うときに以下の部分でハマりました。

  • emailカラムに登録しようとしている値がUNIQUEかどうか判定したい
  • ただし、更新時に自分のemailと重複するのは許容したい
  • 自分かどうかの判定はidカラムではなく、user_idカラムの値で判定したい

1.前提

  • PHP v7.2.5
  • Laravel v5.5.40

2.解決策

$request->validate([
    # unique:ユニークチェックをしたいテーブル名,ユニークチェックをしたいカラム名,ユニークチェックを除外したい値,ユニークチェックを除外したいカラム名
    'email' => 'unique:users,email,'.$this->me->user_id.',user_id',
]);

IDのカラム名がidであれば、上記の第4引数であるuser_idはなくても上手く動きます。
Laravelのデフォルトではプライマリーキーのカラム名はidとなるため、自動でプライマリーキーがidとして検索が行われるからです。

プライマリーキーのカラム名をidでなくuser_idなど、カスタマイズしている場合には上記のようにプライマリーキーのカラム名を明示しなくてはなりません。

3.理由

Laravelのソースを参照すると以下のようになっています。
第4引数でカラム名を取得してくれる構造になっているので、こちらを利用すればOKということになります。

vender/laravel/framework/src/Illuminate/Validation/Rules/Unique.php
<?php

namespace Illuminate\Validation\Rules;

class Unique
{
    use DatabaseRule;

    /**
     * The ID that should be ignored.
     *
     * @var mixed
     */
    protected $ignore;

    /**
     * The name of the ID column.
     *
     * @var string
     */
    protected $idColumn = 'id';

    /**
     * Ignore the given ID during the unique check.
     *
     * @param  mixed  $id
     * @param  string  $idColumn
     * @return $this
     */
    public function ignore($id, $idColumn = 'id')
    {
        $this->ignore = $id;
        $this->idColumn = $idColumn;

        return $this;
    }

    /**
     * Convert the rule to a validation string.
     *
     * @return string
     */
    public function __toString()
    {
        return rtrim(sprintf('unique:%s,%s,%s,%s,%s',
            $this->table,
            $this->column,
            $this->ignore ? '"'.$this->ignore.'"' : 'NULL',
            $this->idColumn,
            $this->formatWheres()
        ), ',');
    }
}

ソースを読めばしょうもない話なのですが、日本語のドキュメントが意外と見つからなかったので、こちらに残しておきます。

4.参考文献

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21