Предыдущие части: JOIN, Делаем список категорий
Код для этого выпуска лежит на github в ветке delete-update.
В прошлом выпуске мы добавили таблицу категорий, связанную с таблицей заметок. Всё работает, но остались две задачи: удаление категорий и повторное редактирование заметки.
Они не сильно сложные, поэтому сейчас с ними разберёмся.
Удаление категории
Это в общем-то самое обыденное действие, но из-за того, что категории связаны с заметками, возникает небольшое затруднение.
Если мы удалим заметку, это никак не повляет на всё остальное. Но если мы удалим категорию, тогда у всех заметок, которые принадлежат этой категории, останется недействительный идентификатор категории category_id.
Скажем, у категории "автомобили" id=100. Мы написали несколько заметок, назначив им категорию "автомобили", следовательно у них category_id=100. Когда мы просматриваем список заметок, или отдельную заметку, имя категории достаётся из таблицы категорий, основываясь на category_id, который хранится в заметке.
Но если эта категория удалена, то мы там ничего не найдём, и возникнет ошибка: в заметке записан category_id, но такой категории нет.
Поэтому при удалении категории нужно дополнительно делать что-то с заметками, у которых указана эта категория. Мы можем просто очистить поле category_id, присвоив ему NULL. Это будет означать, что такие заметки не привязаны ни к каким категориям. Их можно будет, например, отредактировать позже, назначив им какую-то новую категорию.
Либо же мы можем завести специальную категорию, которая называется "Без категории", и присваивать её id всем заметкам, которые лишились категории. Что в общем-то примерно то же самое, что и присваивать NULL, просто логика немного другая. В частности, категорию "Без категории" мы тоже можем удалить, и тогда опять начнутся проблемы.
Поэтому, наверное, лучше присваивать NULL.
Допишем код удаления категории в контроллере category.php, добавив в него обнуление category_id у всех связанных заметок:
Я удалил у себя категорию "автомобили" и теперь в моём списке заметок одна заметка отображается без категории:
Чтобы не вводить пользователя в заблуждение, можно обработать это в представлении note/index.php, выводя вместо пустого места что-нибудь более информативное:
И будет это выглядеть так:
И аналогично сделаем для просмотра заметки в представлении note/view.php (категория туда передаётся как отдельный объект $cat):
И как это выглядит:
Здесь мы начинаем навлекать на себя проблемы, так как в двух местах использовали код, который проверяет наличие категории, и также элемент дизайна <font color="red">, который делает шрифт красным. Это значит, что если придётся что-то менять, то придётся это делать уже минимум в двух местах.
Проверку наличия категории можно осуществлять в самой модели, написав для неё метод getCategory(), к примеру, а дизайн сделать отдельным шаблоном (т.н. виджетом), который включается в основной шаблон. Но всё это тема для дальнейших разработок, сейчас нас больше волнует работа с базой.
Повторное редактирование заметки
В форме редактирования заметки мы сделали список категорий, из которого выбираем нужную. Но если после добавления снова зайти в редактирование заметки, то можно заметить, что её поля "Заголовок" и "Тело" заполнены теми значениями, которые хранятся в заметке сейчас. Что и правильно – ведь мы не должны при редактировании каждый раз набирать всё заново.
Но вот в списке категорий не выбрана текущая категория. Там всегда выбран первый элемент.
Если нажать кнопку "Сохранить", то заметка так и сохранится с первой категорией. Мы можем сначала выбрать правильную категорию, но тогда придётся делать это каждый раз, когда мы редактируем заметку.
Чтобы исправить эту ситуацию, нужно доработать вывод списка. Каждый его пункт выводится с помощью HTML-элемента <option>, в котором хранится id категории и её название. Например:
<option value="100">Автомобили</option>
Чтобы сделать любой элемент списка выбранным, нужно добавить к тэгу <option> атрибут selected:
<option value="100" selected>Aвтомобили</option>
Атрибуту selected можно ничего не присваивать, важно лишь его наличие. Но меня, как представителя старой школы, корёжит такое написание, поэтому обычно я пишу так:
<option value="100" selected="true">Автомобили</option>
Некоторые пишут так, но от этого меня тоже корёжит:
<option value="100" selected="selected">Автомобили</option>
В принципе, атрибуту selected можно присвоить любое значение. Важно не значение, а само наличие атрибута.
Короче говоря, тот пункт списка, который имеет атрибут selected, и будет выбранным по умолчанию.
Нужно изменить код представления note/form.php, который в цикле формирует список. На каждом пункте мы будем сравнивать id категории с category_id заметки. Если они совпадают, мы добавим атрибут selected:
И как это получится в HTML:
Ну вот и всё, теперь в списке всегда будет выбрано текущее значение, так же как и в других полях:
На этом мы можем завершить упражнения по созданию каталога.
Теперь вы можете создавать любые таблицы и связывать их между собой, а также делать HTML-представления для просмотра и редактирования данных.