Как написать валидацию уникальности по двум полям laravel?

как написать валидацию уникальности по комбинации двух полей "source_id" и 'text'
так не работает
'source_id'   => 'unique:table_name, source_id,text',
  • Вопрос задан
  • 2768 просмотров
Решения вопроса 1
Fragster
@Fragster
помогло? отметь решением!
либо функцией:
$validator->after(function ($validator) use ($request, $current_item) {
            if (Items::where('id', '!=', $current_item['id'])->where('source_id', $request->input('source_id'))->where('text', $request->input('text'))->exists()) {
                $validator->errors()->add('source_id', 'Ошибка уникальности сочетания source_id и text');
            }
        });

либо в БД указать уникальный составной индекс (если типы колонок позволяют):
$table->unique(['source_id', 'text']);
и ловить ошибку вставки/сохранения
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
YmNIK_13
@YmNIK_13
Вопросу уже год, но может еще кому пригодится.

Вот как я решил подобное.

В ларе ответы можно обрабатывать отдельно. наследуюсь от класса FormRequest, а у него в свою очередь есть прекрасный метод prepareForValidation() который позволяет предварительно обработать/очистить входящие параметры.

Сам полученный объект имеет метод all() - где содержатся все входные параметры.

Таким образом, в наследуемом классе от FormRequest я добавил поле для хранения второго параметра. а в методе prepareForValidation() его туда помещаю.

Сама валидация проходит в методе rules() - где мы указываем правила.
В нашем распоряжении есть класс Rule который позволяет кастомизировать проверку.

Ниже мой класс который проверяет на уникальность два поля:
name и parent_id

namespace App\Http\Requests\Admin\Common;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class SourceRequest extends FormRequest
{
    protected $parent_id = null;

    protected function prepareForValidation()
    {
        $input = $this->all();

        // parent_id  - это int. который может быть и null, тут мы его сохраняем
        if (isset($input['parent_id'])) {
            $parent_id = intval($input['parent_id']);
            if ($parent_id > 0) {
                $this->parent_id = $parent_id;
            }
        }

        $this->replace($input);
    }


    public function rules()
    {
        // передаем в запрос второй параметр
        $name_rule_uniq = Rule::unique('source')
            ->where(function ($query) {
               // в зависимости от того какой parent_id добавляем правило
                if ($this->parent_id !== null) {
                    $query->where([
                        ['parent_id', $this->parent_id],
                    ]);
                } else {
                    $query->whereNull('parent_id');
                }
            });

        // добавляем игнор если это текущая страница - это для редактирования
        $niche_id = $this->route()->parameter('source');
        if (!empty($niche_id)) {
            $name_rule_uniq->ignore($niche_id);
        }


        return [
            'name' => [
                'required',
                $name_rule_uniq,
            ],
        ];
    }

    // это вывод сообщений если при проверке повторяется имя или оно вообще отсутствует
    // можно не реализовывать
    public function messages()
    {
        return [
            'name.required' => ':attribute - обязательно',
            'name.unique' => ':attribute должно быть уникальным',
        ];
    }

    // это чтоб не писать одно и то же имя валидируемой переменной 
    // можно не реализовывать
    public function attributes()
    {
        return [
            'name' => 'Имя источника',
            'parent_id' => 'Id источника',
        ];
    }

}
Ответ написан
@oleg_ods
'source_id' => 'unique:table_name, source_id',
'text' => 'unique:table_name, text',

Неужели так сложно?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы