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.