Laravel 4 : How are Facades resolved?
laravel, laravel-4, php
Solution
I'll try to describe in short :
So, you already know that `resolveFacadeInstance` method is called via `__callStatic` method of `Facade` class and component's Facade `(i.e. File extends Facade)` extends this `Facade` class.
During the boot-up process of the framework, from `public/index.php` following line starts the execution of `bootstrap/start.php` file
$app = require_once __DIR__.'/../bootstrap/start.php';
So, in this (`bootstrap/start.php`) file you can see some code like
// the first line, initiate the application
$app = new Illuminate\Foundation\Application;
// ...
// ...
// notice this line
require $framework.'/Illuminate/Foundation/start.php';
// ...
// last line
return $app;
In this code snippet, `require $framework.'/Illuminate/Foundation/start.php';` line starts the execution of `Foundation/start.php` file and in this file you may see something like this
// ...
Facade::clearResolvedInstances();
// Notice this line
Facade::setFacadeApplication($app);
This (given above) line sets `application` instanse to `$app` property in the `Facade` class
// support/Facades/Facade.php
public static function setFacadeApplication($app)
{
static::$app = $app;
}
Then in the `Foundation/start.php` file at the bottom, you can see something like this
/*
|--------------------------------------------------------------------------
| Register The Core Service Providers
|--------------------------------------------------------------------------
|
| The Illuminate core service providers register all of the core pieces
| of the Illuminate framework including session, caching, encryption
| and more. It's simply a convenient wrapper for the registration.
|
*/
$providers = $config['providers'];
$app->getProviderRepository()->load($app, $providers);
$app->boot();
In this code snippet given above, all the core components registered by the framework and as you know that, every component has a service provider class (i.e. `FilesystemServiceProvider`) and in every service provider class there is a method `register` which is (for `FilesystemServiceProvider`)
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app['files'] = $this->app->share(function() { return new Filesystem; });
}
Well, in this case `$this->app['files']` setting (`return new Filesystem`) an anonymous function, which returns the `filesystem` when gets executed
$this->app['files'] = $this->app->share(function() { return new Filesystem; });
to `$app['files']` so, when you call the `File::get()`, it finally calls the anonymous function and in this case, the following line
return static::$resolvedInstance[$name] = static::$app[$name];
Calls the function for `static::$app['file'];` and this function returns the instance but before returning, it stores the instance in the `$resolvedInstance` variable, so, next time it can return the instance from the variable without calling the anonymous function again. So, it looks like that, `static::$resolvedInstance[$name] = static::$app[$name];` calls the anonymous function which returns the instance and this function was registered earlier, when the `app` was started through boot up process.
Important :
`Application` extends `Container` and `Container` extends ArrayAccess class and that's why, a property of the `$app` object could be (accessed) set/get using array notation.
I've tried to give you an idea but you have to look in to the code, step by step, you won't get it only reading/tracking the code once.
Problem
I've kind of looking at what's going on Laravel 4 facades under the hood. Let's take this Facade as an example: ``` File::get(someArgs); ``` If i'm not mistaken, the step by step (oversimplified) invocation would be: ``` //static method invocation which are all extended from Facade class File::__callStatic(get, someArgs) //returns an instance of FileSystem File::resolveFacedeInstance('files') FileSystem->get(someArgs) ``` What I'am confused about is in the commented line below of the method File::resolveFacadeInstance() below: ``` protected static function resolveFacadeInstance($name) { if (is_object($name)) return $name; if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } /** * The line that i'm confused about */ return static::$resolvedInstance[$name] = static::$app[$name]; } ``` My questions are: - How is File::$app even initialized or assigned a value inside the Facade class If File::get() is the invoked Facade static::$app[$name] would resolve to i think Application['files'] or Application->files which in turn calls Application->__get('files') since there's no files property inside Application class. How would FileSystem Class be return if this is only the content of this method? ``` public function __get($key) { return $this[$key]; } ```