Валидация формы 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);
     })
 ],