Валидация формы Laravel уникальна с использованием двух полей
Как я могу получить уникальное правило проверки на 2 поля?
а. Приложение не должно позволять двум людям иметь одинаковое имя и фамилию.
Разрешено, чтобы пользователи заполняли только первое имя или только фамилию. Поскольку у пользователя может быть только один из них.
б. Но если пользователь вводит только первое имя (Глен), ни один другой человек в таблице не должен иметь то же самое (имя name = 'Glen' и фамилия = null). другой "Глен Смит" хорошо.
Я попробовал следующее правило. Он отлично работает, когда оба поля (имя и фамилия) не являются нулевыми:
'firstName' => 'unique:people,firstName,NULL,id,lastName,' . $request->lastName
Это правило не работает на b. когда имеется только одно поле.
Любые подсказки?
Ответы
Ответ 1
Встроенный валидатор unique
не будет действительно поддерживать то, что вы пытаетесь сделать. Цель состоит в том, чтобы убедиться, что единственная действительная уникальная в базе данных, а не составная из двух значений. Однако вы можете создать настраиваемый валидатор:
Validator::extend('uniqueFirstAndLastName', function ($attribute, $value, $parameters, $validator) {
$count = DB::table('people')->where('firstName', $value)
->where('lastName', $parameters[0])
->count();
return $count === 0;
});
Затем вы можете получить доступ к этому новому правилу с помощью:
'firstName' => "uniqueFirstAndLastName:{$request->lastName}"
Вероятно, вам, возможно, придется немного подправить запрос к базе данных, поскольку он не тестировался.
Ответ 2
Это обширный ответ на этот вопрос и как создать обычный валидатор laravel в целом, вы можете просто скопировать и вставить и попытаться понять позже:
Шаг 1. Создайте поставщика app/Providers/CustomValidatorProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator as ValidatorFacade;
/**
* Provider for custom validators. Handles registration for custom validators.
*
* @author Aderemi Dayo<[email protected]>
*/
class CustomValidatorProvider extends ServiceProvider {
/**
* An array of fully qualified class names of the custom validators to be
* registered.
*
* @var array
*/
protected $validators = [
App\Validators\MultipleUniqueValidator::class,
];
/**
* Bootstrap the application services.
*
* @return void
* @throws \Exception
*/
public function boot() {
//register custom validators
foreach ($this->validators as $class) {
$customValidator = new $class();
ValidatorFacade::extend($customValidator->getName(), function() use ($customValidator) {
//set custom error messages on the validator
func_get_args()[3]->setCustomMessages($customValidator->getCustomErrorMessages());
return call_user_func_array([$customValidator, "validate"], func_get_args());
});
ValidatorFacade::replacer($customValidator->getName(), function() use ($customValidator) {
return call_user_func_array([$customValidator, "replacer"], func_get_args());
});
}
}
/**
* Register the application services.
*
* @return void
*/
public function register() {
//
}
}
Шаг 2: обновите приложение app.php в папке конфигурации config/app.php, чтобы включить созданного провайдера в массив поставщика
App\Providers\CustomValidatorProvider::class,
Шаг 3: создайте свой собственный валидатор, в моем случае я создаю несколько уникальных полей validator app/Validators/MultipleUniqueValidator.php
<?php
namespace App\Validators;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Illuminate\Validation\Validator;
/**
* Multiple field uniqueness in laravel
*
* @author Aderemi Dayo<[email protected]>
*/
class MultipleUniqueValidator{
/**
* Name of the validator.
*
* @var string
*/
protected $name = "multiple_unique";
/**
* Return the name of the validator. This is the name that is used to specify
* that this validator be used.
*
* @return string name of the validator
*/
public function getName(): string {
return $this->name;
}
/**
*
* @param string $message
* @param string $attribute
* @param string $rule
* @param array $parameters
* @return string
*/
public function replacer(string $message, string $attribute, string $rule, array $parameters): string {
unset($parameters[0]);
$replacement = implode(", ", $parameters);
$replacement = str_replace("_", " ", $replacement);
$replacement = Str::replaceLast(", ", " & ", $replacement);
$replacement = Str::title($replacement);
return str_replace(":fields", "$replacement", $message);
}
/**
*
* @param string $attribute
* @param mixed $value
* @param array $parameters
* @param Validator $validator
* @return bool
* @throws \Exception
*/
public function validate(string $attribute, $value, array $parameters, Validator $validator): bool {
$model = new $parameters[0];
if (!$model instanceof Model) {
throw new \Exception($parameters[0] . " is not an Eloquent model");
}
unset($parameters[0]);
$this->fields = $parameters;
$query = $model->query();
$request = app("request");
foreach($parameters as $parameter){
$query->where($parameter, $request->get($parameter));
}
return $query->count() == 0;
}
/**
* Custom error messages
*
* @return array
*/
public function getCustomErrorMessages(): array {
return [
$this->getName() => ":fields fields should be unique"
];
}
}
Теперь вы можете сделать это в своем запросе
'ANY_FIELD_CAN_CARRY_IT' => 'required|numeric|multiple_unique:'.YOUR_MODEL_HERE::class.',FIELD_1,FIELD_2,FIELD_3...',
Ответ 3
Я думаю, что вы ищете что-то подобное:
'unique:table_name,column1,null,null,column2,'.$request->column2.',column3,check3'
Ответ 4
Laravel теперь позволяет добавлять предложения where в уникальное правило.
В вашем случае вы можете сделать что-то вроде этого:
'firstName' => [
Rule::unique('people', 'firstName')->where(function ($query) use ($lastName) {
return $query->where('lastName', $lastName);
})
],