Удалить запись, которая связана с другой записью в бд через RESTRICT

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Maksat1991
Сообщения: 57
Зарегистрирован: 2016.10.16, 00:15

Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Maksat1991 »

Есть две таблицы, связь one-many. Например countries и cities.

Код: Выделить всё

ON DELETE RESTRICT
ON UPDATE RESTRICT
Создал для обеих таблиц модель и crud.

Теперь, если я из захочу удалить какую-нибудь страну, то естественно БД мне этого сделать не даст, т.к. у некоторых городов стоит country_id этой страны. А в веб-интерфейсе я увижу ошибку

Код: Выделить всё

Cannot delete or update a parent row: a foreign key constraint fails ... бла-бла-бла
Как быть в такой ситуации? Надо ведь как-то красиво уведомлять пользователя, что он не может удалить запись потому-то потому-то, а не выводить такую грубую ошибку.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

На действии удаления сделай проверку и выведи своё собственное сообщение, прежде чем делать запрос к БД на удаление.
Maksat1991
Сообщения: 57
Зарегистрирован: 2016.10.16, 00:15

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Maksat1991 »

Nex-Otaku писал(а): 2017.07.10, 00:10 На действии удаления сделай проверку и выведи своё собственное сообщение, прежде чем делать запрос к БД на удаление.
Я не могу проверить возможность удаления записи, эта ответственность лежит на плечах субд. Надо, чтобы если она ответит "Удалять нельзя, restrict не позволяет", то чтобы я не выводил клиенту mysql-исключение, а показывал сообщение о невозможности удалить
cool
Сообщения: 9
Зарегистрирован: 2015.12.07, 11:11

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение cool »

Перехватывай это исключение и выводи нужное сообщение.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

Я не могу проверить возможность удаления записи
Такого не бывает.

В нормальном приложении это делается так.
1. Пользователь ткнул кнопку, пошёл запрос на действие.
2. Контроллер начал выполнять действие.
3. В действии выполняется проверка - "а разрешено ли нам удалять эту запись"? Мыслим логически.
4. Если всё в порядке, дёргаем базу и говорим ей удалить запись.
5. Если нет, то выводим сообщение пользователю и из базы удалить ничего не пытаемся.
Перехватывай это исключение и выводи нужное сообщение.
А вот это - костыль, который в будущем доставит проблем.
cool
Сообщения: 9
Зарегистрирован: 2015.12.07, 11:11

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение cool »

Nex-Otaku писал(а): 2017.07.12, 16:05 А вот это - костыль, который в будущем доставит проблем.
Какие это может доставить проблемы?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение ElisDN »

Maksat1991 писал(а): 2017.07.12, 09:55 Я не могу проверить возможность удаления записи, эта ответственность лежит на плечах субд.
Не можете вписать

Код: Выделить всё

if (City::find()->andWhere(['country_id' => $id])->exists()) {
    ...
}
перед удалением?
Maksat1991
Сообщения: 57
Зарегистрирован: 2016.10.16, 00:15

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Maksat1991 »

Nex-Otaku писал(а): 2017.07.12, 16:05
Я не могу проверить возможность удаления записи
Такого не бывает.

В нормальном приложении это делается так.
1. Пользователь ткнул кнопку, пошёл запрос на действие.
2. Контроллер начал выполнять действие.
3. В действии выполняется проверка - "а разрешено ли нам удалять эту запись"? Мыслим логически.
4. Если всё в порядке, дёргаем базу и говорим ей удалить запись.
5. Если нет, то выводим сообщение пользователю и из базы удалить ничего не пытаемся.
Перехватывай это исключение и выводи нужное сообщение.
А вот это - костыль, который в будущем доставит проблем.
Да, можно поставить проверку, нет ли городов с country_id удаляемой страны? Аналогично предложил и ElisDN.
Но неужели все так топорно? Я думал это Yii2 сам сможет проверить, каким-нибудь валидатором например.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

Накладывать ограничения на действия пользователя - это обязанность вашего приложения, а не БД и не фреймворка.
Nerf
Сообщения: 780
Зарегистрирован: 2015.01.29, 00:37

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nerf »

Nex-Otaku писал(а): 2017.07.12, 16:05
Я не могу проверить возможность удаления записи
Такого не бывает.

В нормальном приложении это делается так.
1. Пользователь ткнул кнопку, пошёл запрос на действие.
2. Контроллер начал выполнять действие.
3. В действии выполняется проверка - "а разрешено ли нам удалять эту запись"? Мыслим логически.
4. Если всё в порядке, дёргаем базу и говорим ей удалить запись.
5. Если нет, то выводим сообщение пользователю и из базы удалить ничего не пытаемся.
В идеальном мире это 100% решение. А когда не 2 таблицы? Когда добавляются новые связанные таблицы, надо будет не забыть проверить там, там и там? Сомнительное удовольствие.
Nex-Otaku писал(а): 2017.07.12, 16:05
Перехватывай это исключение и выводи нужное сообщение.
А вот это - костыль, который в будущем доставит проблем.
Обработка исключений - костыль? Один вариант не исключает другого: пытаетесь обработать проблему, если это целесообразно; делаете запрос обернув обработкой yii\db\IntegrityException. В случае неудачи выводите человекопонятное сообщение, логируете проблему.
Какие проблемы может доставить перехват исключения в будущем? Вам либо придется реализовывать полноценное удаление (с удалением связанных данных) или нет. И ваш, и "наш" вариант решает лишь один вариант...
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

В идеальном мире это 100% решение. А когда не 2 таблицы? Когда добавляются новые связанные таблицы, надо будет не забыть проверить там, там и там? Сомнительное удовольствие.
Это требования вашего приложения. Если вам нужно быть уверенным, что действие разрешено, делайте все необходимые проверки.

Если вам "доставляет неудовольствие" вписывать проверки в код - не пишите ) Пусть пользователь разнесёт приложение к чертям, лишь бы вам не напрягаться )
Обработка исключений - костыль?
Исключения тоже должны обрабатываться - например, написать в логи, отправить админу email и вывести внятное сообщение об ошибке пользователю.

Костылём здесь является не обработка исключений, а перекладывание с больной головы на здоровую. Приложение должно убедиться, что действие разрешено, а вместо этого сбрасывает ответственность на БД - "авось ошибка брякнется, если что не так". Это неправильно.
kawabanga
Сообщения: 806
Зарегистрирован: 2013.10.12, 23:35
Откуда: Новосибирск

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение kawabanga »

Nex-Otaku писал(а): 2017.07.21, 06:33

Костылём здесь является не обработка исключений, а перекладывание с больной головы на здоровую. Приложение должно убедиться, что действие разрешено, а вместо этого сбрасывает ответственность на БД - "авось ошибка брякнется, если что не так". Это неправильно.
Не соглашусь. Бывают разные примеры. И на мой взгляд нет нчиего плохого, если переложить это задание на плечи базы данных.
Примеров может быть масса.

Как бы вы поступили?
К примеру таблица user. И еще какие нибудь 10 связных таблиц. У этих связных таблиц еще по 2-3 связных.
Чтобы проверить можно ли удалять таблицу user, вы спросите базу данных 20-30 раз, прежде чем сможете удалить запись.

В первую очередь - приложение это ведь алгоритм, который решает свою задачу, а не играет в хочу/не хочу делать.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

Не стану вас переубеждать. Чем больше программистов пишут код как вы, тем больше мне платят )
kawabanga
Сообщения: 806
Зарегистрирован: 2013.10.12, 23:35
Откуда: Новосибирск

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение kawabanga »

А чего переубеждать, вы не ответили на вопрос, ответили бы, тогда может я иначе стал думать.

В итоге к проекту добавится еще одна таблица, и вам нужно будет всегда помнить о том коде, что там нужно исправлять проверку.
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Удалить запись, которая связана с другой записью в бд через RESTRICT

Сообщение Nex-Otaku »

Куда вы хотите поместить бизнес-логику приложения?

Раскидать её где попало? Кусочками в БД, кусками в коде, ещё где-то размазать?

Или всё-таки собрать в отдельном месте в коде, чтобы всё было наглядно и всегда под контролем?
Ответить