Создание собственных функций помощников
Laravel предоставляет множество удобных вспомогательных глобальных функций, которые облегчают работу с массивами, путями к файлам, строками и маршрутами, а также любимая всеми функция dd()
.
Вы также можете создавать свой собственный набор вспомогательных функций для ваших приложений Laravel и PHP-пакетов, используя Composer для их автоматического импорта.
Давайте рассмотрим процесс создания собственных глобальных функций, которые будут автоматически загружаться Laravel.
Создание файла
Первое, где вы могли бы захотеть использовать ваши вспомогательные функции, это в контексте приложения Laravel. В зависимости от ваших предпочтений, вы можете организовать расположение ваших файлов с вспомогательными функциями так, как вам удобно. Например:
app/helpers.php
app/Http/helpers.php
Я предпочитаю хранить мои в app/helpers.php
в корне пространства имен приложения.
Автоматическая загрузка
Чтобы использовать ваши вспомогательные функции PHP, вам нужно загрузить их в во время выполнения. В начале моей карьеры было распространено использование такого кода в начале файла:
require_once ROOT . '/helpers.php';
Сейчас у нас есть гораздо лучшее решение – Composer. Если вы создадите новый проект Laravel, вы увидите ключи autoload
и autoload-dev
в файле composer.json
:
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
Если вы хотите добавить файл с вспомогательными функциями, Composer предоставляет ключ files
(который является массивом путей к файлам), который вы можете определить внутри autoload
:
"autoload": {
"files": [
"app/helpers.php"
],
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
После добавления нового пути в массив files
, вам нужно обновить автозагрузчик:
composer dump-autoload
Теперь файл helpers.php будет загружаться автоматически при каждом запросе, потому что Laravel использует автозагрузчик Composer в public/index.php
:
require __DIR__.'/../vendor/autoload.php';
Определение функций
Определение функций в вашем файле – это простая часть, хотя есть несколько моментов, на которые стоит обратить внимание. Все файлы с вспомогательными функциями Laravel обернуты в условие, чтобы избежать коллизий при определении функций:
if (! function_exists('env')) {
function env($key, $default = null) {
// ...
}
}
Я предпочитаю использовать проверки function_exists
в моих вспомогательных приложениях, но если вы определяете вспомогательные функции в контексте вашего приложения, вы можете пропустить проверку function_exists
.
Пример вспомогательной функции
Мне нравятся функции путей и URL из Rails, которые вы получаете при определении ресурсного маршрута. Например, маршрут photos
предоставит функции new_photo_path
, edit_photo_path
и т. д.
Когда я использую ресурсный маршрутизатор в Laravel, мне нравится добавить несколько вспомогательных функций, которые облегчают определение маршрутов в моих шаблонах. В моей реализации мне нравится иметь функцию которой могу передать модель модель Eloquent и получить обратно URL, например:
create_route($model);
edit_route($model);
show_route($model);
destroy_route($model);
Вот как вы могли бы определить show_route
в файле app/helpers.php
(остальные будут выглядеть похожим образом):
if (! function_exists('show_route')) {
function show_route($model, $resource = null)
{
$resource = $resource ?? plural_from_model($model);
return route("{$resource}.show", $model);
}
}
if (! function_exists('plural_from_model')) {
function plural_from_model($model)
{
$plural = Str::plural(class_basename($model));
return Str::kebab($plural);
}
}
Функция plural_from_model()
– это просто повторяющия функция которую используют другие функции маршрутов для предсказания имени маршрута на основе kebab-case от множественного числа имени модели.
Например, вот пример имени ресурса, полученный из модели:
$model = new App\LineItem;
plural_from_model($model);
// => line-items
plural_from_model(new App\User);
// => users
Используя это соглашение, вы можете определить ресурсный маршрут следующим образом в routes/web.php
:
Route::resource('line-items', 'LineItemsController');
Route::resource('users', 'UsersController');
Затем в шаблонах Blade вы могли бы сделать следующее:
<a href="{{ show_route($lineItem) }}">
{{ $lineItem->name }}
</a>
Что приведет к созданию примерно такого HTML:
<a href="http://localhost/line-items/1">
Line Item #1
</a>
Пакеты
Ваши пакеты также могут использовать файл с вспомогательными функциями, которые вы хотите сделать доступными для проектов, использующих ваш пакет.
Вы будете использовать тот же подход в файле composer.json
пакета, определяя ключ files
с массивом ваших файлов с вспомогательными функциями.
Очень важно добавить проверки
function_exists()
вокруг ваших вспомогательных функций, чтобы проекты, использующие ваш код, не ломались из-за коллизий имен.
Вам следует выбирать подходящие имена функций, уникальные для вашего пакета, и рассмотреть возможность использования короткого префикса, если вы боитесь, что имя вашей функции слишком общее.
Узнать больше
Ознакомьтесь с документацией по автозагрузке Composer, чтобы узнать больше о включении файлов и общей информации об автозагрузке классов.