(0:00)
Хорошо, вы проработали весь путь до этого заключительного эпизода, где наша цель сейчас – просто завершить несколько мелких моментов, которые нужно исправить в этом нашем демо-проекте. Так что без дальнейших проволочек давайте начнём.
Прежде всего, исправим ошибки, связанные с датой. Вот наша личная статья, и если я пытаюсь редактировать её, то вы заметите, что у нас тут есть проблема, где по умолчанию всегда ставится сегодняшняя дата. Так что, если мы обновим её, то вы по сути увидите здесь две проблемы.
(0:30)
Обновим статью, и да, мы больше не видим её здесь, однако, вы всё ещё можете получить доступ к ней. И это является большой проблемой, согласны? Хорошо, запомним этот момент, и мы рассмотрим его через минуту. Но также, если мы вернёмся ещё раз на страницу редактирования, по умолчанию здесь снова стоит сегодняшний день, так что если вы не заметите это и снова обновите статью, то внезапно она снова будет опубликована. Так что, очевидно, это большая проблема. Давайте исправим её прямо сейчас. Мы знаем, что это будет в нашей форме, не так ли?
(1:00)
И заметьте, что здесь показана такая дата, потому что мы там жёстко прописали сегодняшний день.
Что если мы изменим её на null? Мы используем здесь привязку модели форме, не так ли? Но если мы попытаемся изменить страницу, это не работает, потому что данные не в том формате. Хорошо так что, может быть, давайте сделаем:
$article->published_at
мы узнали, что это экземпляр PHPCarbon
, и просто чтобы освежить вашу память, мы сделали его таким вот здесь.
(1:30)
Мы добавили это в список дат, которые должны рассматриваться как экземпляры PHPCarbon
. Хорошо, возможно, вы думаете: «Джефф, давай просто сделаем так»:
$article->published_at->format('Y-m-d')
и теперь, если мы вернёмся, мы обновим даты, и обновим статью. И если мы попытаемся отредактировать её, то на этот раз, да, всё сработало. Так что, значит проблема решена?
Не совсем так. Если мы попытаемся создать новую статью, то блин, здесь у нас проблема, потому что мы пытаемся получить доступ к переменной PHP$article
внутри формы.
(2:00)
Однако она доступна только на странице редактирования. Когда вы на самом деле создаёте новую статью, переменной PHP$article
не существует. Так что же нам делать в таких ситуациях? На самом деле у вас здесь есть несколько вариантов решения этой проблемы, тот, что очень часто встречается, это когда вы делаете привязку модели форме, для формы создания статьи, вы просто передаёте пустой экземпляр PHPArticle
в данном случае. А для формы редактирования вы передаёте объект, который ссылается на существующую запись в базе данных, не так ли?
(2:30)
Так что, некоторые люди делают так:
{!! Form::open($article = new \App\Article, ['url' => 'articles']) !!}
Так мы используем привязку модели формы, но мы только будем передавать ей новый экземпляр PHPArticle
. Хорошо, если мы вернёмся и обновим, у нас всё ещё есть проблема. Мы пытаемся отформатировать дату published_at, но для нового экземпляра PHPArticle
published_at будет равным null, и вы не сможете вызывать PHPformat()
на null.
(3:00)
Так что проблема именно в этом. Так почему бы нам не исправить это с помощью метода доступа? Вы уже успели немного узнать об этом, у нас есть модифицирующий метод-мутатор или setter.
Давайте добавим ещё один:
public function getPublishedAtAttribute($date)
{
return new Carbon($date);
}
И всё, что мы собираемся здесь сделать, это убедиться, что у нас есть экземпляр PHPCarbon
. Так что теперь, если мы вернёмся и обновим, вы можете увидеть что всё работает. Для новой статьи мы по умолчанию ставим сегодняшний день.
(3:30)
И если изменить существующую статью, это тоже обновляется. Так почему бы нам не придерживаться этого подхода? Однако быстрое примечание по теме, если вы хотите, то можете также сказать:
return (new Carbon($date))->format('Y-m-d');
или кстати, вы можете также воспользоваться PHPCarbon::parse()
. Так что если вы захотите его использовать, то:
return Carbon::parse($date)->format('Y-m-d');
Если это справедливо для вашего приложения, что каждый раз, когда вы получаете поле published_at, вы хотите, чтобы оно было в таком формате, то можете сохранить здесь эту логику.
(4:00)
И значит, из вашей формы можно полностью удалить вот это (PHPformat('Y-m-d')
) и всё должно работать.
Таким образом, наши страницы редактирования (edit) и создания (create) замечательно работают. Круто. Итак, мы справились с этим, но как насчёт того момента, ещё раз, где мы могли посмотреть статью, которая ещё не была опубликована? Давайте обновим дату, допустим через неделю или типа того? Да, она не отображается в нашем списке статей, но мы всё ещё можем увидеть её если попробуем перейти к ней напрямую.
(4:30)
Это явная проблема, так что давайте найдём её причину. Вернёмся к нашему PHPArticlesController
и методу PHPshow()
, не забывайте, что в этой серии мы используем привязку модели к маршруту, и мы определили это в нашем файле RouteServiceProvider.php. Обратите внимание на то, что мы привязываем ключ articles, или символ-шаблон нашего маршрута к экземпляру App\Article.
Но как же нам справиться с ситуацией, когда мы только хотим получить её, если статья была опубликована?
(5:00)
И не забывайте, что мы уже создали область действия запроса для этого вот здесь. У нас есть это, так что похоже нам нужно создать специальную привязку здесь. Давайте попробуем. Но позвольте мне быстро добавить тут docblock:
* Получить параметр published_at.
Хорошо, вернёмся к нашему PHPRouteServiceProvider
, и на этот раз мы скажем:
$router->bind('articles', function($id)
{
});
(5:30)
Это даёт мне достаточно гибкости, чтобы определить, какой именно запрос мы должны запустить. В этом случае мы скажем:
return \App\Article::published()->findOrFail($id);
Я хочу выбрать только те статьи, которые уже были опубликованы. ОК, так что это должно всё исправить. Если я обновлю, это больше не работает, и мы получаем PHPModelNotFoundException
, т.е. именно то, что мы хотим. Но если мы вернёмся на страницу статей:
laravel5.dev/articles
laravel5.dev/articles/17
и да, это действительно работает.
(6:00)
Так что да, это один из способов, как мы можем справиться с этим.
Хорошо, что ещё? Почему бы нам не обновить это и не добавить несколько тегов, используя нашу хорошую и элегантную форму. Обновим статью. Отлично, так что я могу видеть теги, но пока что на них не получается кликать. Так почему бы нам это быстренько не исправить? Обратно в наш редактор, в routes.php, и теперь мне нужен раздел для тегов, так что:
Route::get('tags/{tag}', 'TagsController@show');
(6:30)
и мы хотим здесь шаблон для имени тега, который должен загружать TagsController@show. Так что теперь мы делаем:
shphp artisan make:controller TagsController --plain
используем --plain, без каких-либо методов-заглушек. Хорошо, давайте перейдём к TagsController.php и создадим здесь метод PHPshow()
, который будет принимать имя тега, статьи с которым мы хотим вывести.
public function show($tag)
{
}
Хотим ли мы получить тег с этим именем, или же мы ещё раз захотим использовать привязку модели к маршруту?
(7:00)
Почему бы нам это не использовать? Назад к PHPRouteServiceProvider
, мы можем добавить здесь ещё один:
$router->model('tags', 'App\Tag');
и думаю стоит сделать tags, то есть используем множественное число. Давайте привяжем это к App\Tag, и не забывайте, что у нас уже здесь есть модель PHPTag
. Однако, задумайтесь, то что у нас здесь есть на данный момент будет искать тег с заданным идентификатором, но я на самом деле хочу выслеживать тег, задавая имя.
(7:30)
Так что мы снова должны использовать переопределение, типа такого:
return \App\Tag::where('name', $name)->firstOrFail();
т.е. совпадает с именем тега, и затем найти первый. И я поправлю здесь, из PHP$id
сделаю PHP$name
:
$router->bind('tags', function($name)
ОК, так что наше условие такое: «Я хочу теги, где имя равняется тому, что было передано, и затем просто дайте мне первый найденный или, опять же, бросайте PHPModelNotFoundException
».
Мы можем удалить вот это, следовательно... я знаю, что я очень быстро говорю здесь, но нам нужно многое успеть.
(8:00)
Назад в наш PHPTagsController
, здесь должен быть принят объект PHP$tag
:
public function show(Tag $tag)
{
}
use App\Tag;
и давайте почистим здесь. Отлично. Так что теперь, если мы возвращаем тег:
return $tag;
И посмотрим на это в браузере:
laravel5.dev/tags/personal
у нас здесь есть объект PHP$tag
. Это было преобразовано в формат JSON. Замечательно, так что теперь всё, что я хочу сделать, это показать все статьи, в которых есть этот тег. Легко. У нас уже установлено такое отношение вот здесь (в PHParticles()
).
(8:30)
И значит, я должен быть в состоянии сделать:
return $tag->articles;
И это должно сработать, давайте попробуем, и вот эти две статьи, в которых был этот тег. Давайте сделаем ещё раз для тега coding, и в этом случае он есть только в одной статье. Так что теперь мы просто должны их красиво отобразить и всё будет в порядке. Так почему бы нам не сохранить это, а затем:
return view('articles.index', compact('articles'));
(9:00)
Хорошо, давайте попробуем:
laravel5.dev/tags/coding
И готово. Давайте посмотрим теги personal:
laravel5.dev/tags/personal
вот они, и, конечно, все статьи:
laravel5.dev/articles
И это всё ещё работает. В данном случае заметьте, что мы повторно используем тот же вид со статьями, но в реальной жизни вы можете захотеть использовать специальный вид, может быть что-то общее вроде вида с результатами. Таким образом, вы сможете их легко сортировать, но у вас также будет возможность настроить какую-нибудь мета информацию или название, или ещё какие-то вещи в том же роде.
(9:30)
Вы можете сами поиграть с этим, так как это не так уж и трудно.
Но в любом случае, сейчас это реализовано, возможно, за исключением одной вещи – я снова вижу эту статью Some Personal Article, вот она:
laravel5.dev/articles/16
так что теперь у нас здесь есть два варианта, в данном случае мы не добавили правильную область действия. Мы не сказали, что хотели получить все опубликованные статьи, так что мы могли бы либо добавить это вручную, либо есть также концепция глобальной области действия.
(10:00)
Что по сути означает, что каждый раз, когда я выполняю запрос на этой модели я хочу применить эту область. Так что может быть вы захотите так сделать. В нашем случае, мы просто добавим его вручную. Таким образом, здесь мы получаем коллекцию, но мы на самом деле хотим добавить здесь условие where:
$articles = $tag->articles()->published()->get();
так что это должно её удалить, и да, всё работает.
Хорошо, знаете что, я думаю, мы на этом завершим эту серию. Очевидно вы хотели бы сделать ещё много всего, но я думаю, что теперь у вас есть навыки, чтобы справляться с некоторыми из этих вещей самостоятельно.
(10:30)
И значит, в то время как этот видео-курс завершён, ваше введение в Laravel, вам ещё много чему можно научиться. Так что следите за обновлениями для следующего уровня. И он будет включать в себя всё, что мы не охватили в этом курсе. Это такие вещи, как лучшая обработка сессий, расширенные возможности Eloquent, работа с почтовыми программами, командами и обработчиками, использование командной шины, или рассылки событий и много другого интересного материала. Так что там и увидимся!
Комментарии (2)
А репозитория нет для просмотра кода по циклу видео?
Моя беда, что я плохо знаю английский. И как хорошо, что есть вы!