Tuesday, 26 July 2022

[Laravel] How to find out which Class and File are behind a Facade

Facades in Laravel allow us to call libraries very conveniently. However, developers who are new to a project will find it difficult to investigate errors because Laravel Error Handling does not specify which class caused the error. In particular, the problem is very common with Facades that have many services  available. Ex: DB, Image, Auth, Cache, Mail...

Laravel Facade Flow

* Quick debug:

To find out the PHP class behind a Facade that you don't know where it is, you can debug it with the following code:
$behindClass = get_class(\<<Facade>>::getFacadeRoot());
$classReflector = new \ReflectionClass($behindClass);
dd($behindClass, $classReflector->getFileName(), $classReflector);
ex: 
$behindClass = get_class(\Mail::getFacadeRoot());
$classReflector = new \ReflectionClass($behindClass);
dd($behindClass, $classReflector->getFileName(), $classReflector);
result:

* Understand how the Facade is loaded by Laravel:

To find the underlying class behind a Laravel Facade without debugging you need to understand how a Facade is installed and loaded into Laravel.
Facade looks magical, but it's actually based on PHP's built-in class_alias feature. You can see in the project's config file (/config/app.php) there is a block to declare the Facade class alias.
Ex:
'aliases' => [
  ....
  'Lang' => Illuminate\Support\Facades\Lang::class,
  'Log' => Illuminate\Support\Facades\Log::class,
  'Mail' => Illuminate\Support\Facades\Mail::class,
If you open the class Illuminate\Support\Facades\Mail you will see that the class is almost completely empty. It has very little source code and doesn't really handle any features. In this file, the most special thing we see is the getFacadeAccessor() function and this function does not process anything but just returns a simple string like "mailer". This function is present in all Facades.
protected static function getFacadeAccessor()
{
         return 'mailer';
}
It looks magical, but it's not really here. Illuminate\Support\Facades\Mail inherits another class, Illuminate\Support\Facades\Facade::class . In this superclass Laravel will call getFacadeAccessor() to get the name of the actual service that has been configured by laravel for this facade. The example here is 'mailer'. Laravel will then call the 'mailer' service to return the Facade call - app('mailer').
You may be wondering that until now we still do not know where the 'mailer' service is located and how it is declared in Laravel.
Normally, every Laravel service needs to be declared through a Provider and then be available anywhere. Facades are treated the same way. Usually when you install a service pack from outside you will see in the source code of that service pack in addition to the Class Facade there will be a Class Provider to declare the service with Laravel. This means that once we have found information about Facade's extension in config/main.php, we can next look for Class Provider in that extension's source code to see the exact services that have been provided. How is it declared and what files it leads to.
Ex:
class MailServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public function register()
    {
        $this->registerSwiftMailer();
        $this->registerIlluminateMailer();
        $this->registerMarkdownRenderer();
    }
    protected function registerIlluminateMailer()
    {
        $this->app->singleton('mailer', function ($app) {
            $config = $app->make('config')->get('mail');
Usually the Providers will be installed automatically when we add the extension package to the project. In addition, Providers can also be manually declared in "config/app.php". There are some services that are core of Laravel, so by default they are declared when laravel starts. For example, with the 'mailer' service we just learned about. For core services, the Facade location and the service source code may be different. As with most package that you install from a third party, the Facade source code, Facade Provider, and Facade-related files are all in the same place in Vendors.

* Note:

we can read the source code in the "vendor" to understand and find a way to fix the error faster, but it is absolutely not recommended to edit the source code directly in the "vendor".

0 nhận xét:

Post a Comment