Creating your own PHP functions in a Laravel project
Laravel has a lot of great features that make working with arrays, paths, lines, routes, and other things easy — like a favorite feature, for example dd()
.
You can create your own functions for your Laravel application and PHP package, using Composer to automatically import them.
If you are new to Laravel or PHP, let's go through the whole process of creating your own PHP functions that will be automatically loaded into Laravel.
Creating a function file in Laravel
First, you must include functions in the context of your Laravel application. Depending on your preferences, you can organize the storage of your files with functions wherever you want, here are a few suggested places:
app/helpers.php
app/Http/helpers.php
I prefer to store them like that app/helpers.php
in the root of the application namespace.
Autoload
To use your functions, you need to load them into runtime (application life cycle). At the beginning of my career, I often saw this code at the beginning of the file:
require_once ROOT . '/helpers.php';
PHP functions cannot be loaded automatically. However, we have a better solution using Composer than using require
or require_once
.
If you create a new project Laravel, you will see the parameters autoload
and autoload-dev
in the file composer.json
:
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
If we want to add our own file with functions, then in Composer there is a parameter for this files
(which consists of an array of file paths) that you can define inside the parameter autoload
:
"autoload": {
"files": [
"app/helpers.php"
],
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
When you added a new path to the parameter files
, you need to update the autoloader by doing:
composer dump-autoload
Now, with each request, the file helpers.php
will be loaded automatically since Laravel loads the Composer auto-loader into public/index.php
:
require __DIR__.'/../vendor/autoload.php';
Function Definition
Defining functions is not a difficult task, although there are a few caveats. All functions in Laravel are wrapped with a special check that eliminates the possibility of collisions:
if (! function_exists('env')) {
function env($key, $default = null) {
// ...
}
}
Although there may be a catch, because we can execute a function in a situation when it has already been defined, before we assigned it.
I prefer to use function_exists
to test my functions, but if you assign a function in the context of your application, you can refuse function_exists
to check.
By skipping the check, you will see a collision always when your function redefines another, this can be useful.
In practice, collisions do not occur as often as you might think, but you must be sure that the name of your function is not too general. In addition, you can add a prefix to the name of your function, which will reduce the chance of collisions.
Function Examples
I always liked how RoR (Ruby on Rails) made functions for paths and links if you defined a resource path. For example, the resource photos
will be added functions new_photo_path
, edit_photo_path
etc.
When I use resource routing in Laravel, I add a few functions that make it easy to work with routes in templates. In my implementation, I add functions to which I pass the Eloquent model and which return the route to the resource, for example:
create_route($model);
edit_route($model);
show_route($model);
destroy_route($model);
This shows how you can define a function show_route
in your file app/helpers.php
(others will look like):
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);
}
}
A function plural_from_model()
is just code that helps you get the name of a resource based on naming conventions.
For example, here we get the name of the resource based on the model:
$model = new App\LineItem;
plural_from_model($model);
=> line-items
plural_from_model(new App\User);
=> users
Using these conventions, you can define routes for resources in a file routes/web.php
:
Route::resource('line-items', 'LineItemsController');
Route::resource('users', 'UsersController');
After that, in your template, you can use the functions like this:
{{ $lineItem->name }}
And at the output you get the following HTML code:
Line Item #1
Packages
Your Composer packages can also use your function file, for any functions that you want to make available, your package is used in the project.
You will use the same approach for the file composer.json
, defining the parameter files
as an array of your function files.
Be sure to add function_exists()
your function to the test so that the project using your code does not break due to name collisions.
You should use the correct names for your functions, which will be unique, you should also consider using a short prefix if you are afraid that the name of your functions is too general.