📅  最后修改于: 2023-12-03 15:38:59.633000             🧑  作者: Mango
在 Laravel 中,我们可以使用验证器来验证表单输入是否符合规定。其中一个常用的验证规则是 unique
,用于验证某个字段的值在整个数据库中是否唯一。然而,在实际开发中,有时我们需要排除当前记录本身,例如在更新某个记录时,我们需要验证某个字段是否唯一,但需要排除当前记录的 ID。
本文将介绍如何实现在更新记录时,验证某个字段的值是否唯一,但需要排除当前记录的 ID,以及如何将此逻辑封装成自定义验证规则,以便于在多个地方复用。
在 Laravel 中,unique
验证规则可以通过第三个参数指定要排除的记录:
$request->validate([
'email' => 'unique:users,email_address,'.$user->id
]);
在此例中,'email' 为要验证的字段名,'users' 为要验证的表名,'email_address' 为要验证的字段名,'$user->id' 为当前记录的 ID,也就是要排除的记录。
为了方便在多个地方复用上述逻辑,我们可以将其封装成自定义验证规则。首先,我们需要定义一个验证器类,用于封装验证逻辑:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\DB;
class UniqueExceptSelf implements Rule
{
protected $table;
protected $column;
protected $idColumn;
protected $idValue;
public function __construct($table, $column, $idColumn, $idValue)
{
$this->table = $table;
$this->column = $column;
$this->idColumn = $idColumn;
$this->idValue = $idValue;
}
public function passes($attribute, $value)
{
$count = DB::table($this->table)
->where($this->column, $value)
->where($this->idColumn, '<>', $this->idValue)
->count();
return $count === 0;
}
public function message()
{
return 'The :attribute has already been taken.';
}
}
在此例中,我们定义了一个名为 UniqueExceptSelf
的类,实现了 Rule
接口,因此可以作为验证规则使用。该类包含以下属性:
$table
:要验证的表名$column
:要验证的字段名$idColumn
:当前记录的 ID 字段名$idValue
:当前记录的 ID 的值在 passes
方法中,我们根据上述属性执行相应的查询,从而判断该字段的值是否唯一。在 message
方法中,我们定义了当验证失败时返回的错误信息。
接下来,我们可以在表单请求中使用该验证规则:
use App\Rules\UniqueExceptSelf;
$request->validate([
'email' => [
'required',
new UniqueExceptSelf('users', 'email_address', 'id', $user->id)
],
]);
在此例中,我们通过 new
关键字创建了一个 UniqueExceptSelf
实例,并将其作为验证规则传递给了 email
字段。这样,当 email
字段的值重复时,验证器就会返回 'The email has already been taken.'
错误信息。
如果要扩展此验证规则,例如添加可选参数来指定表名或字段名等,只需在构造方法中添加更多参数,并存储为相应属性即可。
以上介绍了如何实现在更新记录时,验证某个字段的值是否唯一,但需要排除当前记录的 ID,以及如何将此逻辑封装成自定义验证规则。这样,在实际开发中,我们就可以方便地复用该规则,避免重复编写代码。