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()
), ',');
}
}
ソースを読めばしょうもない話なのですが、日本語のドキュメントが意外と見つからなかったので、こちらに残しておきます。