Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Timmypro's avatar

Looping through laravel collection to get date difference

Hi everyone,

I've been trying to loop through a product table in my database to get the date difference between now and a given expiry_date. I actually want to a situation whereby if I get the date difference between now and expiry_date coming from my product's table column and the result gives 30 or less, then send email to the admin about an expiring product.

migration:


<?php

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

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('prod_name');
            $table->string('barcode');
            $table->string('model')->nullable();
            $table->bigInteger('quantity');
            $table->decimal('amount', 8, 2);
            $table->decimal('total_amount', 8, 8);
            $table->integer('manufacturer_id')->unsigned();
            $table->integer('batch_id')->unsigned();

            $table->foreign('manufacturer_id')->references('id')->on('manufacturers')
                ->onDelete('cascade')->onUpdate('cascade');

            $table->foreign('batch_id')->references('id')->on('batches')
                ->onDelete('cascade')->onUpdate('cascade');

            $table->timestamp('expiry_date')->nullable()->default(null);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

app\Commands\NotifyExpiredProducts


<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use App\Product;
use App\Notifications\ExpiryProduct;
use Illuminate\Support\Facades\Notification;

class NotifyExpiredProducts extends Command
{
    
    protected $signature = 'product:expired';

    
    protected $description = 'Command to notify admin of products that are expiring.';


    public function __construct()
    {
        parent::__construct();
    }

    
    public function handle(Product $product)
    {/*
        $expiry_date = $product->findOrFail(4)->expiry_date;
        $now = \Carbon\Carbon::now();
        $result = $expiry_date->diffInDays($now);
        dd($result);*/
        
        $expiry_dates = $product->pluck('expiry_date');

        foreach($expiry_dates as $expiry_date){

            $now = \Carbon\Carbon::now();

            $later = $expiry_date->diffInDays($now) >= 30;
            dd($later);

            //dd($expiry_date->diffInDays($now));

            if($expiry_date->diffInDays($now) <= 30){

                $send = Notification::send(\App\User::all(), new ExpiryProduct($product));

                dd($send);
            }

        }

        //$expiry_date = \Carbon\Carbon::parse(Product::findOrFail(1)->expiry_date);

        //$now = \Carbon\Carbon::now();

        //$date_diff = $now->diffInDays($expiry_date);

        //dd($date_diff);
        //Select all products that the admin needs to be notified about
        //$products = Product::whereRaw('DATEDIFF(now(), expiry_date) != 5')->get();

        //Notification::send(\App\User::all(), new ExpiryProduct($products));

        //dd($products);
        //Notify admin about products expiration
    }
}

app\Notifications\ExpiryProduct.php


<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class ExpiryProduct extends Notification
{
    use Queueable;

    public $product;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($product)
    {
        $this->product = $product;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                ->subject('Expiring Product')
                ->markdown('mail.products.expired', ['product' => $this->product]);
    }


    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toDatabase($notifiable)
    {
        return [
            'product_id' => $this->expiry_product->id,
            'product_name' => $this->expiry_product->prod_name
        ];
    }
}


Thanks a lot in advance :) !

0 likes
3 replies
Snapey's avatar
Snapey
Best Answer
Level 122

why loop?

All you need is all records where the expiry_date is less than today+30 days. You can do this with one query.

You will though need some way to track that you have already notified - i'm sure the admin won't want telling every day about the same ones.

$expiring = Product::where('expiry_date' < now()->addDays(30))->get();

Then iterate over those models, putting them as a list in a single email, rather than one per product.

Please or to participate in this conversation.