#9 Laravel 5: Scope

Основы 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;
}

 

Такми образом мы решили поставленную задачу. И с применением Областей нам не придется переписывать множество запросов которые основывались бы на опубликованных статьях.

Добавить отзыв (пожелание, комментарий)