В Laravel есть много отличных функций которые упрощают работу с массивами, путями, строками, маршрутами, и прочими вещами — например любимая функция dd()
.
Вы можете создать и свои собственные функции для вашего Laravel приложения и PHP пакета, используя Composer для автоматического импорта их.
Если вы новичок в Laravel или PHP давайте пройдемся по всему процессу создания собственных PHP функций которые будут автоматически подгружаться в Laravel'ом.
Создание файла с функциями в Laravel
Для начала вы должны включить функции в контекст вашего Laravel приложения. В зависимости от ваших предпочтений, вы можете организовать хранение ваших файлов с функциями там где вы хотите, вот несколько предложеных мест:
app/helpers.php
app/Http/helpers.php
Я предпочитаю хранить их так app/helpers.php
в корне пространства имен приложения.
Автозагрузка
Для использования ваших функций, вам нужно загрузить их в рантайм (жизненный цикл приложения). В начале моей карьеры я часто видел этот код в начале файла:
require_once ROOT . '/helpers.php';
PHP функции не могут автоматически подгружаться. Однако, у нас есть более лучшее решение с использованием Composer нежели использование require
или require_once
.
Если вы создадите новый 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
для проверки.
Пропустив проверку вы увидите коллизию всегда когда ваша функция будет переопределять другую, это может быть полезно.
На практике, коллизии происходят не так часто как можно подумать, но вы должны быть уверены в том что название вашей функции не слишком общее. В дополнение вы можете добавить префикс в название вашей функции что понизит шанс коллизий.
Примеры функций
Мне всегда нравилось как в RoR (Ruby on Rails) сделаны функции для путей и ссылок если вы определили маршрут ресурса. К примеру, для ресурса photos
будут добавлены функции new_photo_path
, edit_photo_path
, и т.д.
Когда я использую ресурсную маршрутизацию в Laravel, я добавляю несколько функций которые упрощают работу с марщрутами в шаблонах. В моей реализации я добавляю функции которым я передаю Eloquent модель и которые возвращают маршрут на ресурс, например:
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()
это всего лишь код который помогает получить имя ресурса основываясь на соглашениях именования.
Например, тут мы получаем имя ресурса на основе модели:
$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');
После этого в вашем шаблоне вы можете использовать функции так:
<a href="{{ show_route($lineItem) }}">
{{ $lineItem->name }}
</a>
И на выходе вы получите такой HTML код:
<a href="http://localhost/line-items/1">
Line Item #1
</a>
Пакеты
Ваши Composer пакеты могут также использовать ваш файл с функциями, для любых функций которые вы хотите сделать доступными, в проекте используемый ваш пакет.
Вы будете использовать тотже подход для файла composer.json
, определяя параметр files
как массив ваших файлов с функциями.
Обязательно добавьте function_exists()
в проверку вашей функции для того чтобы проект использующий ваш код не поломался из-за колизий имен.
Вы должны использовать правильные имена для ваших функций, которые будут уникальными, так же стоит подумать о использовании короткого префикса, если вы боитесь что название ваших функций слишком общее.
Комментарии (6)
VolCh
10.12.2017 23:00И неймспейсы для функций поддерживаются.
А вот про приоритет загрузки было бы интересно узнать. Как, например, загрузить свою функцию гарантированно до ларавеловской, как бы переопределить её.
Asikk
11.12.2017 11:20А почему не использовать класс-хелперы со статическими методами? Экономим несколько байт кода?
ZloAdmin Автор
11.12.2017 11:22Я думаю потому что глобальные функции в шаблоне будут выглядеть лучше.
ellrion
11.12.2017 11:49такие функции за счет объявления с использованием function_exists можно перекрыть например временно для чего то. просто объявив свою такую функцию чуть раньше. Ну и плюс это типо ларавель вэй.
Rpsl
11.12.2017 12:19browner12/helpers пакет который берет все подключение на себя, позволяет генерировать хелперы через artisan и подключать из через конфиг.
Samouvazhektra
На самом деле таким образом хелперы можно добавлять в любой проект под композером, хоть в Yii, хоть без фрейма, так что Laravel тут ни при чём.
Но важно с ними не переборщить!