[Guest post] Why I Decided To Embrace Laravel – Oleksii Rytov

Reading Time: 8 minutes

Over the last year, I took part in three large projects. My task was to move away from the old architecture based on PHP and server-side HTML generation, and transition to REST API.

With the old approach, back-end developers were expected to know much more about the UI and visual aspects of the application. Because of this, they had to pay attention to different segments of the application, instead of focusing on their primary objective. Having the back-end API strictly separated from the UI allowed our developers to focus on the quality of their code.

Also, testing API services is much easier as REST API can be verified by automated unit testing.

I’ve had some experience in writing my own framework, as well as working with Yii, CakePHP, CodeIgniter, Slim Framework, Symfony and few other open source frameworks. Each time, I’ve experienced a lack of functionality or awkward approach to some problems.

I used Laravel for four months before deciding to choose it as the platform for our next project. The project itself was a great success and this article is a product of this experience. Now I am able to call myself a Laravel developer.

 

Why I Chose Laravel

I’ve already outlined some of my reasons for using Laravel and my experience, so let’s take a closer look at what made Laravel a better choice for my latest project:

  • Quick and functional core that can be extended
  • Clean and simple routing
  • Effective ORM and database layer
  • Easy integration with third-party libraries (AWS, export libs, etc.). You can use Composer or Packagist to include libraries in your project
  • Active and growing community that can provide quick support and answers
  • Supporting unit tests out of the box
  • Async queue and background jobs for the long running tasks

 

Laravel Core And Routing

The Laravel kernel is hosted on GitHub. The kernel implements an IoC pattern allowing customization and rewriting of any part of the framework (request, logging, authentication, etc.).

Laravel designers didn’t spend too much time reinventing the wheel. A lot of solutions and practices are transferred from other frameworks. A good example of this approach is the extended Symfony console called Artisan, which is a command-line interface included with Laravel.

 

Routing

Routing in Laravel is amazing; it is very similar to the Ruby on Rails (RoR) implementation, which I like a lot. You can easily group routes, create resources for CRUD pages, attach filters and automatically bind models to the request parameters.

Nested routes are a very useful feature:

Route::group(['prefix'=>'level0'], function(){
   	Route::get('/', array('uses' => 'TestController@level0'));
    Route::group(['prefix'=>'/{level0}/level1'], function(){
   	    Route::get('/', array('uses' => 'TestController@level1'));
	    Route::post('/{custom_variable}/custom_route', array('uses' => 'CustomConroller@custom_route'));
    });
});

Versioning can be implemented as a group on the top level for all nested routes by using the ‘v1’ prefix. When we change the API version, we can retain the old one and use the ‘v2’ prefix to start implementation of routes with new code and logic, i.e., new references to controllers and actions.

Let’s take a step-by-step look at everything used in this Laravel tutorial:

A defined group of routes with path level0 at top level of our API.

If we have a call BASEURL/level0, then Laravel will resolve it and call method level0() of TestController to process the request.

We have a sub-group with the {level0}/level1 pattern. To access API resources inside this group we should use the path for the parent group (level0) and match the pattern of our sub-group ({level0}/level1). For example, level0/777/level1 is the correct path for this sub-group of our API. Here we have 777 as the variable level0 that Laravel will path to the handler of the routes inside the sub-group.

In the the end we have two sample routes:

BASEURL/level0/777/level1 – GET request to this URI will be processed with method level1($level0) of TestController where the first parameter is {level0} and it will be initialized with value 777.

BASEURL/level0/777/level1/888/custom_variable – POST request to this URI will be processed using the custom_route($level0, $custom_variable) method of CustomController.

The parameters used in the method come from the route variables.

Finally, we can associate our variable {level0} in the route with a model, i.e., LevelModel. In this case, the framework automatically tries to find existing database records and pass it on as a parameter to the controller’s method.

It helps us write less code and we don’t need to write LevelModel::find($id) or LevelModel::findOrFail($id) in controllers.

The Dingo API package takes routing one step further.

Here are a few features that Dingo provides to the framework:

  • Transformers: Special objects for response customization (e.g., type-cast integers and boolean values, paginate results, include relationships, etc.)
  • Protect routes and allow different/custom authentication providers. Controller Trait provides protection of custom actions, while we can easily retrieve authenticated user info with API::user().
  • Limiting request count per user by using built-in or custom throttles.
  • A powerful internal requests mechanism that allows requests on your API internally

 

Laravel uses Eloquent ORM

Laravel is based on Eloquent ORM. I’ve used it with PostgreSQL and MySQL, and in both cases it performed flawlessly.

The official documentation is comprehensive, so there is no reason to repeat things in this article:

Query Scope – query logic is created as a function with a special scope prefix.

The following example shows the standard SQL Query transformed to a query function in Eloquent ORM:

SELECT * WHERE hub_id = 100 AND (name LIKE `%searchkey%` OR surname LIKE `%searchkey%`):
function scopeByFieldListLike($query, $fields, $value){
    $query->where(function($query) use ($fields, $value){
        foreach($fields as $field){
            $query->orWhere($field , 'like', "%".$value."%");
        }
    });
    return $query;
}

Using a function in your code is straightforward.

$model = new User;
$model->byFieldListLike(['name', 'surname'], 'searchkey');

A lot Eloquent methods return an instance of the QueryBuilder. You can use almost all of these methods on models.

 

Unit Testing

Writing unit tests is usually very time consuming, however, it’s definitely worth the time, so please do it.

Laravel relies on a TestCase base class for this task. It creates a new instance of the application, resolves the route and runs the controller method in its own sandbox. However, it does not run application filters (App::before and App::after) or more complex routing scenarios. To enable these filters in a sandbox environment, I had to manually enable them by using Route::enableFilters().

Obviously, if you know how to use Laravel, you know it could use some more work in the unit testing segment. I’ve set up a few functions that helped me create more advanced unit tests. Feel free to take these and use them in your projects.

To perform more advanced real-life testing and implement “curl-like” requests, I used the kriswallsmith/buzz library. This provided me with a much needed feature set for testing, including custom headers and uploading files.

The code below shows the function you can use to execute this kind of test:

public function browserRequest($method, $resource, $data = [], $headers = [], $files = [])
{
    $host = $this->baseUrl();
    if (count($files)){
        // Use another form request for handling files uploading
        $this->_request = new Buzz\Message\Form\FormRequest($method, $resource, $host);
        if (isset($headers['Content-Type'])) {
            // we don't need application/json, it should form/multipart-data
            unset($headers['Content-Type']);
        }
        $this->_request->setHeaders($headers);
        $this->_request->setFields($data);
        foreach($files as $file) {
            $upload = new Buzz\Message\Form\FormUpload($file['path']);
            $upload->setName($file['name']);
            $this->_request->setField($file['name'], $upload);
        }
        $response = new Buzz\Message\Response();
        $client = new Buzz\Client\FileGetContents();
        $client->setTimeout(60);//Set longer timout, default is 5
        $client->send($this->_request, $response);
    } else {
        $this->_request = new Buzz\Message\Request($method, $resource, $host);
        $this->_request->setContent(json_encode($data));
        $this->_request->setHeaders($headers);
        $response = new Buzz\Message\Response();
        $client = new Buzz\Client\FileGetContents();
        $client->setTimeout(60);//Set longer timout, default is 5
        $client->send($this->_request, $response);
    }
    return $response;
}

I am a very lazy developer, so I added optional parameters that allowed me to decode responses, extract data, and check the response codes. This led to another method that includes default headers, authorization tokens and some additional functionality.

public function request($method, $path, $data = [], $autoCheckStatus = true, $autoDecode = true, $files = [])
{
    if (!is_array($data)){
        $data = array();
    }
    $servers = ['Content-Type' => 'application/json'];
    if ($this->_token){
        $servers['authorization'] = 'Token ' . $this->_token;
    }
    $this->_response = $this->browserRequest($method, $path, $data, $servers, $files);
    if ($autoCheckStatus === true){
        $this->assertTrue($this->_response->isOk());
    } elseif(ctype_alnum($autoCheckStatus)){
        $this->assertEquals($autoCheckStatus, $this->_response->getStatusCode());
    }
    if ($autoDecode){
        $dataObject = json_decode($this->_response->getContent());
        if (is_object($dataObject))
        {
            // we have object at response
            return $this->_dataKeyAtResponse && property_exists($dataObject, $this->_dataKeyAtResponse) ? $dataObject->{$this->_dataKeyAtResponse} : $dataObject;
        }
        elseif (is_array($dataObject))
        {
            // perhaps we have a collection
            return $this->_dataKeyAtResponse && array_key_exists($this->_dataKeyAtResponse, $dataObject) ? $dataObject[$this->_dataKeyAtResponse] : $dataObject;
        }
        else
        {
            // Uknown result
            return $dataObject;
        }
    } else {
        return $this->_response->getContent();
    }
}

Once again, my lazy habits made me add wrappers designed to test CRUD pages:

create($data = [], $autoCheckStatus = true, $autoDecode = true, $files = [])
show($id, $data = [], $autoCheckStatus = true, $autoDecode = true)
update($id, $data = [], $autoCheckStatus = true, $autoDecode = true, $files = [])
delete($id, $data = [], $autoCheckStatus = 204, $autoDecode = false)
index($data = [], $autoCheckStatus = true, $autoDecode = true)

A simple test code would look like this:

// send wrong request
// Validation error has code 422 in out specs
$response = $this->create(['title'=>'', 'intro'=>'Ha-ha-ha. We have validators'], 422);
// Try to create correct webshop
$dataObject = $this->create(
    $data = [
        'title'=>'Super webshop',
        'intro'=>'I am webshop',
    ]
);
$this->assertGreaterThan(0, $dataObject->id);
$this->assertData($data, $dataObject);

// Try to request existing resource with method GET
$checkData = $this->show($dataObject->id);
// assertData is also a help method for validation objects with nested structure (not a part of PHPUnit).
$this->assertData($data, $checkData);

// Try to update with not valid data
$this->update($dataObject->id, ['title'=> $data['title'] = ''], 422);

// Try to update only title. Description should have old value. Title - changed
$this->update($dataObject->id, ['title'=> $data['title'] = 'Super-Super SHOP!!!']);

// Then check result with reading resource
$checkData = $this->show($dataObject->id);
$this->assertData($data, $checkData);
       
// Read all created resources
$list = $this->index();
$this->assertCount(1, $list);
// TODO:: add checking for each item in the collection
        
// Delete resoure
$this->delete($dataObject->id);
$this->show($dataObject->id, [], 404);

Here is another useful function for validating response data including relations and nested data:

public function assertData($input, $checkData){
// it could be stdClass object after decoding json response
    $checkData = (array)$checkData;
    foreach($input as $k=>$v){
        if (is_array($v) && (is_object($checkData[$k]) || is_array($checkData[$k]))) {
    	    // checking nested data recursively only if it exists in both: response data($input) and expected($checkData)
           $this->assertData($v, $checkData[$k]);
        } else {
           $this->assertEquals($v, $checkData[$k]);
        }
    }
}

 

Queuing

Long running tasks are a common bottleneck in web applications. A simple example would be the creation of a PDF report and its distribution inside an organisation, which can take a lot of time.

Blocking user requests to perform this action is not a desirable way of addressing the issue. Using Queue in Laravel is a great way of handling and queuing long running tasks in the background.

One of the last issues was PDF generation and sending reports via email. I used a default queue driver for Beanstalkd, supported with the package pda/pheanstalk. It is very easy to add tasks to the queue

For example, generating and sending PDFs could be done like this:

\Queue::push('\FlexiCall\Queue\PdfSend', [....data for sending to job's handler..], 'default');

Our PdfSend handler could be implemented like this:

class PdfSend extends BaseQueue{
    function fire($job, $data){
    	//.............................
    	//..... OUR IMPLEMENTATION.....
    	//.............................
    }
}

Laravel specifications suggest tracking a queue with --daemon options, but I use the supervisor daemon that keeps it running permanently:

php artisan queue:listen --env=YOUR_ENV

Queues are great for tasks like saving data. They can be used to repeat failed jobs, add sleep timeouts before executing jobs, etc.

 

Putting It All Together

I’ve mentioned few key points related to Laravel development in this Laravel review. How you put it all together and build your application will depend on your specific setup and project. However, here is a brief checklist of steps you might want to consider:

  • Setup homestead Vagrant box prepared for development using Laravel and configured local environment.
  • Add endpoints (configure routes).
  • Add authentication layer.
  • Add filters before/after application execution, giving you an option to run anything before and after application is executed. Additionally, you can define filters for any route.

My default “before” filter creates a global scope as a singleton and starts the timer for monitoring performance:

class AppBefore {
	function filter($request) {
		\App::singleton('scope', function() {
			$scope = new AppScope();//My scope implementation
			$scope->startTimer();
			return $scope;
		});
	}
}

The “after” filter stops the timer, logs it to the performance log, and sends CORS headers.

class AppAfter{
	function filter($request, $response){
		$response->header('Access-Control-Allow-Origin', '*');
		$response->header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
		$response->header('Access-Control-Allow-Headers', 'Content-Type');
		$response->header('Access-Control-Max-Age', '86400');
		\App::make('scope')->endTimer();
		\App::make('scope')->logTotalTime();
		return $response;
	}
}

Developing each of your modules will likely require these steps:

Setup data migration, and seed default data. Implement models and relations, transformers, validators and sanitizers (if needed). Write unit tests. Implement controllers and execute tests.

 

Wrap Up

I’ve been using Laravel for over a year. As with any technology, there were some teething problems, but I believe that learning Laravel has convinved me that it is an amazing framework. There are a few more things that I haven’t mentioned in this Laravel tutorial, but if you are interested in learning more, you may want to consider these points and features:

  • Powerful model for subscribing and listening to application events.
  • Support for Amazon SDK aws/aws-sdk-php.
  • Caching.
  • Own templating engine called Blade, if you like building the application “the old way” without RESTful backend and UI separation.
  • Simple configuration.
  • Built-in Stripe billing module.
  • Out of the box localization.
  • Catching and handling most errors.

Good luck and stay tuned, Laravel is a promising framework and I believe it will be around for years to come.

 

Note: this article was first published on Toptal’s blog. Shared with permission from Toptal

 

Oleksii Rytov

Alexei is a web developer with over eight years of experience in developing business applications. He has architected entire projects and has most recently worked as a Scrum Master and Senior PHP Developer. He enjoys photography, travel, and fishing in his spare time.

 

Catch TokenMismatchException thrown by VerifyCsrfToken in Laravel

Reading Time: 2 minutes

If you are using Laravel 5, you must have come across something like this when a form wasn’t after a long period of time of opening the page.

 

This was meant to help with checking against CSRF but it can be really annoying seeing this. Most of your user/visitors don’t understand the gibberish written, and you can’t possibly tell them to always submit the forms on time. No, you just can’t. Neither should you assume that they will only be visiting your website/app at the time they are on the page.

Solution

Don’t disable the CSRF verification on your site. DON’T!

You can just simply catch this error and do something with it (well, not literarily).

Let me show you how you can catch the error and possible display the form again.

  1. Open app/Exceptions/Handler.php
  2. Find the render() method
  3. Add this piece of code to it

     

    if ($exception instanceof TokenMismatchException){
        //redirect to a form. Here is an example of how I handle mine
        return redirect($request->fullUrl())->with('flash-msg', 'Oops! Seems you didn\'t submit form for a longtime. Please try again.');
    }
  4. So your render method should now look like this

     

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if ($exception instanceof TokenMismatchException){
            //redirect to a form. Here is an example of how I handle mine
            return redirect($request->fullUrl())->with('flash-msg', 'Oops! Seems you didn\'t submit form for a longtime. Please try again.');
        }
        return parent::render($request, $exception);
    }

You can decide to do something else instead of redirecting to the original form.

That, my friend, is how to overcome the ugly TokenMismatchException in VerifyCsrfToken.php without compromising your site’s security.

Update

If you cannot find the render() method, go to vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php

Copy the render() method and paste it in app/Exceptions/Handler.php

Replace $exception with $e

So your final render() method in app/Exceptions/Handler.php will look like this

public function render($request, Throwable $e)
    {
        if (method_exists($e, 'render') && $response = $e->render($request)) {
            return Router::toResponse($request, $response);
        } elseif ($e instanceof Responsable) {
            return $e->toResponse($request);
        }

        $e = $this->prepareException($this->mapException($e));

        foreach ($this->renderCallbacks as $renderCallback) {
            if (is_a($e, $this->firstClosureParameterType($renderCallback))) {
                $response = $renderCallback($e, $request);

                if (! is_null($response)) {
                    return $response;
                }
            }
        }

        if ($e instanceof HttpResponseException) {
            return $e->getResponse();
        } elseif ($e instanceof AuthenticationException) {
            return $this->unauthenticated($request, $e);
        } elseif ($e instanceof ValidationException) {
            return $this->convertValidationExceptionToResponse($e, $request);
        } elseif ($e instanceof TokenMismatchException){
            return redirect($request->fullUrl());
        }

        return $request->expectsJson()
            ? $this->prepareJsonResponse($request, $e)
            : $this->prepareResponse($request, $e);
    }
 

Bind multiple models to a form in Laravel 5 and validate it

Reading Time: 3 minutesForm model binding in Laravel 5 makes the programmers’ live easier, no doubt. But what if you want to bind multiple models to a form? This is not straight forward but it’s not so complex either. (May be it was till I cracked it)

Follow the steps below and you should be okay.

Note:

  • I am assuming that there is a one on one relationship between the models you are binding.
  • Form model binding works if you have Laravel Collective’s Form & HTML package installed in your project.

 

Creating the Form Controller Method

First of all, create the controller method, and pass the model to the view.

class MyProfileController extends Controller
{
    public function edit(){
        $data = [
            'user' => User::find(Auth::user()->id), //Pass the model as data
            'pageTitle' => 'Edit my profile',
        ];
        return view('profiles.edit', $data);
    }
}

In the above example, the User model has a relationship with the other models we are binding to the form.

 

Defining the relationships in the Models

The models need to be related for this method to work. In our case, we are working with User model and Profile models.

The User model

The user model was created using the artisan make:auth command but this doesn’t matter. It can as well be a child of the Model class

class User extends Authenticatable
{

    //
    //...
    //
    public function profile(){
        return $this->hasOne('App\Profile');
    }
}

 

The Profile model

This is the reverse in the one one one relationship

class Profile extends Model
{
    
    //
    //...
    // 


    public function user(){
        return $this->belongsTo('App\User');
    }
}

 

The View, where the Form Model binging takes place

Like I mentioned, form model binding works with Laravel Collective’s Form & HTML package. So here is what the view looks like

{!! Form::model($user, ['url' => url('profile/edit')]) !!}
            {!! csrf_field() !!}



            <!-- name field -->
            <div class="form-group  {{ $errors->has('name') ? ' has-error' : '' }}">
                {{ Form::label('name', 'Full name') }}
                {{ Form::text('name', null, ['id'=>'name', 'placeholder'=>'Your full name', 'class'=>"form-control"]) }}

                @if ($errors->has('name'))
                    <span class="help-block">{{ $errors->first('name') }}</span>
                @endif
            </div>

            <!-- About Me field -->
            <div class="form-group  {{ $errors->has('profile.about_me') ? ' has-error' : '' }}">
                {{ Form::label('about_me', 'About me') }}
                {{ Form::textarea('profile[about_me]', null, ['id'=>'about_me', 'placeholder'=>'A little info about you', 'class'=>"form-control", 'rows' => 4]) }}

                @if ($errors->has('profile.about_me'))
                    <span class="help-block">{{ $errors->first('profile.about_me') }}</span>
                @endif
            </div>

            <!-- city field -->
            <div class="form-group  {{ $errors->has('profile.city') ? ' has-error' : '' }}">
                {{ Form::label('city', 'Town/City   ') }}
                {{ Form::text('profile[city]', $value = null, ['id'=>'city', 'placeholder'=>'Your town or city of residence', 'class'=>"form-control"]) }}

                @if ($errors->has('profile.city'))
                    <span class="help-block">{{ $errors->first('profile.city') }}</span>
                @endif
            </div>

         

            <button class="btn btn-info btn-md" type="submit">
                <i class="fa fa-save"></i>
                Save profile
            </button>

            {!! Form::close() !!}

 

Take note

  • The name field belongs to the User model while the about_me and city fields belong to the Profile model
  • Dot notation is used for the error names of the Profile fields/properties e.g profile.city while the name of the form field uses [ ]  e.g profile[city] (No quotation marks)

 

Writing the Validation logic

We need to validate the 3 fields i.e

  1. name
  2. about_me
  3. city

There are a number of ways to write the validation logic. I usually prefer to create a Request. This allows for reuse.

class ProfileRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {

        return [
            'name' => 'required|max:40|min:3',
            'profile.about_me' => 'required|max:500',
            'profile.city' => 'max:40|min:2',
        ];

    }

    public function messages()
    {
        return [
            'required' => 'This field is required',
            'min' => 'Must not be less than :min characters',
            'max' => 'Must not be greater than :max characters'
        ];
    }
}

In the rules() method, notice that I used the dot notation for about_me and city properties.

You need to create/override the messages() method and define custom messages, if not your users will see gibberish arising from :attribute property used in the default message which will make return something like “The profile.about_me field is required

 

Saving the form fields

You can go ahead and save the form fields. You don’t have to use the [] or dot notations, Request will recognise the form fields (i.e name, about_me and city) the way they are.

 

Conclusion

This process is pretty straightforward like I mentioned earlier. Go ahead and give it a try. And if you have any questions, use the comment section below.

 

How to prevent Android’s RecyclerView from recycling views

Reading Time: < 1 minuteThe RecyclerView widget, alongside the CardView widget, was introduced in Android API 21 (Lollipop). RecyclerView is a more flexible and more advanced version of ListView, according to Android developers’ website. But don’t read flexible as easier to implement. It’s cool though. yeah, it’s ListView on steroids.

One of its key feature is that it recycles views that are out of device screen. It is a cool feature but it’s not always a good thing. There are times you don’t really want to recycle views. Or when recycling messes up your display.

To overcome that, you have to take advantage of the setIsRecyclable() of the RecyclerView.ViewHolder class. Take a look at the onBindViewHolder() method to see how I solved implemented this.

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    final DataSource dataSource = dataSourceList.get(position);

    holder.setIsRecyclable(false);

    holder.name.setText(dataSource.getName());
    holder.active.setChecked(dataSource.getActive());

    String logoStr = dataSource.getLogo();

    //Logo
    /**
     * Do all the logo insertion stunts here
     */
    /**
     * Register the changes to the Switch
     */
    holder.active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
            dataSource.setActive(isChecked);
        }
    });
}

You can argue that this is going against what RecyclerView was designed to do, but then remember that Google themselves must have considered that recycling might not always be a desired result, hence they created a shortcut.

Hope this works for you.

 

P.S.: If you have any issues or questions, don’t hesitate to ask questions via the comments below. I will try to answer as many as I can. Well, you can also talk about anything related too. No, no spamming please

P.P.S.: if you want to learn how to work with RecyclerView, I recommend a very good tutorial on AndroidHive.info

 

How to create custom helper functions in Laravel 5

Reading Time: 2 minutesCreating simple PHP helper functions in Laravel 5 is not really something that comes out of the box, unlike what is obtained in CodeIgniter. This is one of the very few things I initially missed when I switched from CodeIgniter to Laravel.

However, there is a short solution. This might not necessarily be in compliance with Laravel’s best practices, but I kinda like it. Besides, it’s pretty straight forward.

Follow these three steps and you are good to go.

1. Create a Helper’s folder

Go to your app folder, create a new folder and name it Helpers. Helpers should be a sub folder of the app folder. This folder will be where all your helper function files will reside.

You can group related functions in the same script. This is one more reason I like this approach rather than creating one long file with all the helper functions (which will get harder to maintain as you add more functions)

2. Create a Service Provider

Create a Laravel Service Provider to handle your helper scripts and functions. You can do that manually or just use the artisan CLI command.

php artisan make:provider HelperServiceProvider

In the above, the Service Provider is called HelperServiceProvider.

Service Providers in Laravel have two methods ie the boot() and the register() methods. We are going to leave the boot() method empty, we only need the register() method. Add the following code to the register() method of the Service Provider you created.

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

3. Register your Service Provider

The last step involves registering your Service Provider in your application’s app config file ie config/app.php

Got to the providers section/element of the array and add the following

App\Providers\HelperServiceProvider::class,

So your providers section should look like this

'providers' => [
    //
    // Other Service providers listed here...
    //

    App\Providers\HelperServiceProvider::class,
];

Next steps

You can now start creating your functions in files in the Helpers sub folder of the app folder. You don’t have to follow any rules in naming your files. But I like to end mine with Helper.php so as to make them easily searchable for me.

Note that the helper files are just simple PHP scripts and not classes. So you can create a new function using the following syntax

if(!function_exists('exampleFunction')){
    /**
     * Doc block of function defined
     * @param type $symbol
     * @return 
     */
    function exampleFunction($param){
        //
        //Function code here
        //
    }
}

And whenever you want to call your functions, just do it the normal PHP way ie exampleFunction()

That’s all folks!

 

 

Note:

  • This code was tested with Laravel 5.2
  • You can change the name of the Service Provider file and that of the helper folder, it will still work so long as you are consistent.