Основы Laravel 5
На текущий момент на главной странице сайта у нас выводятся все опубликованные статьи с сортировкой в обратном порядке (сначала идут самые последние).
public function index() { $posts = Post::latest('published_at') ->where('published_at', '<=', Carbon::now()) ->get(); return view('post.index', ['posts' => $posts]); }
По сути здесь мы реализовали ту логику которую от нас требовал заказчик - "вывод статей". И то каким образом мы делаем выборку описано в ТЗ. Об этом знаем мы и знает заказчик. Допустим что спустя некоторое время за доработку кода принимается новый разработчик. Что он увидит? Он увидит именно то что написано кодом - "Сделать выборку с условиями". Он не увидит что это регламентированный "вывод статей". Ну и при подобном подходе придется каждый раз вникать в то что выполняет код. Первое что надо сделать - это вынести логику из контроллера. Создать новый метод в модели и название метода должно точно показывать что конкретно будет происходить. Чтобы было понятно и без комментирования кода.
public function index(Post $postModel) { $posts = $postModel->getPublishedPosts(); return view('post.index', ['posts' => $posts]); }
Согласитесь так на много читабельнее. И контроллер занят своим делом - контролирует, а выполняет. Указывает что и кому делать.
Параметром к методу мы указали переменную $postModel как экземпляр класса Post. Для того чтобы начать ее использовать более нам ничего не нужно - Laravel сделает все сам.
Теперь создадим метод getPublishedPosts() в модели Post -
public function getPublishedPosts() { $posts = Post::latest('published_at') ->where('published_at', '<=', Carbon::now()) ->get(); return $posts; }
В приложении нам может потребоваться часто создавать различные выборки именно по опубликованным статьям.
Но в один прекрасный момент логика "что есть опубликованная статья" может поменяться.
Например пусть статья будет считаться опубликованной когда дата публикации в прошлом И поле published = 1;
В таком случае нам пришлось бы изменять все написанные запросы которые основывались на выборках именно опубликованных статей. Для решения этого вопроса напрашивается решение которое бы унифицировало, сделало константой, поместило в единое место, алгоритм определения опубликована статья или нет.
Для этого в Laravel есть решение и назвается оно Scope - область.
Создадим область в модели -
public function scopePublished($query) { $query->where('published_at', '<=', Carbon::now()) ->where('published', '=', 1); }
Метод который будет областью должен начинаться именоваться так - scope<Имя метода>();
Теперь применим область в методе getPublishedPosts() -
public function getPublishedPosts() { $posts = $this->latest('published_at')->published()->get(); return $posts; }
Такми образом мы решили поставленную задачу. И с применением Областей нам не придется переписывать множество запросов которые основывались бы на опубликованных статьях.