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

shez1983's avatar

blade customHelpers with loop $key?

so i have a blade helper:

        Blade::directive('date', function ($expression) {
            return "<?php echo ($expression)->format('D d, M'); ?>";
        });

and normally when i echo out a model's date like so: @date($model->start_time)

works nicely..

but i am doing a foreach (on invoices grouped by date paid) so i get a collection which has a date (or null) with another collection as 'values'.. so i am doing:

@forelse($invoiceGroup as $date => $invoices)
       @date($date) 
      @foreach($invoices as $invoice)

@date($date) is giving me problems and not working.. it doesnt pass in the actual value of $date to the @date() function and so i get an error cannot format a string '$date'..

i have dumped($expression) and indeed it is = to literal 'date' and not whatever the date is..

(for now i have created a php helper which does the same thing but kind of annoying..)

0 likes
12 replies
D9705996's avatar

I think you problem is coming from your loop construct as you directive looks ok.

Offical docs show the construct as below

@forelse ($users as $user)
    {{ $user->name }}
@endforelse

Therefore I think you need to remove => $invoices and see what $date holds. You can the do something like @date($date->date)

You will probably need to rename some of your variables though as there are a lot of dates above!

shez1983's avatar

when i echo date in the blade itself i get the correct timestamp whatever it should be.. its just not being passed to the custom Helper...

D9705996's avatar

Could you not use $casts with your date format in the model e.g.

protected $casts = [
    'start_time' => 'date:D d, M',
];

Removes the need for the blade directive?

Snapey's avatar

sometimes Blade helpers just are not worth it

@forelse($invoiceGroup as $date => $invoices)
       {{ $date->format('D d, M') }}
      @foreach($invoices as $invoice)

But actually.... $date probably is just a string key from a groupBy and not a Carbon object? You can only apply format to Carbon object, making the line more like;

   {{ Carbon\Carbon::parse($date)->format('D d, M') }}
shez1983's avatar

i have mentioned this but i will repeat..

when i echo $date inside the blade directive, it echoes out '$date' and not the value of the variable ie a string..

but you are right i did parse the date...

Reason for using a helper is becuase we are extracting date/time all over the place so it would be handy to have it defined in one place should we need to change the format.

@D9705996 casts sounds like a good solution, even i knew about it but i thought it might mess with saving/creating/updating.. or is this purely used when we echo the field/property?

D9705996's avatar

The casts property simply tells eloquent how to format the date when your model is serialized

https://laravel.com/docs/5.6/releases

You may now individually customize the format of Eloquent date cast columns. To get started, specify the desired date format within the cast declaration. Once specified, this format will be used when serializing the model to an array / JSON:

Seems like the ideal place to ensure you dates are returned in a standard format.

If you fancied taking it a step further you could create a base model with protected $dateFormat = 'D d, M'; which extends model. Then extend you models from this base model.

Now you only need to specify the format in $casts if you want to override your application default.

$casts = [
    'start_time' => 'date',
    'custom_start_time' => 'date:U'
];

shez1983's avatar

thats the thing serialize = json object.. anyway will try this.. thanks

D9705996's avatar

@shez1983 - when you pass data from controller to the view it will serialize as an array so will perform the cast.

Snapey's avatar

If the date is part of a model then you can create an accessor with a different name to the column and returns the formatted string.

You are seeing $date in your blade because thats all there is. Blade prepares php code for executing later. You are seeing the code that will be inserted into the view

You have said that $date is the result of grouping by date so it will be just a string, and not something you can influence in a model

However, since $date will be the same as date paid in the first of your grouped invoices, the below should work, subject to you inserting the correct field name

@forelse($invoiceGroup as $date => $invoices)
       @date($invoices->first()->datepaid) 
      @foreach($invoices as $invoice)


shez1983's avatar

i quite clearly said when i do a dump inside the blade directive, on the screen i see the '$date' literal - i cant be any more clearer than that..

Snapey's avatar

You are not understanding me.

The point of the blade directive is to insert PHP code into the view. It is NOT inserting the value of $date

I have said this twice now ..i cant be any more clearer than that..

Did you even try the suggestion I made that would allow you to keep your precious Blade directive... No, I guess too stubborn

Cronix's avatar

Just making a helper is so much easier.

function formatDate($date, $defaultFormat = 'D d, M') {
    if ( ! $date instanceof Carbon\Carbon) {
        $date = new \Carbon\Carbon($date);
    }
    return $date->format($defaultFormat);
}
// use default
{{ formatDate($date) }}
// use another format
{{ formatDate($date, 'Y-m-d') }}

It even works on things that aren't already a carbon object, like a date string.

Please or to participate in this conversation.