Форум программистов, компьютерный форум, киберфорум
PHP: Laravel
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/18: Рейтинг темы: голосов - 18, средняя оценка - 4.72
 Аватар для kib0rg
0 / 0 / 0
Регистрация: 26.10.2011
Сообщений: 49

Как проверить в валидаторе уникальность сразу по нескольким полям из БД

10.06.2021, 14:11. Показов 3921. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!

Есть база данных с полями: id, x, y, z

Есть к примеру 3 записи:
id 1, x = 1, y = 1, z = 1
id 2, x = 1, y = 2, z = 1


есть форма добавления этих записей и соответственно валидатор -
PHP
1
2
3
4
5
$roomData = $this->validate($request, [
            'x' => 'required|unique:rooms',
            'y' => 'required|unique:rooms',
            'z' => 'required|unique:rooms',
        ]);
В данный момент валидатор ищет в базе уникальность по каждому полю.

Вопрос - как сделать валидацию данных так, что бы можно было добавить запись только в том случае, если хотя бы одно (любое) из полей отличается?

То есть на данный момент если я добавлю запись с x = 999, y = 1, z = 1 то валидатор мне выдаст что по полю y и z данные уже есть. А мне надо как раз добавить эту запись и выдавать предупреждение только в том случае, если сразу все три поля совпадают с тем, что уже есть в базе. Подскажите пожалуйста как это сделать?

Заранее спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.06.2021, 14:11
Ответы с готовыми решениями:

Как вносить данные в объект сразу по нескольким полям за один раз
Всем привет, допустим, хочу вносить данные в объект в консоли вот так Имя...(курсор здесь и здесь вношу) Фамилия...(потом могу ...

Как задать уникальность по двум полям
есть поля 1 - id (ид) 2 - id_user (ид пользователя) 3 - date_r (дата) как сделать так чтобы при инсерте нельзя добавить две...

Как получить уникальность по нескольким столбцам
Всем доброй ночи! Приложение работает с ling2db + MySQL. В одну из таблиц нужно добавить из партнёрки utm-метки...

10
 Аватар для tarasalk
1992 / 1216 / 440
Регистрация: 13.06.2013
Сообщений: 4,115
12.06.2021, 16:54
Если валидировать на уровне PHP, то можно написать свою кастомную валидацию.
PHP
1
2
3
4
5
6
7
8
9
10
11
12
$roomData = $this->validate($request, [
    'params' => [
        'required',
        function ($attribute, $value, $fail) {
            $xyz = $attribute['y'] . $attribute['z']])->doesntExist();
            $is_exists = Room::query()->whereRaw('concat(x, y, z) = ?', [$xyz])->exists();
            if ($is_exists) {
            $fail('The '.$attribute.' is exists.');
        }
        },
    ]
]);
А можно на уровне базы повесить индекс уникальности.
SQL
1
ALTER TABLE rooms ADD CONSTRAINT unique_xyz UNIQUE (x, y, z);
1
Эксперт PHP
5755 / 4134 / 1508
Регистрация: 06.01.2011
Сообщений: 11,276
12.06.2021, 17:31
tarasalk, а зачем тут concat?
PHP
1
$is_exists = Room::where($value)->exists();
Где $value -- такой массив:
PHP
1
2
3
4
5
$value = [
    'x' => 1,
    'y' => 1,
    'z' => 1
];
Получится такой запрос:
SQL
1
SELECT EXISTS(SELECT * FROM `rooms` WHERE (`x` = 1 AND `y` = 1 AND `z` = 1)) AS `exists`)
2
 Аватар для kib0rg
0 / 0 / 0
Регистрация: 26.10.2011
Сообщений: 49
13.06.2021, 00:04  [ТС]
Вот интересно, если использовать второй вариант, где в базе мы применим индекс уникальности, то как тогда сделать проверку в валидаторе в таком случае, когда будем добавлять новую запись?

Добавлено через 44 секунды
tarasalk,
0
 Аватар для tarasalk
1992 / 1216 / 440
Регистрация: 13.06.2013
Сообщений: 4,115
13.06.2021, 09:11
Лучший ответ Сообщение было отмечено kib0rg как решение

Решение

Para bellum, я похоже плохо соображал в то время, чушь написал, да Но суть вроде верная. Пишете свой валидатор, в нем делаете запрос в БД на наличие записи.

Цитата Сообщение от kib0rg Посмотреть сообщение
то как тогда сделать проверку в валидаторе в таком случае, когда будем добавлять новую запись?
Тогда можно не валидировать. Просто будете ловить эксепшен по факту. На самом деле это даже более правильно, иначе может быть эффект гонок + не делается лишний запрос.
1
 Аватар для kib0rg
0 / 0 / 0
Регистрация: 26.10.2011
Сообщений: 49
13.06.2021, 22:09  [ТС]
tarasalk, Так и сделаю, сразу в базе уникальность поставлю. Спасибо
0
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.06.2021, 14:43
Цитата Сообщение от tarasalk Посмотреть сообщение
будете ловить эксепшен по факту
Пользуясь случаем, а как в подобных ситуациях определить текстовое сообщение, которое нужно показать пользователю?

Условно, есть 3 поля, x1, x2 и x3, каждое UNIQUE. В случае ошибки у нас есть код и текст на английском языке (в самом исключении). По коду можно определить, что за ошибка, и подготовить шаблон текста, но нужно ещё определить название столбца.

Значит надо регуляркой парсить текст ошибки и вытаскивать название столбца?
0
 Аватар для kib0rg
0 / 0 / 0
Регистрация: 26.10.2011
Сообщений: 49
14.06.2021, 14:54  [ТС]
Jodah, Если я правильно понял ваш вопрос, то можно сделать так -
скрин приклеил. Берем валидатор, в моем случае я на сайте сохраняю ссылку на другой ресурс (то что на скрине), валидатор должен проверить уникальность имени самой ссылки в базе и корректность url. В папке resources/lang/validation.php можно на каждый случай проверки написать сообщение. Потом после валидатора сделать возврать с ошибками/сообщением ->withErrors, можно и инпут вставить

В случае если идет проверка сразу по трем полям, если базе стоит маркер уникальности на три поля, то поидее и ошибка будет как unique, а сообщение типа "такая запись уже существует"
Миниатюры
Как проверить в валидаторе уникальность сразу по нескольким полям из БД  
0
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.06.2021, 15:07
kib0rg, не, я говорю о ситуации, когда мы отказываемся от валидации и просто отправляем запись на добавление.

PHP
1
2
\DB::table('products')->insert(['article' => 1]);
\DB::table('products')->insert(['article' => 1]); // Ошибка - не уникальное поле
Вот эту ошибку мы через try-catch отловили, в итоге у нас в руках объект PDOException, в котором есть номер ошибки (1062) и текст (Duplicate entry '1' for key 'products_article_unique').

И исходя из этого нужно составить корректное сообщение для пользователя. Сам текст можно привязать к номеру ошибки, а вот столбец article (поскольку уникальных полей может быть несколько) можно вытащить только из текста ошибки.
0
 Аватар для tarasalk
1992 / 1216 / 440
Регистрация: 13.06.2013
Сообщений: 4,115
14.06.2021, 15:27
Jodah, парсить строку как-то не очень Если очень надо, я бы получил строку из базы и попарно сравнил колонки.
1
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.06.2021, 19:04
tarasalk, жаль, что в этом плане нет чего-то системного, ну или я не нашёл.

Просто бывают такие вещи, которые не очень хочется всё время прописывать в валидациях. Например, что цена, или вес, или количество на складе имеют тип integer, а значит передаваемое значение не должно быть выше, чем максимальное значение integer в нашей СУБД. Или длина строки не может превышать VARCHAR 255.

Для себя я сделал множество доп. правил, закинул всё это дело в фасад и получилось примерно следующее:

PHP
1
2
3
4
5
[
    'title' => ['required', RuleFacade::string()], // string - не более 255 символов
    'body' => [RuleFacade::text()], // text - не более 65000 символов
    'price' => [RuleFacade::bigintU()], // U = unsigned, не может быть отрицательным
];
Выглядит вроде норм, но всё равно есть ощущение, что я придумал большой костыль.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.06.2021, 19:04
Помогаю со студенческими работами здесь

Как осуществить суммирование в БД по нескольким полям?
Приветствую! Есть БД. В ней 3 поля: Номер вызывающего абонента, Номер вызываемого абонента, Продолжительность разговора. Любой абонент...

Как сделать поиск по нескольким полям?
Я уже искал различные темы, и в интернете искал. Но я не понимаю того что там пишут. Вернее поисковик не совсем правильно работает как...

Как фильтровать товары по нескольким полям?
Здравствуйте, подскажите как можно сделать так, чтобы фильтр был не взаимоисключающим? Т.е. чтобы можно было комбинировать, например...

Как сделать findfirst по нескольким полям?
Как сделать findfirst по нескольким полям?

Как создать запрос в БД по нескольким полям?
Как правильно составить запрос. Или тут без SQL не получится? Private Sub btnFind_Click(sender As Object, e As EventArgs) Handles...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru