tips tutorials

What is a Laravel Macro, and how can you write an IDE Helper for a Macro?

September 7, 2023

//

1 min read

What is a Macro in Laravel?

Macro is a simple mechanism that lets you add extra functionality to the classes that use the Macroable trait.

For example, in my filament-jalali-datetime plugin for filament, I added a jalaliDate method to the filament TextColumn class using the code below:

1TextColumn::macro('jalaliDate', function (?string $format = null, ?string $timezone = null): static {
2 $format ??= config('filament-jalali-datetime.date_format');
3 
4 $this->formatStateUsing(static function (Column $column, $state) use ($format, $timezone): ?string {
5 /** @var TextColumn $column */
6 
7 if (blank($state)) {
8 return null;
9 }
10 
11 return Jalalian::fromCarbon(Carbon::parse($state)
12 ->setTimezone($timezone ?? $column->getTimezone()))
13 ->format($format);
14 });
15 
16 return $this;
17 });

You can add new functionality to any class that uses the Illuminate\Support\Traits\Macroable trait.

It's valuable, especially when you want to add new functionality to the core components of the framework and share it as a package.

The IDE-Helper

Laravel Macros are magical, and your IDE might not detect them correctly, so to have better IDE support, you must create some IDE helpers so the IDE can see your macros.

The simplest way I found is an ide_helpers.stubs.php on the root that contains the signature of your macros; for example, for my jalaliDate method, I created this file, and my IDE can detect this method without any problem:

1<?php
2 
3namespace Filament\Tables\Columns {
4 class TextColumn
5 {
6 /**
7 * @source packages/filament-jalali-datetime/src/FilamentJalaliDatetimeServiceProvider.php:28
8 */
9 public function jalaliDate(?string $format = null, ?string $timezone = null): self
10 {
11 return $this;
12 }
13}

There is also a package to create automatic IDE-Helpers for macros named tutorigo/laravel-ide-macros.

If you have any other option to create IDE-Helpers for Laravel macros, you can share it in the comments.