1.Dependency Injection

Before digging into laravel service provider, let have some basic knowledge about dependency injection in PHP

So what is dependency injection, that is we could easily inject class into a class, by PHP’s magic method, which is __constructor(){}, this also ensures the property “low coupling” in object-oriented programing. Let take an example:

<?php

class Resource
{
    private $resource = "Video";

    public function cache()
    {
        $cacher = new Cacher();
        $cacher->handleCaching($this->resource);
    }
}

class Cacher
{
    public function handleCaching($resource)
    {
        echo $resource. " was cached by Cacher!";
    }
}

$resource = new Resource();
$resource->cache();

This one looks good, but not that good. We inited an object in the cache() method, which leads to a strong dependence of Resource class to Cacher class. Imagine one day your team decide to use another cache class, thirst party or something similar, you will have to change the cache method, so terrible and dangerous, So we could change those code to this:

class Resource
{
    private $resource = "Video";
    protected $cacher;

    public function __construct($cacher)
    {
        $this->cacher = $cacher;
    }

    public function cache()
    {
        $this->cacher->handleCaching($this->resource);
    }
}

class Cacher
{
    public function handleCaching($resource)
    {
        echo $resource. " was cached by Cacher!";
    }
}

$resource = new Resource(new Cacher());
$resource->cache();

This one is better, now Resource is not depend to Cacher anymore, if we need to use another cacher, just passing another one to resouce.

But, the point is, laravel handle this:

$resource = new Resource(new Cacher());

Yep, we don’t have to passing a new class to Resouce, laravel already handle it for us by service container/provider

2. Laravel Concept

'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,


        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

    ],3. Service provider

Those providers make laravel become one of the most starred PHP frameworks on GitHub, i do believe so.

So now, we want to have our own service provider, that could easily inject in a controller class and using services from it. OK, let created one!

3. Service provider

Let have a service provider class, this one will be soonly define in config/app.php

<?php

namespace App\Repositories;

class RepositoryServiceProvider extends ServiceProvider
{
   /**
     * @return void
     */
    
    public function register()
    {
        $this->app->singleton(
            \App\Repositories\Homestay\HomestayRepositoryInterface::class,
            \App\Repositories\Homestay\HomestayRepository::class
        );
    }
}

Don’t forget that this one has to extend laravel service provider class. HomestayRepositoryInterface now consume a concrete is HomestayRepository class

<?php
namespace App\Repositories\Homestay;

interface HomestayRepositoryInterface
{
    public function getHomestay();
}
<?php
namespace App\Repositories\Homestay;

use App\Repositories\Homestay\HomestayRepositoryInterface;

class HomestayRepository implements HomestayRepositoryInterface
{
	public function getHomestay() 
    {
      	// handle service...
    	return "result of method" 
    }
}

Then define our service provider class in config/app.php

 'providers' => [
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
		// ......

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
		// ....
      
      
        // THIS IS SERVICE THAT WE HAVE JUST BEEN CREATED!!!!!
        App\Repositories\RepositoryServiceProvider::class,
		// DON;T EVER FORGET TO DEFINE IT ON 'providers' ARRAY
    ],

Now, just inject our service to where ever we want, the best practice is injecting it into the Controller class

<?php

namespace App\Http\Controllers\API\Admin;

use App\Repositories\Homestay\HomestayRepositoryInterface;


class HomestayController
{

    protected $homestayRepo;

    public function __construct(
      // Inject it here
        HomestayRepositoryInterface $homestayRepo,
    )
    {
        $this->homestayRepo = $homestayRepo;
    }
     
    public function getHomestay()
    {
    	  return $this->homestayRepo->getHomestay();
    }
}

Your controller now looks much prettier. No need to show a bunch of logic code in the controller method and the important thing is, you could use this service, inject into whatever classes, services that you want!

There are so many practices for this, I will have another post about it later.

You guys may want to take a look at late static binding in PHP


Leave a Reply

Your email address will not be published. Required fields are marked *