Avatar ·

Как создать свои собственные вспомогательные функции (helpers) в Laravel 8?

Всем привет! Я новичок в Laravel (версия 8) и пытаюсь разобраться с созданием кастомных вспомогательных функций. Встроенные функции типа `str_slug()` или `route()` работают отлично, но мне нужно добавить свои. Ситуация: в проекте я часто форматирую даты и цены. В каждом контроллере приходится писать один и тот же код: ```php // Форматирование цены $price = number_format($product->price, 2, ',', ' '); // Форматирование даты $date = Carbon::parse($product->created_at)->format('d.m.Y'); ``` Это жутко раздражает. Я хочу сделать что-то вроде `formatPrice($value)` и `formatDate($date)`, чтобы вызывать их где угодно — в контроллерах, моделях, Blade-шаблонах. Пробовал просто создать файл `app/helpers.php` и написать там функции. В контроллере они работают, но в Blade-шаблонах выдает ошибку "Call to undefined function". Я читал, что нужно подключать файл через composer.json, но не уверен, что делаю правильно. Подскажите, как правильно организовать кастомные хелперы в Laravel 8? Есть ли какой-то стандартный подход? И можно ли сделать так, чтобы функции были доступны и в Blade, и в PHP-коде без лишних действий? Заранее спасибо за помощь! <<>>

Решение: создание кастомных хелперов в Laravel 8

Ты на правильном пути. В Laravel нет встроенного механизма для автозагрузки кастомных хелперов, но всё решается очень просто через Composer. Вот проверенный способ, который работает в Laravel 8 и новее.

Шаг 1. Создаем файл с функциями

Создай файл app/helpers.php (или app/Http/helpers.php — не принципиально). Важно: не используй пространство имен, иначе функции не будут глобально доступны.

<?php

if (!function_exists('formatPrice')) {
    function formatPrice($value, $decimals = 2, $decPoint = ',', $thousandsSep = ' ') {
        return number_format($value, $decimals, $decPoint, $thousandsSep) . ' ₽';
    }
}

if (!function_exists('formatDate')) {
    function formatDate($date, $format = 'd.m.Y') {
        if (!$date) return '';
        return \Carbon\Carbon::parse($date)->format($format);
    }
}

if (!function_exists('generateSlug')) {
    function generateSlug($string) {
        return \Illuminate\Support\Str::slug($string);
    }
}

Обрати внимание на обертку if (!function_exists(...)). Это защита от конфликтов, если ты случайно определишь функцию дважды или она уже существует в другом месте.

Шаг 2. Подключаем файл через Composer

Открой composer.json в корне проекта. В секцию "autoload" добавь:

"files": [
    "app/helpers.php"
]

Должно получиться примерно так:

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    },
    "files": [
        "app/helpers.php"
    ]
}

Шаг 3. Регистрируем автозагрузку

Выполни в терминале:

composer dump-autoload

Эта команда перестраивает карту автозагрузки Composer. Теперь твой файл helpers.php будет загружаться при каждом запросе к приложению.

Шаг 4. Используем хелперы

Теперь функции доступны везде — в контроллерах, моделях, Blade-шаблонах:

// В контроллере
public function show(Product $product) {
    return view('products.show', [
        'price' => formatPrice($product->price),
        'created' => formatDate($product->created_at)
    ]);
}

// В Blade-шаблоне
<p>Цена: {{ formatPrice($product->price) }}</p>
<p>Дата: {{ formatDate($product->created_at) }}</p>

// В модели (например, в аксессоре)
public function getFormattedPriceAttribute() {
    return formatPrice($this->price);
}

Дополнительные советы

  • Группируй функции по смыслу. Если функций много, разбей на несколько файлов: helpers/strings.php, helpers/dates.php. В composer.json перечисли их все в секции files.
  • Не злоупотребляй. Хелперы — это утилиты. Сложную бизнес-логику лучше выносить в сервис-классы или репозитории.
  • Альтернатива с сервис-провайдером. Можно зарегистрировать файл через AppServiceProvider в методе register(): require_once app_path('helpers.php');. Но вариант с Composer чище и быстрее.

Почему твой первый вариант не работал в Blade?

Файл app/helpers.php не загружается автоматически — Laravel не знает о его существовании. Без подключения через Composer или Service Provider функции доступны только если ты явно вызвал require_once в том же файле. Blade-шаблоны компилируются в PHP-файлы, которые не имеют доступа к твоему файлу.

После выполнения composer dump-autoload файл загружается глобально, и всё работает.

<<>>

Альтернативный подход: класс-хелпер с статическими методами

Если ты предпочитаешь ООП-стиль или хочешь сгруппировать функции по контексту, можно создать класс-хелпер.

Создаем класс

// app/Helpers/FormatHelper.php
<?php

namespace App\Helpers;

use Carbon\Carbon;

class FormatHelper
{
    public static function price($value, $decimals = 2): string
    {
        return number_format($value, $decimals, ',', ' ') . ' ₽';
    }

    public static function date($date, $format = 'd.m.Y'): string
    {
        if (!$date) return '';
        return Carbon::parse($date)->format($format);
    }
}

Регистрируем алиас (опционально)

Добавь в config/app.php в секцию 'aliases':

'FormatHelper' => App\Helpers\FormatHelper::class,

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

// В контроллере
use App\Helpers\FormatHelper;
// или через алиас
FormatHelper::price(1500.5);

// В Blade
{{ \App\Helpers\FormatHelper::price($product->price) }}

Плюсы и минусы

  • + Чистая ООП-структура, легко тестировать (можно замокать).
  • + IDE автодополнение работает отлично.
  • - В Blade приходится писать длинные вызовы или использовать алиасы.
  • - Не так лаконично, как простые функции.

Выбирай подход под свои задачи. Для простых утилит — функции, для сложной логики с зависимостями — классы.