Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overwrite laravel 5 helper function

I'm using the response() helper very often and I just return the data with a message to the user. Now I have to include the http status code as well, but I don't want to change every response (which is likely bad anyway).

So I'm trying to overwrite the response() helper function by creating my own helpers.php within app/Http/helpers.php.

When I add it to my composer files, it does autoload the current helpers.php from the framework first and when I add it before the autload include in bootstrap/global.php I wont be able to use the app() and other Laravel functions.

How would I be able to solve this issue? I just want to include the status code as well in the response array.

like image 643
guidsen Avatar asked Feb 12 '15 10:02

guidsen


Video Answer


4 Answers

All Laravel helper functions written with this logic

if ( ! function_exists('response'))
{
    function response($content = '', $status = 200, array $headers = array())
    {
         // function body
    }
}

for first Laravel check is this function exists, if it exists, Laravel will not define this function again(otherwise it will throw fatal error). So if you will define your function before autoloader include vendor/laravel/framework/src/Illuminate/Foundation/helpers.php file, you can define your custom response function.

Unfortunately there is no way to say composer load first your autoload.files section, then laravel autoload.files. But you can do small hack ...

open bootstrap/autoload.php file and include your file before autoloader

// file with your custom helper functions
require __DIR__.'/../app/app/Http/helpers.php'; 
require __DIR__.'/../vendor/autoload.php';
like image 164
Marty Aghajanyan Avatar answered Oct 20 '22 13:10

Marty Aghajanyan


In Laravel 5.5+ laravel doesn't have bootstrap/autoload.php and you must use a package like https://github.com/funkjedi/composer-include-files

how to do it:

first run command

composer require funkjedi/composer-include-files

then add your helper functions file path in composer.json

{
    "extra": {
        "include_files": [
            "/path/to/file/you/want/to/include",
            "/path/to/another/file/you/want/to/include"
        ]
    },
}

then just do

composer dump-autoload
like image 38
Mahdi mehrabi Avatar answered Oct 20 '22 13:10

Mahdi mehrabi


I've just had to do this in order to override the now() helper so I can control the apparent time when running tests. I followed the regular advice of creating app/Http/helpers.php and then adding it to bootstrap/autoload.php like so:

require __DIR__.'/../app/Http/helpers.php'; // added
require __DIR__.'/../vendor/autoload.php';

This usually works because as Marty says, all helpers are only defined if there's not an existing function with that name. So the two lines above load your custom helpers, then perform all vendor autoloading, which includes Laravel's helpers, and your already-defined function takes precedence.

But unfortunately, autoload.php doesn't seem to be used when testing with Behat, which is what I'm using. So I needed an alternative solution. Long story short, the only easy way to ensure that files get autoloaded before vendor files is by using the https://github.com/funkjedi/composer-include-files package. To quote from its readme:

In the past simply modifying bootstrap/autoload.php to include helpers was sufficient. However new versions of PHPUnit include the Composer Autoloader prior to executing the PHPUnit bootstrap file. Consequently this method of overriding helpers is no longer viable as it will trigger a fatal error when your bootstrap file is included.

So I installed this package using composer require funkjedi/composer-include-files and then added this to composer.json:

"extra": {
    "include_files": [
        "app/Http/helpers.php"
    ]
},

Once that's done, run composer dump-autoload to regenerate the autoload files. Now the overrides work both during regular app operation, and when running tests!

like image 29
Daniel Buckmaster Avatar answered Oct 20 '22 12:10

Daniel Buckmaster


I'm not going to directly answer your question since I don't know if there's a solution (without changing Laravels helpers.php or renaming your function)

However there is a solution from the framework for this common use case. Response Macros

You can define a macro (this is done in a service provider)

Response::macro('foo', function($value){
    // do some stuff
    return Response::make($value);
});

And you can use it like this:

return response()->foo('bar');
like image 23
lukasgeiter Avatar answered Oct 20 '22 14:10

lukasgeiter