Загрузка...

Что такое Macroable в Laravel

laravel cover

Macroable — это трейт (Illuminate\Support\Traits\Macroable), который позволяет динамически добавлять методы в классы во время выполнения приложения.

Проще говоря:
ты можешь взять уже существующий класс Laravel (или свой) и дописать в него новые методы, не меняя сам класс.

Это очень мощный приём, особенно когда:

  • нельзя или не хочется наследоваться
  • нужно расширить функциональность фреймворка
  • хочется писать чистый, читаемый код без хелперов по всему проекту

Простая аналогия

Представь, что у тебя есть класс Collection.

Обычно ты пишешь:

collect($users)->filter(...)->map(...)

А теперь представь, что тебе нужен метод ->active().

Вместо:

collect($users)->filter(fn ($u) => $u->active);

Ты хочешь:

collect($users)->active();

Вот тут и появляется Macroable.


Как работает Macroable внутри

Если заглянуть под капот, то:

  • макросы хранятся в статическом массиве
  • при вызове метода Laravel проверяет:
    «А нет ли такого макроса?»

Если есть — он вызывается как обычный метод объекта.


Пример: добавляем макрос в Collection

1. Добавляем макрос

Обычно это делают в AppServiceProvider:

use Illuminate\Support\Collection;

public function boot()
{
    Collection::macro('active', function () {
        return $this->filter(fn ($item) => $item->active);
    });
}

2. Используем

$users = User::all()->active();

✨ Чисто, красиво, читаемо.


Macroable ≠ Хелперы

Очень важный момент.

Плохо:

active_users($users);

Хорошо:

$users->active();

Почему?

  • читается как естественный язык
  • не засоряет глобальное пространство функций
  • легко найти через IDE
  • логически относится к объекту

Какие классы в Laravel уже Macroable

Laravel активно использует этот трейт. Вот самые популярные:

  • Collection
  • Str
  • Response
  • Request
  • Route
  • Builder (Eloquent и Query Builder)
  • Carbon

Пример: макрос для Str

use Illuminate\Support\Str;

Str::macro('telegramEscape', function (string $text) {
    return preg_replace('/([_*\[\]()~`>#+\-=|{}.!])/', '\\\\$1', $text);
});

Использование:

Str::telegramEscape($message);

Макросы для Eloquent Builder

Очень мощная тема.

Пример: scope без scope

use Illuminate\Database\Eloquent\Builder;

Builder::macro('active', function () {
    return $this->where('active', true);
});

Использование:

User::query()->active()->get();

⚠️ И да — это альтернатива локальным scope, но не замена.
Макросы хороши, когда логика общая для многих моделей.


Макросы с аргументами

Collection::macro('paginate', function ($perPage = 15) {
    $page = request('page', 1);

    return new LengthAwarePaginator(
        $this->forPage($page, $perPage),
        $this->count(),
        $perPage,
        $page
    );
});
$items->paginate(20);

Когда Macroable — это хорошая идея

Используй макросы, если:

  • логика общая
  • метод логично относится к объекту
  • не хочется наследования
  • нужно расширить фреймворк

Когда НЕ стоит использовать Macroable

Не лучший выбор, если:

  • логика специфична для одной модели
  • метод нужен в одном месте
  • ты прячешь бизнес-логику слишком глубоко
  • макрос зависит от контекста (auth, request, session)

Где хранить макросы

Лучшие варианты:

  • AppServiceProvider
  • отдельный сервис-провайдер:
    app/Providers/MacroServiceProvider.php
    
  • по доменам:
    app/Macros/CollectionMacros.php
    app/Macros/StrMacros.php
    

И регистрировать их аккуратно и централизованно.


Типизация и IDE

Laravel умеет @mixin и @method — не игнорируй это.

/**
 * @method static Collection active()
 */
class Collection {}

Или через IDE helper — тогда автокомплит будет идеальным.


Итог

Macroable — это один из самых недооценённых инструментов Laravel.

Он позволяет:

  • писать выразительный код
  • расширять фреймворк без костылей
  • избегать хелперов и лишнего наследования

Если использовать его осознанно — код становится чище, короче и понятнее.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *