600

I would like to create helper functions to avoid repeating code between views in Laravel. For example:

view.blade.php

<p>Foo Formated text: {{ fooFormatText($text) }}</p>

They're basically text formatting functions. How should I define globally available helper functions like fooFormatText()?

Paulo Boaventura
  • 1,365
  • 1
  • 9
  • 29
Calebe Oliveira
  • 6,111
  • 3
  • 14
  • 7

23 Answers23

761

Create a helpers.php file in your app folder and load it up with composer:

"autoload": {
    "classmap": [
        ...
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/helpers.php" // <---- ADD THIS
    ]
},

After adding that to your composer.json file, run the following command:

composer dump-autoload

If you don't like keeping your helpers.php file in your app directory (because it's not a PSR-4 namespaced class file), you can do what the laravel.com website does: store the helpers.php in the bootstrap directory. Remember to set it in your composer.json file:

"files": [
    "bootstrap/helpers.php"
]
miken32
  • 42,008
  • 16
  • 111
  • 154
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • 118
    Tip for noobs: use this command after changing composer.json. composer dump-autoload – Allfarid Morales García Jun 02 '15 at 22:44
  • 20
    @AllfaridMoralesGarcía Or perhaps just 'A useful tip, as the answer doesn't make it clear you need to do this afterwards'. – Matt McDonald Jun 09 '15 at 15:52
  • 11
    I approve of helper functions to make writing views easier but I hate how much this answer is referenced in other answers. Don't get me wrong, it's a good answer and correct, I just fear that people will abuse it and start writing tons of poorly written, poorly organized functional PHP again. – andrewtweber Oct 18 '15 at 21:02
  • I'm not sure why it's necessary to autoload the file individually - even in Laravel 4 this wasn't necessary. – heisian Nov 03 '15 at 02:04
  • 50
    I don't understand this approach. Composer is supposed to be a tool to include libraries: Laravel would work perfectly well without it, and Composer without Laravel. This suggestion tells us to create a file within our app, leave our app, go to Composer, tell composer to go back into our app and include a file. Laravel clearly handles the inclusion of files, right? Why would we forgo Laravel's native implementation and use this external tool to include a file for us, thus coupling our application to Composer more? Is it laziness, or am I missing something? – dKen Nov 18 '15 at 08:30
  • 10
    Laravel uses composer's autoloader to know where to include all the libraries and files it relies on. This referenced in bootstrap/autoload.php. Read the comment in that file. The approach is to add the reference to the file into the composer.json, then "dump autoload," which regenerates composer's autoloader so that Laravel can find it. Using Composer's "files" collection is a good way to add libraries or one-off function files that aren't neatly wrapped up in composer packages. It's nice to have a place for all the "by the way I have to include this one weird file" situations. – Phillip Harrington Nov 18 '15 at 16:55
  • 3
    Thanks @PhillipHarrington, makes sense to some degree. I still think that if it's possible to resolve this using a class file and either a line in Composer, or [a line in Laravel](http://stackoverflow.com/a/33776272/366529), one is more maintainable, less coupled and easier to understand than the other, especially for those who, for some reason, [don't like composer](http://stackoverflow.com/q/15940140/366529). Maybe it's a personal preference thing, but for some reason it makes me feel dirty :( – dKen Nov 20 '15 at 09:56
  • `"files": [ "app/helpers.php", "app/second.php" ]` - if I want to autoload more than one file, can I just keep appending like this ? – code-8 Mar 19 '16 at 00:02
  • You don't need to add files to composer.json for them to be autoloaded. Laravel's already got a built-in class loader: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php Just create a class file in a directory with a matching namespace and Laravel will automatically include the file/class in your project. You don't even need to run composer dump-autoload. Just use a `use` statement for the class where ever you need it. – heisian Apr 27 '16 at 09:47
  • @PhillipHarrington http://www.php-fig.org/psr/psr-4/ No need to mess with composer.json. A file with matching directory structure and namespace is enough for Laravel 5 to autoload your custom class. – heisian Apr 27 '16 at 09:48
  • Except the whole point of this helpers file is to be outside of a class scope. Also, Laravel is dependent on Composer. Natively, Laravel won't work without Composer. They are independent, but they're still coupled. I think adding a require statement in Laravel is a worse solution than in a composer.json because you know have things being loaded in multiple places, thus, less maintainable. – Kenyon Nov 23 '16 at 00:18
  • `Helpers.php` is more convenient than `helpers.php` – OverCoder Nov 27 '16 at 20:34
  • 1
    in laravel 5.3 they make a point of `app/` directory being a completely psr-4 autoloaded dir. Thats why they removed the `routes.php` to a separate folder outside of `app`. What should we do now? – Mubashar Abbas Mar 09 '17 at 09:52
  • 2
    @MubasharAbbas You answered your own question. Move your helpers into a different location outside of `app/` and point composer there instead. – David Barker Mar 22 '17 at 11:21
  • I was getting error message as not valid json. Then I removed the comments "// <---- ADD THIS" from "files" tag, then the command "composer dump-autoload" works fine. – M_Idrees Jul 13 '17 at 13:31
  • 1
    This is not a correct answer, this will work, but this is most incorrect approach a programmer could make to solve this problem. – Bartłomiej Sobieszek Oct 11 '17 at 10:15
  • I agree with @DavidBarker - this is not the correct answer. It is wrong to put this file in the app directory. This point is clearly evidenced by the fact that Taylor moved the routes file OUT of the app directory. – JamesG Jun 05 '18 at 07:38
  • Its surprising how a simple question like this could have generated several opinions that deviate from the question. The simple question "how to create...helper functions...in L5 style" How to do it the way its done on L5. Simple! Apart from not putting the helper file in `app` directory this is the simplest way to do it. There's no need for Facade/Static functions etc... – Oluwatobi Samuel Omisakin Sep 05 '18 at 06:22
  • Thanks your answer helped me. but just one question when I stored my helper file in bootstrap directory, composer dump-autoload gave me warnings and errors saying it can't find the path. I check twice, the path was correct. – codingbruh Oct 04 '18 at 14:17
  • @djangodude - Can you post two screenshots? One of your directory structure, the other of your `composer.json` autoload section. – Joseph Silber Oct 04 '18 at 14:26
  • This answer works, but gives [problems](https://stackoverflow.com/questions/55152340/netbeans-does-not-see-a-returning-type-of-a-custom-helper-functions-laravel-ph) to NetBeans users – Yevgeniy Afanasyev Mar 13 '19 at 22:54
  • I cannot stress how much that this is the wrong way to setup a helper. The correct way is to create a class and alias it (see answer below). However, if you have a helper that so complex that it needs to be it's own app create a laravel package seen here... https://laravel.com/docs/5.8/packages – Jed Lynch Apr 21 '19 at 13:56
  • Does it required to run composer dump-autoload everytime when helper.php changes? – Amitesh Bharti May 26 '20 at 13:02
  • link not working – giò Mar 18 '22 at 13:29
  • Based on the `laravel.com` git history (`git log -- bootstrap/helpers.php`), there has never been a `helpers.php` file in the `bootstrap` directory for that repository. – Jordan Pickwell Jul 25 '22 at 15:26
  • @JordanPickwell - Unfortunately, when the site was redesigned, all of the old history was lost. It was created as a brand new project. [Here's a link to the first commit](https://github.com/laravel/laravel.com/commit/000ea1f652bd38e648c4f42d978475fa1a7510c4) (you can see that it has no parents). That commit is from 2019, when the site was redesigned. – Joseph Silber Jul 27 '22 at 00:17
  • @JordanPickwell - [Here's a screenshot of that file](https://img001.prntscr.com/file/img001/Tpfvi7wlQMuOmoz65izfgA.png) from the archived repository for the old design. – Joseph Silber Jul 27 '22 at 01:10
482

Custom Classes in Laravel 5, the Easy Way

This answer is applicable to general custom classes within Laravel. For a more Blade-specific answer, see Custom Blade Directives in Laravel 5.

Step 1: Create your Helpers (or other custom class) file and give it a matching namespace. Write your class and method:

<?php // Code within app\Helpers\Helper.php

namespace App\Helpers;

class Helper
{
    public static function shout(string $string)
    {
        return strtoupper($string);
    }
}

Step 2: Create an alias:

<?php // Code within config/app.php

    'aliases' => [
     ...
        'Helper' => App\Helpers\Helper::class,
     ...

Step 3: Run composer dump-autoload in the project root

Step 4: Use it in your Blade template:

<!-- Code within resources/views/template.blade.php -->

{!! Helper::shout('this is how to use autoloading correctly!!') !!}

Extra Credit: Use this class anywhere in your Laravel app:

<?php // Code within app/Http/Controllers/SomeController.php

namespace App\Http\Controllers;

use Helper;

class SomeController extends Controller
{

    public function __construct()
    {
        Helper::shout('now i\'m using my helper class in a controller!!');
    }
    ...

Source: http://www.php-fig.org/psr/psr-4/

Why it works: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php

Where autoloading originates from: http://php.net/manual/en/language.oop5.autoload.php

jave.web
  • 13,880
  • 12
  • 91
  • 125
heisian
  • 6,127
  • 1
  • 17
  • 17
  • 52
    To be clear, this answer doesn't actually deal with helpers, which are global-namespaced functions. Instead, it encourages converting helpers to class methods. This is generally the best approach, but doesn't actually answer the question asked here, which is why other answers are so complex by comparison. – Dan Hunsaker Nov 18 '15 at 03:50
  • 1
    Function helper means it is available in Blade as well.How do you make this function available in blade? You cannot call Helper::prettyJason(parameters) in blade. – MaXi32 Jan 21 '16 at 16:55
  • 1
    @MaXi32 you could add the class under the `aliases` array in `app/config.php`: `'Helper' => App\Helpers\Helper::class,` Then you would be able to call `Helper::prettyJson();` in blade just fine. – heisian Apr 27 '16 at 09:56
  • @DanHunsaker edited to directly answer the question, and it's still the same simple approach. You can also just write your own custom blade directives: http://stackoverflow.com/questions/28290332/best-practices-for-custom-helpers-on-laravel-5#36888067 – heisian Apr 29 '16 at 00:38
  • 1
    @heisian while I agree this is the *correct* answer, it still doesn't actually give you access to *helpers*. That's all I was intending to point out to the previous commenter. I personally favor discontinuing use of helpers (which are, to be clear, global functions, rather than class methods) in favor of this approach, for all the reasons stated elsewhere on this page. (Though since the OP explicitly wanted a helper for their views, the Blade directive approach is, perhaps, even better for answering the *specific* question asked here.) – Dan Hunsaker Apr 30 '16 at 14:39
  • 1
    @DanHunsaker Well, here's the framework source for where helpers are defined: https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/helpers.php No namespacing, so this file is loaded somewhere in Laravel without the help of the `ClassLoader`.. so to extend these types of functions the way to do it would be as others have said is to do a manual `require` or `include`. I don't know though, some people's obsession is with being able to call `myGlobalFunction()` whereas my obsession is `VerySpecificClass::method()`.. I just think it encourages proper organization. – heisian May 02 '16 at 20:21
  • 2
    Yeah, I dug through the framework once and found where they pulled the helpers in. And again, I completely agree that methods of namespaced static classes are a much cleaner fit than what's being requested - or recommended - most of the time. The fact is, helpers aren't really The Laravel Way in the first place, but rather a holdover from CodeIgniter 2.x that still hasn't been phased out. So my pedantry about this approach not answering the OP exactly as asked is more an attempt to highlight the fact that you don't get helpers, but rather something better. – Dan Hunsaker May 04 '16 at 19:14
  • 1
    so perhaps an all-encompassing answer would say, hey, this is how you can create global helpers (w/ code examples), but there is actually a more "friendly" way to do things, and this is what I recommend instead. – heisian May 25 '16 at 19:58
  • This works well. But should it be /config/app.php not /app/config.php (Step 2) – P_95 Jul 29 '16 at 10:47
  • @heisian your alias definition should be `'Helper' => App\Helpers\Helper::class,` (ie quotes around the key but no quotes around the value) - or it will throw a `Class Helper does not exist` error – goredwards Dec 22 '16 at 23:03
  • This gives me an error:: Argument 1 passed to App\Helpers\Helper::shout() must be an instance of App\Helpers\string, string given. Something to do with scalar type hinting? – stef Apr 22 '17 at 18:35
  • This is the best answer but you don't even need to create an alias for this class, certainly not in 5.4 anyway. Create a class somewhere convenient for you, eg App/Libraries/Helper.php class Helper() { – omarjebari Jul 02 '17 at 13:34
  • Wouldn't that 'Use helper' throw an The use statement with non-compound name 'Helper' has no effect in... ? – FabioCosta Nov 30 '17 at 19:02
  • This answer was written for Laravel 5.1, feel free to propose any edits for the latest version.. I haven't used it yet. – heisian Dec 01 '17 at 01:59
  • finally find a way that can be used in blade – Evol Rof Jun 08 '18 at 15:27
  • 1
    This solution makes the most sense. Any application should work with in laravel framework, especially if you are a part of a team of developers. Composer.json should only change if you adding vendor libraries (and as few as possible should be added). Stitching a script to the composer.json file invites future developers to this pseudo app dumping ground that is not bound to any context with in the framework. I don't why that is the winning answer. That solution wouldn't make it through code review where I work. – Jed Lynch Dec 07 '18 at 18:24
  • 2
    For Laravel 8 (I tested on this version), just before the `composer dump-autoload`, you need to run : `php artisan config:cache` to clear the cache of the file config/app.php. Then it will work – Axel Paris Mar 04 '21 at 16:46
351

My initial thought was the composer autoload as well, but it didn't feel very Laravel 5ish to me. Laravel 5 makes heavy use of Service Providers, which bootstraps your application.

To start off, I created a folder in my app directory called Helpers. Then within the Helpers folder I added files for functions I wanted to add. Having a folder with multiple files allows us to avoid one big file that gets too long and unmanageable.

Next I created a HelperServiceProvider.php by running the artisan command:

php artisan make:provider HelperServiceProvider

Within the register method I added this snippet

public function register()
{
    foreach (glob(app_path().'/Helpers/*.php') as $filename){
        require_once($filename);
    }
}

lastly register the service provider in your config/app.php in the providers array

'providers' => [
    'App\Providers\HelperServiceProvider',
]

Now any file in your Helpers directory is loaded, and ready for use.

UPDATE 2016-02-22

There are a lot of good options here, but if my answer works for you, I went ahead and made a package for including helpers this way. You can either use the package for inspiration or feel free to download it with Composer as well. It has some built in helpers that I use often (but which are all inactive by default) and allows you to make your own custom helpers with a simple Artisan generator. It also addresses the suggestion one responder had of using a mapper and allows you to explicitly define the custom helpers to load, or by default, automatically load all PHP files in your helper directory. Feedback and PRs are much appreciated!

composer require browner12/helpers

Github: browner12/helpers

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Andrew Brown
  • 5,330
  • 3
  • 22
  • 39
  • 32
    for people who only have a few functions they need to add, the composer autoload is perfectly fine, but for those of us that may have a lot of helper functions, multiple file organization is a must. this solution is essentially what I did in L4 except I registered the files in my `start.php` file (which wasn't great, but served its purpose for the time). do you have another suggestion for loading multiple files? – Andrew Brown Feb 10 '15 at 19:52
  • 8
    If you have multiple files, add them all to your composer.json file. Adding even 5-10 lines there makes *way* more sense than what you have here. – Joseph Silber Feb 10 '15 at 21:36
  • i like it too . small files , just used when needed , i have no idea why i would have them all in one file or have to change composer each time i add a function to an app . – Rizerzero Mar 21 '15 at 15:56
  • 26
    I think this technique has a lot of merit. It's elegant and efficient because you don't have to remember to mess with the composer.json file every time you create a helper file. – impeto Mar 22 '15 at 16:44
  • 9
    Really good solution. The only thing I disagree is the way you add the files, I think should be a mapper instead, where we add the name of the file we want to load. Think on errors! if there is just one helper in one of the files that is failing, then you should remove all of them, or have the site broken till you solve it. – Pablo Ezequiel Leone Apr 17 '15 at 13:20
  • 4
    Do you use App\Providers namespace? How i call that helper from controller and view. Sorry, noob question. – Cengkaruk Jun 10 '15 at 11:01
  • using this method all of the helpers will be autoloaded, so you can simply call your function anywhere in your application. – Andrew Brown Jun 12 '15 at 00:14
  • I somewhat agree with this solution but not so wholly. But I do agree that loading non-class files need a framework-esque solution and this does it just fine. Other than loading helpers, not all libraries are classes (especially the old ones) so in case you have to load a non-class file then this is it. – enchance Jun 25 '15 at 15:33
  • 1
    @PabloEzequielLeoneSignetti How to add a mapper? Can you provide an example? – Christopher Jul 26 '15 at 12:44
  • This seems to work for me, I just had to use $this->app->basePath . '/app/Http/Helpers/*.php' in the glob() for that to work. app_path() wasn't defined in my case. – The Unknown Dev Oct 20 '15 at 15:53
  • 1
    I think manually including php files goes directly against what Laravel was designed to do. Please see my answer below for including custom classes as intended. – heisian Nov 03 '15 at 02:03
  • Actually sorry, meant no offense, but I tend to agree with @JosephSilber. The reason why is because usually you'd want these classes to be as loosely coupled with the framework as possible. Let's say one day you have to change your framework, you would want the helpers to work by themselves. With Composer, you don't need to modify a line. You don't want to write it "Too Laravel", though Laravel is a great framework of course. – Thomas Cheng Nov 14 '15 at 18:11
  • 2
    I think is a strange implementation. If you're winding up with so many helper functions that you need to split them into multiple files, I think you're creating way too many global functions. Creating a file per method is asinine, as is requiring every file pre-emptively. – MetalFrog Nov 16 '15 at 17:52
  • Ok so, based on all those comments, seems that each variant for this solution is good. If you write custom helper functions that makes use of Laravel Framework itself, it's better to do like @PabloEzequielLeoneSignetti says. But, if you are writing helper functions that can be used anywhere, maybe is better to do like Joseph Silber says, including it on the composer.json file. – Ricardo Vigatti Jan 11 '16 at 11:17
  • "do you have another suggestion for loading multiple files?" Yes, register your helper functions inside a file relating to your package like `Illuminate/Foundation/helpers.php` and correctly use Packages. Also instead of `glob` you should load the FileSystem from the container. – Ash Feb 01 '16 at 14:52
  • @AndrewBrown When you add the provider to the providers array it should be `App\Providers\HelperServiceProvider::class` not `App\Providers\HelperServiceProvider`, right? I'm trying this method but for some reason Laravel not recognize my functions :s – Gerard Reches Mar 21 '16 at 15:59
  • all that `::class` does is return a string of the class name, so you can do it that way, or just write the string in yourself. – Andrew Brown Mar 21 '16 at 16:01
  • Guys, this answer is essentially re-writing an already-made ClassLoader found in Laravel: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php There is no reason to re-write code that's already built into the framework. – heisian Apr 27 '16 at 10:04
  • Looks like this method is deprecated in new Laravel version... I try with Laravel 5.6 but I keep getting error "Class 'Helper' not found..." – despotbg Jun 14 '18 at 17:13
93

This is what is suggested by JeffreyWay in this Laracasts Discussion.

  1. Within your app/Http directory, create a helpers.php file and add your functions.
  2. Within composer.json, in the autoload block, add "files": ["app/Http/helpers.php"].
  3. Run composer dump-autoload.
Steve Lorimer
  • 27,059
  • 17
  • 118
  • 213
itsazzad
  • 6,868
  • 7
  • 69
  • 89
  • 23
    The helpers might not be HTTP-only. `app/helpers.php` or `app/Helpers/` seems to be a better place. – sepehr Dec 06 '15 at 06:55
  • 2
    What if we are on a shared server and dont have option to use `composer dump-autoload `? – user3201500 Feb 04 '16 at 18:36
  • @user3201500 that is another question and you may need to do manually if you want to follow the above answer. Or you can choose from other answers. And to manually reflect the `composer dump-autoload` you may follow this: http://developed.be/2014/08/29/composer-dump-autoload-laravel/ – itsazzad Feb 05 '16 at 01:53
67

Having sifted through a variety of answers on SO and Google, I still couldn't find an optimal approach. Most answers suggest we leave the application and rely on 3rd party tool Composer to do the job, but I'm not convinced coupling to a tool just to include a file is wise.

Andrew Brown's answer came the closest to how I think it should be approached, but (at least in 5.1), the service provider step is unnecessary. Heisian's answer highlights the use of PSR-4 which brings us one step closer. Here's my final implementation for helpers in views:

First, create a helper file anywhere in your apps directory, with a namespace:

namespace App\Helpers;

class BobFinder
{
    static function bob()
    {
        return '<strong>Bob?! Is that you?!</strong>';
    }
}

Next, alias your class in config\app.php, in the aliases array:

'aliases' => [
    // Other aliases
    'BobFinder' => App\Helpers\BobFinder::class
]

And that should be all you need to do. PSR-4 and the alias should expose the helper to your views, so in your view, if you type:

{!! BobFinder::bob() !!}

It should output:

<strong>Bob?! Is that you?!</strong>
Community
  • 1
  • 1
dKen
  • 3,078
  • 1
  • 28
  • 37
  • thanks for posting this. as @Dan-Hunsaker pointed out in my solution we still have not ended up with a globally-namespaced function, i.e. being able to write simply `{!! bob() !!}`. going to do some more searching and see if that is possible – heisian Nov 25 '15 at 19:43
  • 2
    I've thought about it more and attempting to make `bob()` truly global would not be a wise thing to do. Namespaces are there for a reason and we shouldn't be calling `bob()` alongside base PHP functions. I'll be adding your aliasing bit to my code - thanks! – heisian Nov 25 '15 at 19:56
  • 1
    I find this to be a the best of all – Jimmy Obonyo Abor Dec 09 '15 at 23:12
  • Why is there `extends Helper`? It doesn't seem necessary for me. – bernie Jan 21 '16 at 00:02
  • @bernie @user3201500 Sorry team, I had my own base helper class that all my helpers inherit from; the `extends Helper` is indeed not necessary. Thanks for the heads up. – dKen Feb 05 '16 at 09:01
  • i am not a huge fan of Facades and like to avoid them when possible, but if you are okay with them this is a very good solution as well. – Andrew Brown Feb 22 '16 at 23:03
  • 1
    @AndrewBrown Unfortunately almost every example in the Laravel docs uses facades, without any warnings or suggestions for when and when not to use them. It makes it very difficult for newcomers to Laravel to know they have an option to not use them, and what the impact of that is. – dKen Feb 23 '16 at 08:25
  • @AndrewBrown there are no Facades here - just php static methods. Essentially namespaced functions. I agree that Facades are a ridiculous nonstandard obfuscation though. – Rick Jolly Mar 09 '16 at 05:15
  • 1
    @AndrewBrown this is not a facade. This is PSR-4 autoloading. http://www.php-fig.org/psr/psr-4/ – heisian Apr 27 '16 at 09:49
  • @dKen Take a look at the Laravel source: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php Class-loading is already built into Laravel, that's how my and your answer works. – heisian Apr 27 '16 at 10:05
43

Custom Blade Directives in Laravel 5

Yes, there is another way to do this!

Step 1: Register a custom Blade directive:

<?php // code in app/Providers/AppServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

use Blade; // <-- This is important! Without it you'll get an exception.

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
     public function boot()
     {
         // Make a custom blade directive:
         Blade::directive('shout', function ($string) {
             return trim(strtoupper($string), '(\'\')');
         });

         // And another one for good measure:
         Blade::directive('customLink', function () {
             return '<a href="#">Custom Link</a>';
         });
     }
    ...

Step 2: Use your custom Blade directive:

<!-- // code in resources/views/view.blade.php -->

@shout('this is my custom blade directive!!')
<br />
@customLink

Outputs:

THIS IS MY CUSTOM BLADE DIRECTIVE!!
Custom Link


Source: https://laravel.com/docs/5.1/blade#extending-blade

Additional Reading: https://mattstauffer.co/blog/custom-conditionals-with-laravels-blade-directives


If you want to learn how to best make custom classes that you can use anywhere, see Custom Classes in Laravel 5, the Easy Way

Community
  • 1
  • 1
heisian
  • 6,127
  • 1
  • 17
  • 17
31

This is my HelpersProvider.php file:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    protected $helpers = [
        // Add your helpers in here
    ];

    /**
     * Bootstrap the application services.
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     */
    public function register()
    {
        foreach ($this->helpers as $helper) {
            $helper_path = app_path().'/Helpers/'.$helper.'.php';

            if (\File::isFile($helper_path)) {
                require_once $helper_path;
            }
        }
    }
}

You should create a folder called Helpers under the app folder, then create file called whatever.php inside and add the string whatever inside the $helpers array.

Done!

Edit

I'm no longer using this option, I'm currently using composer to load static files like helpers.

You can add the helpers directly at:

...
"autoload": {
    "files": [
        "app/helpers/my_helper.php",
        ...
    ]
},
...
Pablo Ezequiel Leone
  • 1,337
  • 17
  • 22
  • Are there any other reasons than performance to create a mapper instead of loading all the files in the directory with `glob()` as Andrew Brown wrote? If you want to be able to specify the files that you want to include, why not specify the files in the `composer.json` to autoload them as Joseph Silber wrote? Why do you prefer this solution? I'm not saying this is a bad solution, I'm just curious. – Pelmered Oct 30 '15 at 21:21
  • 3
    It's easier, with a mapped approach, to selectively enable/disable helpers if, for example, one of the helper files contains a breaking error. That said, mapping files in a service provider is not very different from doing so in `composer.json` except for two points - first, it keeps the map inside the application itself, rather than a metadata file; second, it doesn't require you to re-run `composer dump-autoload` every time you change the list of files to load. – Dan Hunsaker Nov 18 '15 at 03:56
  • No need for `include` or `require`, Laravel already has built-in PSR-4 autoloading: http://www.php-fig.org/psr/psr-4/ – heisian Apr 27 '16 at 09:58
  • 1
    using PSR-4 and composer won't allow you to switch on/off helpers. – Pablo Ezequiel Leone Apr 27 '16 at 14:22
  • @PabloEzequielLeone and how would I use it inside a controller or a blade file? This looks as the best option if you are concerned with not loading all the helpers for all the controllers everytime, but is not good for beginners in Laravel (like myself). – VinGarcia Sep 28 '17 at 15:32
20

Since OP asked for best practices, I think we're still missing some good advices here.

A single helpers.php file is far from a good practice. Firstly because you mix a lot of different kind of functions, so you're against the good coding principles. Moreover, this could hurt not only the code documentation but also the code metrics like Cyclomatic Complexity, Maintainability Index and Halstead Volume. The more functions you have the more it gets worse.

Code documentation would be ok using tools like phpDocumentor, but using Sami it won't render procedural files. Laravel API documentation is such a case - there's no helper functions documentation: https://laravel.com/api/5.4

Code metrics can be analyzed with tools like PhpMetrics. Using PhpMetrics version 1.x to analyze Laravel 5.4 framework code will give you very bad CC/MI/HV metrics for both src/Illuminate/Foundation/helpers.php and src/Illuminate/Support/helpers.php files.

Multiple contextual helper files (eg. string_helpers.php, array_helpers.php, etc.) would certainly improve those bad metrics resulting in an easier code to maintain. Depending on the code documentation generator used this would be good enough.

It can be further improved by using helper classes with static methods so they can be contextualized using namespaces. Just like how Laravel already does with Illuminate\Support\Str and Illuminate\Support\Arr classes. This improves both code metrics/organization and documentation. Class aliases could be used to make them easier to use.

Structuring with classes makes the code organization and documentation better but on the other hand we end up loosing those great short and easy to remember global functions. We can further improve that approach by creating function aliases to those static classes methods. This can be done either manually or dynamically.

Laravel internally use the first approach by declaring functions in the procedural helper files that maps to the static classes methods. This might be not the ideal thing as you need to re-declare all the stuff (docblocks/arguments).
I personally use a dynamic approach with a HelperServiceProvider class that create those functions in the execution time:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    /**
     * The helper mappings for the application.
     *
     * @var array
     */
    protected $helpers = [
        'uppercase' => 'App\Support\Helpers\StringHelper::uppercase',
        'lowercase' => 'App\Support\Helpers\StringHelper::lowercase',
    ];

    /**
     * Bootstrap the application helpers.
     *
     * @return void
     */
    public function boot()
    {
        foreach ($this->helpers as $alias => $method) {
            if (!function_exists($alias)) {
                eval("function {$alias}(...\$args) { return {$method}(...\$args); }");
            }
        }
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

One can say this is over engineering but I don't think so. It works pretty well and contrary to what might be expected. It does not cost relevant execution time at least when using PHP 7.x.

DevThiman
  • 920
  • 1
  • 9
  • 24
Paulo Freitas
  • 13,194
  • 14
  • 74
  • 96
17

For Custom Helper Libraries in my Laravel project, I have created a folder with name Libraries in my Laravel/App Directory and within Libraries directory, I have created various files for different helper libraries.

After creating my helper files I simply include all those files in my composer.json file like this

...
"autoload": {
        "classmap": [
            "database"
        ],
        "files": [
            "app/Libraries/commonFunctions.php"
        ],
        "psr-4": {
            "App\\": "app/"
        }
    },
...

and execute

composer dump-autoload
Jignesh Joisar
  • 13,720
  • 5
  • 57
  • 57
Akshay Khale
  • 8,151
  • 8
  • 50
  • 58
14

instead of including your custom helper class, you can actually add to your config/app.php file under aliases.

should be look like this.

 'aliases' => [ 
    ...
    ...
    'Helper' => App\Http\Services\Helper::class,
 ]

and then to your Controller, include the Helper using the method 'use Helper' so you can simply call some of the method on your Helper class.

eg. Helper::some_function();

or in resources view you can directly call the Helper class already.

eg. {{Helper::foo()}}

But this is still the developer coding style approach to be followed. We may have different way of solving problems, and i just want to share what i have too for beginners.

Kenneth Sunday
  • 865
  • 7
  • 14
12

Here's a bash shell script I created to make Laravel 5 facades very quickly.

Run this in your Laravel 5 installation directory.

Call it like this:

make_facade.sh -f <facade_name> -n '<namespace_prefix>'

Example:

make_facade.sh -f helper -n 'App\MyApp'

If you run that example, it will create the directories Facades and Providers under 'your_laravel_installation_dir/app/MyApp'.

It will create the following 3 files and will also output them to the screen:

./app/MyApp/Facades/Helper.php
./app/MyApp/Facades/HelperFacade.php
./app/MyApp/Providers/HelperServiceProvider.php

After it is done, it will display a message similar to the following:

===========================
    Finished
===========================

Add these lines to config/app.php:
----------------------------------
Providers: App\MyApp\Providers\HelperServiceProvider,
Alias: 'Helper' => 'App\MyApp\Facades\HelperFacade',

So update the Providers and Alias list in 'config/app.php'

Run composer -o dumpautoload

The "./app/MyApp/Facades/Helper.php" will originally look like this:

<?php

namespace App\MyApp\Facades;


class Helper
{
    //
}

Now just add your methods in "./app/MyApp/Facades/Helper.php".

Here is what "./app/MyApp/Facades/Helper.php" looks like after I added a Helper function.

<?php

namespace App\MyApp\Facades;

use Request;

class Helper
{
    public function isActive($pattern = null, $include_class = false)
    {
        return ((Request::is($pattern)) ? (($include_class) ? 'class="active"' : 'active' ) : '');
    }
}

This is how it would be called:
===============================

{!!  Helper::isActive('help', true) !!}

This function expects a pattern and can accept an optional second boolean argument.

If the current URL matches the pattern passed to it, it will output 'active' (or 'class="active"' if you add 'true' as a second argument to the function call).

I use it to highlight the menu that is active.

Below is the source code for my script. I hope you find it useful and please let me know if you have any problems with it.

#!/bin/bash

display_syntax(){
    echo ""
    echo "  The Syntax is like this:"
    echo "  ========================"
    echo "      "$(basename $0)" -f <facade_name> -n '<namespace_prefix>'"
    echo ""
    echo "  Example:"
    echo "  ========"
    echo "      "$(basename $0) -f test -n "'App\MyAppDirectory'"
    echo ""
}


if [ $# -ne 4 ]
then
    echo ""
    display_syntax
    exit
else
# Use > 0 to consume one or more arguments per pass in the loop (e.g.
# some arguments don't have a corresponding value to go with it such
# as in the --default example).
    while [[ $# > 0 ]]
    do
        key="$1"
            case $key in
            -n|--namespace_prefix)
            namespace_prefix_in="$2"
            echo ""
            shift # past argument
            ;;
            -f|--facade)
            facade_name_in="$2"
            shift # past argument
            ;;
            *)
                    # unknown option
            ;;
        esac
        shift # past argument or value
    done
fi
echo Facade Name = ${facade_name_in}
echo Namespace Prefix = $(echo ${namespace_prefix_in} | sed -e 's#\\#\\\\#')
echo ""
}


function display_start_banner(){

    echo '**********************************************************'
    echo '*          STARTING LARAVEL MAKE FACADE SCRIPT'
    echo '**********************************************************'
}

#  Init the Vars that I can in the beginning
function init_and_export_vars(){
    echo
    echo "INIT and EXPORT VARS"
    echo "===================="
    #   Substitution Tokens:
    #
    #   Tokens:
    #   {namespace_prefix}
    #   {namespace_prefix_lowerfirstchar}
    #   {facade_name_upcase}
    #   {facade_name_lowercase}
    #


    namespace_prefix=$(echo ${namespace_prefix_in} | sed -e 's#\\#\\\\#')
    namespace_prefix_lowerfirstchar=$(echo ${namespace_prefix_in} | sed -e 's#\\#/#g' -e 's/^\(.\)/\l\1/g')
    facade_name_upcase=$(echo ${facade_name_in} | sed -e 's/\b\(.\)/\u\1/')
    facade_name_lowercase=$(echo ${facade_name_in} | awk '{print tolower($0)}')


#   Filename: {facade_name_upcase}.php  -  SOURCE TEMPLATE
source_template='<?php

namespace {namespace_prefix}\Facades;

class {facade_name_upcase}
{
    //
}
'


#  Filename: {facade_name_upcase}ServiceProvider.php    -   SERVICE PROVIDER TEMPLATE
serviceProvider_template='<?php

namespace {namespace_prefix}\Providers;

use Illuminate\Support\ServiceProvider;
use App;


class {facade_name_upcase}ServiceProvider extends ServiceProvider {

    public function boot()
    {
        //
    }

    public function register()
    {
        App::bind("{facade_name_lowercase}", function()
        {
            return new \{namespace_prefix}\Facades\{facade_name_upcase};
        });
    }

}
'

#  {facade_name_upcase}Facade.php   -   FACADE TEMPLATE
facade_template='<?php

namespace {namespace_prefix}\Facades;

use Illuminate\Support\Facades\Facade;

class {facade_name_upcase}Facade extends Facade {

    protected static function getFacadeAccessor() { return "{facade_name_lowercase}"; }
}
'
}


function checkDirectoryExists(){
    if [ ! -d ${namespace_prefix_lowerfirstchar} ]
    then
        echo ""
        echo "Can't find the namespace: "${namespace_prefix_in}
        echo ""
        echo "*** NOTE:"
        echo "           Make sure the namspace directory exists and"
        echo "           you use quotes around the namespace_prefix."
        echo ""
        display_syntax
        exit
    fi
}

function makeDirectories(){
    echo "Make Directories"
    echo "================"
    mkdir -p ${namespace_prefix_lowerfirstchar}/Facades
    mkdir -p ${namespace_prefix_lowerfirstchar}/Providers
    mkdir -p ${namespace_prefix_lowerfirstchar}/Facades
}

function createSourceTemplate(){
    source_template=$(echo "${source_template}" | sed -e 's/{namespace_prefix}/'${namespace_prefix}'/g' -e 's/{facade_name_upcase}/'${facade_name_upcase}'/g' -e 's/{facade_name_lowercase}/'${facade_name_lowercase}'/g')
    echo "Create Source Template:"
    echo "======================="
    echo "${source_template}"
    echo ""
    echo "${source_template}" > ./${namespace_prefix_lowerfirstchar}/Facades/${facade_name_upcase}.php
}

function createServiceProviderTemplate(){
    serviceProvider_template=$(echo "${serviceProvider_template}" | sed -e 's/{namespace_prefix}/'${namespace_prefix}'/g' -e 's/{facade_name_upcase}/'${facade_name_upcase}'/g' -e 's/{facade_name_lowercase}/'${facade_name_lowercase}'/g')
    echo "Create ServiceProvider Template:"
    echo "================================"
    echo "${serviceProvider_template}"
    echo ""
    echo "${serviceProvider_template}" > ./${namespace_prefix_lowerfirstchar}/Providers/${facade_name_upcase}ServiceProvider.php
}

function createFacadeTemplate(){
    facade_template=$(echo "${facade_template}" | sed -e 's/{namespace_prefix}/'${namespace_prefix}'/g' -e 's/{facade_name_upcase}/'${facade_name_upcase}'/g' -e 's/{facade_name_lowercase}/'${facade_name_lowercase}'/g')
    echo "Create Facade Template:"
    echo "======================="
    echo "${facade_template}"
    echo ""
    echo "${facade_template}" > ./${namespace_prefix_lowerfirstchar}/Facades/${facade_name_upcase}Facade.php
}


function serviceProviderPrompt(){
    echo "Providers: ${namespace_prefix_in}\Providers\\${facade_name_upcase}ServiceProvider,"
}

function aliasPrompt(){
    echo "Alias: '"${facade_name_upcase}"' => '"${namespace_prefix_in}"\Facades\\${facade_name_upcase}Facade'," 
}

#
#   END FUNCTION DECLARATIONS
#


###########################
## START RUNNING SCRIPT  ##
###########################

display_start_banner

init_and_export_vars
makeDirectories 
checkDirectoryExists
echo ""

createSourceTemplate
createServiceProviderTemplate
createFacadeTemplate
echo ""
echo "==========================="
echo "  Finished TEST"
echo "==========================="
echo ""
echo "Add these lines to config/app.php:"
echo "----------------------------------"
serviceProviderPrompt
aliasPrompt
echo ""
kuttumiah
  • 525
  • 1
  • 11
  • 19
Dash
  • 317
  • 4
  • 4
9

Create custom helpers directory

  • First create Helpers directory in app directory

Create helper class definition

  • Create a simple helper function that will concatenate two strings

  • Create a new file MyFuncs.php in /app/Helpers/MyFuncs.php and add the following code:

    <?php
    
    namespace App\Helpers; // defines the Helpers namespace under App namespace.
    
    class MyFuncs { // defines the helper class MyFuncs.
    
        // Defines a static function that accepts two string parameters and returns a concatenated string
        public static function full_name($first_name,$last_name) {
            return $first_name . ', '. $last_name;   
        }
    }
    

Service providers are used to auto load classes. We will need to define a service provider that will load all of our helper classes in /app/Helpers directory.

Run the following artisan command:

php artisan make:provider HelperServiceProvider

The file will be created in /app/Providers/HelperServiceProvider.php. Open /app/Providers/HelperServiceProvider.php and add the following code:

<?php 

namespace App\Providers; // defines the namespace provider 

use Illuminate\Support\ServiceProvider; // imports the ServiceProvider class namespace
// defines a class HelperServiceProvider that extends the ServiceProvider class
class HelperServiceProvider extends ServiceProvider {

   /**
    * Bootstrap the application services.
    *
    * @return void
    */
   public function boot()
   {
      //
   }

   /**
    * Register the application services.
    *
    * @return void
    */
   public function register()
   {    // loops through all the files in /app/Helpers directory and loads them.
        foreach (glob(app_path().'/Helpers/*.php') as $filename){
            require_once($filename);
        }
   }
}

We now need to register the HelperServiceProvider and create an alias for our helpers.

Open /config/app.php file

Locate the providers array variable

Add the following line

App\Providers\HelperServiceProvider::class,

Locate the aliases array variable

Add the following line

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

Save the changes using our custom helper.

We will create a route that will call our custom helper function, open /app/routes.php

Add the following route definition

Route::get('/func', function () {
    return MyFuncs::full_name("John","Doe");
});

Here:

return MyFuncs::full_name("John","Doe"); calls the static function full_name in MyFuncs class
matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Mizanur Rahman
  • 336
  • 4
  • 6
8

**

  • Status Helper

** create new helper

<?php

namespace App\Helpers;

use Illuminate\Database\Eloquent\Collection;

class StatusHelper
{
 protected static $_status = [
        1=> [
            'value' => 1,
            'displayName' => 'Active',
        ],
        2 => [
            'value' => 2,
            'displayName' => 'Inactive',
        ],
        3 => [
            'value' => 3,
            'displayName' => 'Delete',
        ],

    ];

     public static function getStatusesList()
    {
        $status = (new Collection(self::$_status))->pluck('displayName', 'value')->toArray();


        return $status;
    }
}

Use for the controller and any view file

use App\Helpers\StatusHelper;

class ExampleController extends Controller
{
        public function index()
        {
            $statusList = StatusHelper::getStatusesList();

            return view('example.index', compact('statusList'));
        }
}
Sunil
  • 175
  • 1
  • 9
7

First create helpers.php inside App\Http directory. Then add the following code inside the composer.json

"autoload": {
        "classmap": [
            "database"
        ],
        "files": [
            "app/Http/helpers.php"
        ],
        "psr-4": {
            "App\\": "app/"
        }
    },

Next run the following command

composer dump-autoload

Now you can define your custom function inside the helpers.php file.

Flexo
  • 87,323
  • 22
  • 191
  • 272
ujjal
  • 225
  • 4
  • 8
7

Create Helpers.php in app/Helper/Helpers.php

namespace App\Helper
class Helpers
{


}

Add in composer and composer update

 "autoload": {
        "classmap": [
            "database/seeds",
            "database/factories",
            "database","app/Helper/Helpers.php"
        ],
        "psr-4": {
            "App\\": "app/"
        },
         "files": ["app/Helper/Helpers.php"]
    },

use in Controller

use App\Helper\Helpers

use in view change in config->app.php file

   'aliases' => [
    ...
    'Helpers'   => 'App\Helper\Helpers'
    ],

call in view

<?php echo Helpers::function_name();  ?>
abhishek kumar
  • 448
  • 4
  • 10
  • Thank you, would you mind expanding a bit on your explaination? – Felipe Valdes Nov 29 '17 at 19:05
  • 2
    If the class is namespaced, adding the file in `composer.json` is useless, since psr-4 autoload will do the job. – Arcesilas Apr 26 '18 at 14:32
  • @abhishekkumar - any suggestion for Lumen 8.0. Thanks in advance. – Kamlesh Apr 29 '21 at 13:47
  • I have tried same solution for the Lumen 8 but getting error "Fatal error: Cannot declare class MasterFunctionsHelper, because the name is already in use in /Applications/MAMP/htdocs/laravelprojects/project_api/app/Helpers/MasterFunctionsHelper.php on line 3" – Kamlesh Apr 29 '21 at 13:52
  • @Kamlesh namespace problem, this link will help you https://stackoverflow.com/questions/40406418/cannot-declare-class-controller-because-the-name-is-already-in-use/40406578 – abhishek kumar Apr 30 '21 at 08:20
5

Best Practice to write custom helpers is

1) Inside the app directory of the project root, create a folder named Helpers (Just to separate and structure the code).

2) Inside the folder write psr-4 files or normal php files

If the PHP files are in the format of psr-4 then it will be auto loaded, else add the following line in the composer.json which is inside the project root directory

Inside the autoload key, create a new key named files to load files at the time of auto load,inside the files object add the path starting from app directory., here is an example.

"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/Helpers/customHelpers.php"
    ]
},
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php"
    ]
},

PS : try running composer dump-autoload if the file dosen't loaded.

Reiah Paul Sam
  • 555
  • 6
  • 16
4

Another Way that I used was: 1) created a file in app\FolderName\fileName.php and had this code inside it i.e

<?php
namespace App\library
{
 class hrapplication{
  public static function libData(){
   return "Data";
  }
 }
}
?>

2) After that in our blade

 $FmyFunctions = new \App\FolderName\classsName;
  echo $is_ok = ($FmyFunctions->libData());

that's it. and it works

Dee
  • 91
  • 1
  • 11
2

I know it is very late to answer this but, this issue is happening with all junior developers everyday, so for straight steps do the following:

** group your helper functions into classes (to use the functions in the blade just make them static) & put all classes in the config Laravel folder app.php aliases

'aliases' => [
  "YourClassName" => App\Support\YourClassName,
]

Now you can use all your static functions all over the blades and controllers too.

Astro
  • 641
  • 2
  • 6
  • 13
1

in dir bootstrap\autoload.php

require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/../app/Helpers/function.php'; //add

add this file

app\Helpers\function.php
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
panqingqiang
  • 167
  • 1
  • 2
0

In Laravel 5.3 and above, the Laravel team moved all procedural files (routes.php) out of the app/ directory, and the entire app/ folder is psr-4 autoloaded. The accepted answer will work in this case but it doesn't feel right to me.

So what I did was I created a helpers/ directory at the root of my project and put the helper files inside of that, and in my composer.json file I did this:

...
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "helpers/ui_helpers.php"
    ]
},
...

This way my app/ directory is still a psr-4 autoloaded one, and the helpers are a little better organized.

halfer
  • 19,824
  • 17
  • 99
  • 186
Mubashar Abbas
  • 5,536
  • 4
  • 38
  • 49
0

There are some great answers here but i think this is the simplest. In Laravel 5.4 (and prob earlier versions too) you can create a class somewhere convenient for you, eg App/Libraries/Helper.php

class Helper() {
    public function uppercasePara($str) {
        return '<p>' .strtoupper($str). '<p>;
    }
}

Then you can simply call it in your Blade template like this:

@inject('helper', \App\Libraries\Helper)
{{ $helper->drawTimeSelector() }}

If you don't want to use @inject then just make the 'uppercasePara' function as static and embed the call in your Blade template like this:

{{ \App\Libraries\Helper::drawTimeSelector() }}

No need for aliases. Laravel resolves the concrete class automatically.

omarjebari
  • 4,861
  • 3
  • 34
  • 32
0

First Of All Create Your Helper File/Class at App\Helpers\Helper.php which is like:

<?php

namespace App\Helpers;

class Helper {

    // Your customer public function
}

And Then Define it in Composer.json At Auto-load And then run composer dump-autoload

ruleboy21
  • 5,510
  • 4
  • 17
  • 34
-2

Create new file examplehelper.php in App/Helpers/ and then add in composer.json file

"autoload": { "classmap": [ "database"], "psr-4": { "App\\": "app/" },
"files": ["helpers/examplehelper.php" ]},
buddemat
  • 4,552
  • 14
  • 29
  • 49
Faran
  • 138
  • 6
  • 4
    This is very similar to the solution in the accepted answer. When answering older questions that already have answers, please make sure you provide either a novel solution or a significantly better explanation than existing answers. – Eric Aya Aug 31 '21 at 11:29