Laravel group by result with callback function

Grouping data by some specific conditions is commonly required to reduce load time. Grouping data is the concept of SQL but Laravel provides an effective way to group data into nested collection objects instead of row-level data.

Let’s take an example to perform group by using date.

Creating model and migration

Here, we will create a posts table that has a publish date and perform further logic based on that column. Open a terminal and enter the below command:

php artisan make:model Post -m

The above command will create a model and migration file for posts. Let’s modify each file one by one. Open App\Models\Post.php and modify below:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Test extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'title',
        'slug',
        'content',
        'publish_date'
    ];

    protected $casts = [
        'publish_date'  =>  'date',
    ];
}

Here, we have defined title, slug, content, and publish date columns in the Post model. We have also cast publish_date as a date.

Let’s modify the migration file as a Post model.

<?php

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

class CreatePostTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug');
            $table->text('content');
            $table->text('content');
            $table->date('publish_date');
            $table->softDeletes();
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Let’s create a seeder and factory to seed dummy data. Open a terminal and enter the below command:

php artisan make:factory PostFactory

Open the database/factories/PostFactory.php file and modify it as below:

<?php

namespace Database\Factories;

use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition()
    {
        return [
            'title'         =>  $this->faker->sentence(10),
            'slug'          =>  Str::slug($this->faker->sentence(10)),
            'content'       =>  $this->faker->paragraph(),
            'publish_date'  =>  Carbon::now()->subDays(rand(1,100))->format('Y-m-d')
        ];
    }
}

Now, let’s generate dummy data using the Database Seeder file open the Database/seeders/DatabaseSeeder.php file and enter the below code into the run() method.

\App\Models\Post::factory(100)->create();

Open the terminal and enter the below command into terminal to create a post table and seed data into it:

php artisan migrate

php artisan db:seed

Performing Group By On Date In Laravel

Now our database table is created and we have also completed database seeding into the posts table. so we can perform our queries.

First of all let’s perform day-wise data grouping of the current month’s data.

$posts = \App\Models\Post::whereMonth('publish_date', Carbon::now('m'))
    ->get()
    ->groupBy(function($data){
        return $data->publish_date->format('d');
    });

In the above example, we have added a condition to get only the current month’s data. and then we grouped data day-wise using the groupBy() function with the callback function. The output of this query will have current month’s data and those data will return collection with the day as key and the value will be recorded on that day.

Let’s take another example where we will group data by month. Here we will just modify the return date format function like this:

$posts = \App\Models\Post::whereMonth('publish_date', Carbon::now('m'))
    ->get()
    ->groupBy(function($data){
        return $data->publish_date->format('m');
    });

Here, we can also set grouping by month and year too or even by time if we have a date and time column.

Conclusion

In this article, created a posts table and seeded dummy data into that to perform different types of groups by queries on the date column.