Paulund
2017-11-22 #laravel

Creating View Classes In Laravel

In this tutorial we're going to investigate creating view objects in Laravel. This functionality is very useful if you have multiple routes that return the same view in different ways. For example if you have a blog you'll have a page that displays a list of posts. Depending on the route this will display different content but in the same view. On the home page you will display a list of the latest posts but on a category page you'll display a list of posts for the specific category. This means that we need to display the same view from different controllers. Using the new Responsable interface from Laravel 5.5 we can move this view functionality into it's own class to reuse the view and parameters from different controllers.

Responsable Interface

The Responsable interface was added to Laravel in 5.5 and allows objects to be converted to a HTTP response which can be returned from a controller or a route closure. To add this Responsable object all you have to is allow your class to implement Responsable. class HttpResponse implements Responsable This will then require a toResponse() method which will be called when you return this object from a controller.

Home Page Controller

Below is the entire code for the HomeController.php. As you can see the controller has one method which will search for the latest posts and pass them into the PostListResource object. This object will be responsible for collecting the posts and returning them with the blade view.

<?php
namespace App\Http\Controllers;

use App\Http\Resources\PostIndexResource;
use Dappa\Blog\Repositories\PostRepository;

/**
 * Homepage controller
 */
class HomeController extends Controller
{
    /**
     * HomeController constructor.
     *
     * @param PostRepository $repository
     */
    public function __construct(PostRepository $repository)
    {
        $this->repository = $repository;
    }

    /**
     * @return PostIndexResource
     */
    public function index()
    {
        $posts = $this->repository->filter([
            'include' => 'tags',
            'order_by' => '-published_at',
            'page' => request('page')
        ]);
        return new PostListResource($posts);
    }
}

PostListResource

This class will need to collect the posts and in the toResponse method we need to return the view template with posts passed into it. In the constructor we collect a LengthAwarePaginator of the posts. Then in the toResponse method we can return the view helper function with passing in the posts.

<?php

namespace App\Http\Resources;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Contracts\Support\Responsable;

/**
 * Class PostListResource
 * @package App\Http
 */
class PostListResource implements Responsable
{
    /**
     * @var LengthAwarePaginator
     */
    private $posts;

    /**
     * PostListResource constructor.
     * @param LengthAwarePaginator $posts
     */
    public function __construct(LengthAwarePaginator $posts)
    {
        $this->posts = $posts;
    }
  
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function toResponse($request)
    {
        return view('blog.post.list', [
            'posts' => $this->posts
        ]);
    }
}

Now whenever we need to return a list of posts we can reuse this resource class. Another benefit we get is whenever need to pass more information into the view blade template we only have to do this in one place. For example if we want to add SEO title or meta description into the view template we can do this in the resource class and it's applied throughout the site.