Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 : How are Facades resolved?

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];
    }
    
like image 764
theUnknown777 Avatar asked Dec 01 '13 10:12

theUnknown777


People also ask

How do Laravel facades work?

How Facades Work. In a Laravel application, a facade is a class that provides access to an object from the container. The machinery that makes this work is in the Facade class. Laravel's facades, and any custom facades you create, will extend the base Illuminate\Support\Facades\Facade class.

What does Laravel use for seeding & facades?

Laravel includes the ability to seed your database with data using seed classes. All seed classes are stored in the database/seeders directory. By default, a DatabaseSeeder class is defined for you. From this class, you may use the call method to run other seed classes, allowing you to control the seeding order.

What is the difference between facades and contracts in Laravel?

Contracts Vs.Laravel's facades provide a simple way of utilizing Laravel's services without needing to type-hint and resolve contracts out of the service container. However, using contracts allows you to define explicit dependencies for your classes. For most applications, using a facade is just fine.

Where is facades in Laravel?

All of Laravel's facades are defined in the Illuminate\Support\Facades namespace.


1 Answers

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.

like image 91
The Alpha Avatar answered Nov 02 '22 22:11

The Alpha