How does Laravel 4 load deferred provider?

前端 未结 1 2036
刺人心
刺人心 2021-02-04 22:19

I need to deeply understand laravel. I have to explain everything to my dev team since we are starting to use laravel.

Please correct this if it is wrong: When laravel s

1条回答
  •  孤街浪徒
    2021-02-04 22:53

    I wanted to know the answer to this as well, but I decided to look for myself instead.

    If you go to app/storage/meta there is a services.json that lists the eager and deferred classes. This is so we don't load all classes for every request as we may never need the Form class if we are building an API.

    The ProviderRepository class scans all the providers listed in app/config/app.php and instantiates the providers for each of them (These are not the actual libraries).

    These providers eg CacheServiceProvider in Illuminate/Cache have a variable called defer that determines whether the library will be eagerly loaded of deferred until needed.

    Here is a quote from ProviderRepository

    When recompiling the service manifest, we will spin through each of the providers and check if it's a deferred provider or not. If so we'll add it's provided services to the manifest and note the provider.

    For the CacheServiceProvider this is set to true.

    So lets say Validator::make() is called here is what I have gathered; Each Facade such as the Validator facade extends the base Facade class in Illuminate\Support\Facades\Facade.

    This has a magic method __callStatic($method, $args) which is quite self explanatory, the main point of this method is

    $instance = static::resolveFacadeInstance(static::getFacadeAccessor());
    

    The facade accessor in this case returns a string of the actual class that performs the validation (Illuminate\Validation\Validator):

    protected static function getFacadeAccessor() { return 'validator'; }
    

    The main method resolveFacadeInstance checks if the returned accessor is an object. If it is it simply returns that back as it is probably a custom Laravel package.

    The second part of this method checks if it has already been resolved, if it has then return that. The final part:

    return static::$resolvedInstance[$name] = static::$app[$name];
    

    Calls the Illuminate\Foundation\Application (which extends the Illuminate\Container\Container class) via the array access interface located in the previously mentioned parent class.

    So static::$app[$name] calls:

    public function offsetGet($key)
    {
        return $this->make($key);
    }
    

    This is located in the Container class

    Which leads us to the make() method in the Application class:

    public function make($abstract, $parameters = array())
    {
        if (isset($this->deferredServices[$abstract]))
        {
            $this->loadDeferredProvider($abstract);
        }
    
        return parent::make($abstract, $parameters);
    }
    

    I'll let you delve into the parent::make() method as this would start getting very lengthy, but as it stands this is where it loads the deferred provider and instantiates it via the loadDeferredProvider()

    public function loadDeferredProviders()
    {
        // We will simply spin through each of the deferred providers and register each
        // one and boot them if the application has booted. This should make each of
        // the remaining services available to this application for immediate use.
        foreach (array_unique($this->deferredServices) as $provider)
        {
            $this->register($instance = new $provider($this));
    
            if ($this->booted) $instance->boot();
        }
    
        $this->deferredServices = array();
    }
    

    The comments in the code block should explain the rest of what is happening.

    From here, the last part of __callStatic($method, $args) fires the actual method called Validator::make().

    public static function __callStatic($method, $args)
    {
        $instance = static::resolveFacadeInstance(static::getFacadeAccessor());
    
        switch (count($args))
        {
            case 0:
                return $instance->$method();
    
            case 1:
                return $instance->$method($args[0]);
    
            case 2:
                return $instance->$method($args[0], $args[1]);
    
            case 3:
                return $instance->$method($args[0], $args[1], $args[2]);
    
            case 4:
                return $instance->$method($args[0], $args[1], $args[2], $args[3]);
    
            default:
                return call_user_func_array(array($instance, $method), $args);
        }
    }
    

    So the facade calls Illuminate\Validation\Validator's non-static method validate().

    I'm pretty sure this is accurate for 4.0 but please correct me if there any mistakes.

    0 讨论(0)
提交回复
热议问题