(0:00)
Если вы смотрели наш самый последний урок, то я там остановился на своего рода интриге. Например, у нас здесь есть 2 тега. Давайте представим, что coding был добавлен по ошибке, на самом деле здесь нужен только personal. Хорошо, я отредактирую статью, или удалю один тег, и, если я обновлю страницу, блин, он всё ещё здесь. И мы можем в этом убедиться – сделаю запрос в SQLite:
sqlselect * from articles;
и эта статья имеет идентификатор 16, так что:
sqlselect * from article_tags where article_id = 16;
(0:30)
и да, в БД у нас всё ещё есть 2 тега. Так в чём же здесь проблема? И если вы задумаетесь, то это довольно очевидно. Я вернусь к моему PHPArticlesController
, где мы обновляем существующую статью вот здесь, в PHPupdate()
.
Заметьте, что в этом случае мы обновили модель PHPArticle
и таблицу статей, но мы не обратили никакого внимания на саму сводную таблицу.
(1:00)
И на самом деле это всего лишь первый шаг для решения этой задачи, но давайте сделаем его в самую первую очередь. Итак, давайте посмотрим, если я перейду в мой метод PHPstore()
, вот тот раздел что мне нужен. Если помните, мы берём статью, существующую статью, находим связанные с ней теги, а затем с помощью PHPattach()
добавляем новый тег в эту сводную таблицу. Что если я возьму вот это и просто скопирую и вставлю сюда, будет ли это работать? Подумайте об этом минутку.
(1:30)
И давайте проверим это в браузере. Я отредактирую это ещё раз, мы удаляем coding, я обновлю статью и давайте посмотрим. Блин, всё стало ещё хуже. Раньше у нас были personal и coding, но теперь у нас на самом деле появилась ещё одна ссылка на тег. Давайте проверим. Выполним наш запрос ещё раз, и да заметьте, мы добавили это дважды. Очевидно, что мы не хотим так делать.
(2:00)
И у нас на самом деле есть пара способов решить эту проблему. Во-первых, можно было бы с помощью SQL убедиться, что такая пара всегда уникальна. И таким образом он по определению не позволит вам создать новую запись где article_id = 16 и tag_id = 1.
Это один вариант, но в нашем случае я хочу решить эту проблему по-другому. Как бы нам по сути синхронизировать всё так, чтобы я мог сказать: «всегда при запуске этого метода просто убедитесь, что этот массив идентификаторов тегов, что я даю вам, единственный, который существует в сводной таблице для этой модели»?
(2:30)
Я надеюсь вы понимаете о чём я. И как выясняется, термин sync (синхронизация) и на самом деле является здесь ключевым словом, так что на этот раз я сделаю только одно изменение вот здесь. Вместо метода PHPattach()
, и кстати, есть также метод PHPdetach()
, который выполняет противоположную функцию. Но у нас также есть метод который называется PHPsync()
.
(3:00)
Он так же принимает массив идентификаторов, однако ключевая вещь для понимания в том, что этот массив идентификаторов тегов будет единственным в базе данных, связанным с этим конкретным идентификатором статьи. И это означает, что Laravel будет сам заботиться об удалении и добавлении. Насколько это круто, а?
Почему бы нам это не попробовать? Но для начала давайте здесь немного подчистим. Давайте исправим нашу раннюю ошибку. Почему бы нам просто не сделать:
sqldelete from article_tag;
(3:30)
Хорошо, вернёмся в Chrome. Мы находимся на странице редактирования edit. Я добавлю personal и coding, как мы делали раньше, обновлю, теперь посмотрим, и готово. Но теперь мы сделаем новое изменение. И в этот раз, как и в начале видео, я удалю coding, и если я обновлю статью, смотрите, на этот раз всё работает.
Так что давайте разберёмся. Запустим снова, и на этот раз, так как нам и было нужно, вторая запись в этой таблице, связывавшая статью с тегом coding, теперь удалена.
(4:00)
И это именно потому, что мы здесь использовали метод PHPsync()
. Так что просто помните: PHPattach()
когда вы хотите добавить новые строки в сводную таблицу, PHPdetach()
когда вы хотите удалить их, и PHPsync()
когда вы хотите всё синхронизировать. Мы предоставляем массив из идентификаторов тегов, в этом случае, и только эти идентификаторы будут ассоциироваться со статьёй в сводной таблице, всё остальное в таблице будет удалено.
(4:30)
Так почему бы нам не сделать вот что, почему бы нам не извлечь этот private-метод в нашем контроллере и не назвать его PHPsyncTags()
? И если мы запустим это, мы, вероятно, немного подправим его. Я не хочу передавать запрос на всю статью. Давайте изменим это и лучше будем передавать статью и список тегов, вот так:
$this->syncTags($article, $request->input('tag_list'));
private function syncTags(Article $article, array $tags)
{
$article->tags()->sync($tags);
}
* Синхронизировать список тегов в базе данных.
Теперь мы можем использовать этот же метод в нашем методе PHPstore()
, где мы создаём статью. Вот здесь:
$this->syncTags($article, $request->input('tag_list'));
мы передаём PHP$article
и снова tag_list. И, наконец, почему бы нам не выделить это в метод, ведь по сути мы здесь именно это и делаем. Мы создаём новую статью или публикуем статью, или как вам удобнее это представлять. Давайте сделаем всё просто и скажем:
this->createArticle($request);
(5:30)
ОК, я добавлю этот метод и вставлю это сюда. Тогда я смогу сделать:
return $article;
в нижней части, и затем давайте введём вот это (PHPArticleRequest $request
) и создадим docblock:
* Сохранить новую статью.
* Создать новый экземпляр контроллера статьи.
Хорошо. Хорошо, давайте рассмотрим этот контроллер, по-прежнему очень чистый.
(6:00)
У нас есть метод PHPindex()
, где мы извлекаем последние опубликованные статьи и загружаем вид. Отлично. У нас есть метод PHPshow()
чтобы показать статью, в котором мы просто используем привязку модели к маршруту, чтобы получить статью, и затем загружаем вид и передаём его дальше. Далее у нас имеется страница PHPcreate()
для создания статьи. Мы выбираем некоторые теги из выпадающего списка и загружаем вид. Далее сам процесс сохранения новой статьи – мы делаем автоматическую проверку данных в форме.
(6:30)
И затем, если всё соответствует требованиям, то мы создаём статью, выдаём flash-сообщение и перенаправляем пользователя. Обратите внимание как легко это читается. Здесь нет никаких строк, где вы должны думать 5 секунд и стараться выяснить что именно здесь происходит. Всякий раз, когда вы так делаете, стоит извлекать код в легко-читаемый метод.
Это всё что мне нужно знать, мы создаём статью, и затем позже, если вы на самом деле захотите снова рассмотреть этот процесс, то вы можете копнуть глубже, но в общем, это всё, что нам тут нужно. Мы создаём статью.
(7:00)
Далее у нас есть страница для её редактирования PHPedit()
, где мы снова извлекаем теги и загружаем вид. Краткое замечание, обратите внимание, как мы продублировали это здесь. Я поднял эту тему в последнем видео. Думайте об этом, есть ли способ, чтобы автоматически привязать список тегов для этой формы? Мы вернёмся к этому позже. Далее мы обновляем статью в PHPupdate()
. Снова мы проводим проверку, используя тот же класс формы запроса, а затем мы обновляем статью, синхронизируем теги и переадресуем назад к списку статей.
(7:30)
И, наконец, так как наш проект всё ещё довольно мал, это нормально, что у нас здесь есть такие вещи. Вы не умрёте от того, что у вас есть private-метод в вашем контроллере. Так, у нас есть здесь один для синхронизации наших тегов, и ещё один, который дирижирует процессом создания и сохранения новой статьи. Хорошо, вполне достаточно для этого урока. Вы узнали как синхронизировать ваши сводные таблицы, а также как делать небольшой рефакторинг.