Laravel 4:外墙是如何解决的?

时间:2013-12-01 10:51:57

标签: php laravel laravel-4

我有点想看Laravel 4 Facade 的内幕。

我们以此Facade为例:

File::get(someArgs);

如果我没有弄错的话,一步一步(过度简化)的调用将是:

//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)

我感到困惑的是下面方法 File :: resolveFacadeInstance()的注释行:

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];
}

我的问题是:

  • File :: $ app 如何在Facade类中初始化或分配值
  • 如果 File :: get()是调用的Facade

    静态:: $ app [$ name] 会解析为我认为应用['文件'] 或者应用程序>文件又调用Application-> __ get('files'),因为应用程序类中没有文件属性。

    如果这只是此方法的内容,将如何返回FileSystem类?

    public function __get($key)
    {
        return $this[$key];
    }
    

1 个答案:

答案 0 :(得分:21)

我将简要介绍一下:

因此,您已经知道resolveFacadeInstance方法通过__callStatic类的Facade方法进行调用,而组件的Facade (i.e. File extends Facade)扩展了此Facade类。

在框架的启动过程中,从public/index.php以下行开始执行bootstrap/start.php文件

$app = require_once __DIR__.'/../bootstrap/start.php';

因此,在此(bootstrap/start.php)文件中,您可以看到一些代码,如

// the first line, initiate the application
$app = new Illuminate\Foundation\Application;
// ...
// ...
// notice this line
require $framework.'/Illuminate/Foundation/start.php';
// ...
// last line
return $app;

在此代码段中,require $framework.'/Illuminate/Foundation/start.php';行开始执行Foundation/start.php文件,在此文件中您可能会看到类似这样的内容

// ...

Facade::clearResolvedInstances();
// Notice this line
Facade::setFacadeApplication($app);

这(上面给出的)行将application类设置为$app类中的Facade属性

// support/Facades/Facade.php
public static function setFacadeApplication($app)
{
    static::$app = $app;
}

然后在底部的Foundation/start.php文件中,您可以看到类似这样的内容

/*
|--------------------------------------------------------------------------
| 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();

在上面给出的代码片段中,框架注册的所有核心组件,如您所知,每个组件都有一个服务提供者类(即FilesystemServiceProvider),并且在每个服务提供者类中都有一个方法{ {1}}(对于register

FilesystemServiceProvider

嗯,在这种情况下/** * Register the service provider. * * @return void */ public function register() { $this->app['files'] = $this->app->share(function() { return new Filesystem; }); } 设置($this->app['files'])一个匿名函数,它在执行时返回return new Filesystem

filesystem

$this->app['files'] = $this->app->share(function() { return new Filesystem; }); 所以,当你调用$app['files']时,它最终调用匿名函数,在这种情况下,调用以下行

File::get()

调用return static::$resolvedInstance[$name] = static::$app[$name]; 函数并且此函数返回实例但在返回之前,它将实例存储在static::$app['file'];变量中,因此,下次它可以从变量返回实例而不调用匿名功能再次。 因此,看起来,$resolvedInstance调用匿名函数,该函数返回实例,并且在static::$resolvedInstance[$name] = static::$app[$name];通过启动过程启动时,此函数已在之前注册。

重要提示:

app扩展ApplicationContainer扩展ArrayAccess类,这就是为什么Container对象的属性可以(访问)设置/获取使用数组符号。

我试图给你一个想法,但是你必须一步一步地查看代码,你不会只阅读/跟踪代码一次。