Adding pinned posts with Laravel

Adding pinned posts with Laravel

Let's say you have a blog and have posts ordered by their published date. Later you decide you want to pin certain posts.

Pinned posts should be displayed before any other posts regardless of their published date.

The Solution

You can accomplish this by modifying the order clause in the query.

Take this order:

->orderBy('published_at', 'desc')

This will order posts by their published date in descending order.

Adding a second-order clause:

->orderBy('is_pinned', 'desc')->orderBy('published_at', 'desc');

This time ordered by a is_pinned column then order by the published_at column.

This will show the posts pinned first and then show the posts in their published order.

The Setup

Adding a migration to add a column called is_pinned to a posts table

php artisan make:migration add_pinned_field_to_posts

Migration

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddPinnedFieldToPosts extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->boolean('is_pinned')->default(false);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropColumn('is_pinned');
        });
    }
}

Create a local scope

In the post model, create a local scope for the order.

public function scopeOrder($query)
    {
        return $query->orderBy('is_pinned', 'desc')->orderBy('published_at', 'desc');
    }

Using the local scope

When querying the posts use the order scope to set the order for both is_pinned and published_at

Post::order()->paginate();

Did you find this article valuable?

Support David Carr by becoming a sponsor. Any amount is appreciated!