New Get started on Amezmo with a $60, 12-month credit for new users. Create free account →

Replacing Your Facades With Dependency Injection – Before and After

Avatar
Ryan McCullagh on

One of the things that that facades have going for them, is that they are elegant to look at it. But in my view, they hide the core logic, and make it difficult to understand how exactly a class works. Often times, when debugging, you need to look at the implementation of a method because it’s not documented.

Something that I believe is not documented and encouraged well enough is using Dependency Injection instead of Facades all over your codebase. I want to start with an example of a “before” and “after” class that used Facades, but now uses DI. For all internal Laravel services, and classes, such as the encryption class, you can see the mapping from interface to implementation in the Illuminate\Foundation\Application class. You can use this as a reference when replacing facades with Dependency Injection.

Before

namespace App\Http\Api\Site\Progress;

use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;

use App\Http\Api\Constants\AmezmoApi;
use App\Http\Api\BaseApiController;
use App\Http\Api\Site\Progress\Models\ProgressReport;

class SiteProgressController extends BaseApiController
{
    public function __construct() {}

    public function report(ProgressReport $report)
    {
        if ($report->step === 0) {
            $package = ['percentage' => 100, 'message' => 'Failed'];
            Log::error('got error signal from container instance engine');
        } else {
            $package = ['percentage' => $report->step, 'message' => $report->message];
        }

        Log::debug('progress', $package);

        Redis::set(stubbedProgressKey() json_encode($package), 'EX', AmezmoApi::PROGRESS_MESSAGE_TTL);

        return view();
    }
}

After

namespace App\Http\Api\Site\Progress;

use \Illuminate\Redis\Connections\PhpRedisConnection;
use \Illuminate\Contracts\Routing\ResponseFactory;
use \Psr\Log\LoggerInterface;

use App\Http\Api\Constants\AmezmoApi;
use App\Http\Api\BaseApiController;
use App\Http\Api\Site\Progress\Models\ProgressReport;
use App\Utils\JsonEncoder;


class SiteProgressController extends BaseApiController
{
    /** @var \Illuminate\Redis\Connections\PhpRedisConnection */
    private $redis;

    /** @var \Illuminate\Contracts\Routing\ResponseFactory */
    private $responseFactory;

    /** @var \Psr\Log\LoggerInterface $logger*/
    private $logger;

    /** @var \App\Utils\JsonEncoder */
    private $json;

    public function __construct(
        PhpRedisConnection $redis,
        JsonEncoder $json,
        ResponseFactory $response,
        LoggerInterface $logger
    ) {
        $this->redis = $redis;
        $this->json = $json;
        $this->responseFactory = $response;
        $this->logger = $logger;
        $this->ttl = AmezmoApi::PROGRESS_MESSAGE_TTL;
    }


    public function report(ProgressReport $report)
    {
        if ($report->step === 0) {
            $package = ['percentage' => 100, 'message' => 'Failed'];
            $this->logger->error('got error signal from container instance engine');
        } else {
            $package = ['percentage' => $report->step, 'message' => $report->message];
        }

        $this->redis->setEx(stubbedProgressKey() $this->ttl, $this->json->encode($package));

        return $this->responseFactory->noContent();
    }
}

So with the above setup, you do not have to do any configuration, or service binding because Laravel will automatically instantiate your instances for you through it’s container. The registerCoreContainerAliases method on the Illuminate\Foundation\Application class is the source of truth for these Facade to container aliases. The format is as follows:

As we can see the first element of each array is the implementation, while the second element is the interface. For example on line 17, encrypter is mapped to interface \Illuminate\Contracts\Encryption\Encrypter::class from core implementation \Illuminate\Encryption\Encrypter::class

This post was brought to you by Amezmo – Where we make professional PHP hosting as simple as possible. Deploy your PHP project today for free.