loading...
Cover image for Laravel Tutorial #9: Add Search, Pagination and Related Posts to Our Blog

Laravel Tutorial #9: Add Search, Pagination and Related Posts to Our Blog

ericnanhu profile image Eric Hu Originally published at techjblog.com Updated on ・3 min read

Checkout the Laravel 8 edition of this tutorial: https://dev.to/ericnanhu/laravel-tutorial-for-beginners-laravel-8-edition-1nl0

Search

img

The search function is necessary for any website, and now we’ll add it to our blogging system as well.

Let’s first look at the search form:

resources\views\widgets\sidebar.blade.php
<!-- Search Widget -->
<div class="card my-4">
    <h5 class="card-header">Search</h5>
    <form class="card-body" action="/search" method="GET" role="search">
        {{ csrf_field() }}
        <div class="input-group">
            <input type="text" class="form-control" placeholder="Search for..." name="q">
            <span class="input-group-btn">
            <button class="btn btn-secondary" type="submit">Go!</button>
          </span>
        </div>
    </form>
</div>
Enter fullscreen mode Exit fullscreen mode

Line 5, adds the CSRF protection to the field.

Line 7, adds name attribute to the input field, its value could be anything, here we’ll call it “q”

When the button is clicked, it’ll go to /search, so we need to add the corresponding route:

Route::get('search', 'IndexController@search');
Enter fullscreen mode Exit fullscreen mode

This route points to the search() function in the IndexController. You can create a separate controller for it if you want.

public function search(Request $request)
{
    $key = trim($request->get('q'));
    $posts = Post::query()
    ->where('title', 'like', "%{$key}%")
        ->orWhere('content', 'like', "%{$key}%")
        ->orderBy('created_at', 'desc');

    //get all the categories
    $categories = Category::all();

    //get all the tags
    $tags = Tag::all();

    //get the recent 5 posts
    $recent_posts = Post::where('is_published',true)->orderBy('created_at','desc')->take(5)->get();

    return view('search', array(
        'key'=>$key,
        'posts'=>$posts,
        'categories' => $categories,
        'tags' => $tags,
        'recent_posts' => $recent_posts
    ));
}
Enter fullscreen mode Exit fullscreen mode

Create the view search.blade.php

@extends('master')

@section('content')
    <div class="row">
        <!-- Blog Entries Column -->
        <div class="col-md-8">

            <h1 class="my-4">You are searching for:
                <small>{{$key}}</small>
            </h1>

            @include('widgets.blog-masonry')

        </div>
        @include('widgets.sidebar')
    </div>
@endsection
Enter fullscreen mode Exit fullscreen mode

Pagination

img

When we add more and more posts in our blog, creating a paginator might be a good idea, since we don’t want to have too many posts on one page.

First, we need to add some codes in our controllers, IndexController for example:

$posts = Post::where('is_published',true)->orderBy('id','desc')->paginate(5);
Enter fullscreen mode Exit fullscreen mode

Notice the last method, instead of get(), we have paginate(5). It means we will have 5 posts for every page. Of course, you can change that number to whatever you like.

And now we need to tell Laravel where to add that paginator. Go to resources/views/widgets/blog-masonry.blade.php

<!-- Pagination -->
<ul class="pagination justify-content-center mb-4">
    {{$posts->links()}}
</ul>
Enter fullscreen mode Exit fullscreen mode

Refresh the page, and you should see this at the bottom.

img

Do the same thing for all the pages that need a paginator.

Related Posts

img

The idea is to get the posts with the same tags.

app/Http/Controllers/PostController.php
//related posts
$related_posts = Post::where('is_published',true)->whereHas('tags', function ($q) use ($post) {
    return $q->whereIn('name', $post->tags->pluck('name'));
})
    ->where('id', '!=', $post->id)->take(3)->get();
Enter fullscreen mode Exit fullscreen mode

Line 3, $post->tags->pluck('name') returns an array with all the tags of the current post.

Line 5, where('id', '!=', $post->id) makes sure the same post will not be included.

Remember to return the $related_posts.

Now add the “related posts” section in the view:

<!-- Related Posts -->

<h3>Related Posts</h3>

<div class="row">
    @foreach($related_posts as $post)
    <div class="col-md-4">
        <div class="card mb-4 box-shadow">
            <img class="card-img-top" src="/storage/{{$post->featured_image}}" alt="Card image cap">
            <div class="card-body">
                <p class="card-text">{{\Illuminate\Support\Str::limit(strip_tags($post->content), 100, '...')}}</p>
                <div class="d-flex justify-content-between align-items-center">
                    <div class="btn-group">
                        <a href="/post/{{$post->slug}}" class="btn btn-sm btn-outline-secondary">Read More →</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    @endforeach
</div>
Enter fullscreen mode Exit fullscreen mode

If you are tired of coding, there is always an easy way by using AddThis. They have related posts, share buttons, subscription forms and lots of other tools you may find useful.

Related Articles

How to Make Your Server More Secure

Laravel Tutorial For Beginners

Django Tutorial For Beginners

Discussion

pic
Editor guide