博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
laravel5.5源码笔记(三、门面类facade)
阅读量:4952 次
发布时间:2019-06-12

本文共 6799 字,大约阅读时间需要 22 分钟。

上次说了provider,那么这次来说说facade

首先是启动的源头,从laravel的kernel类中的$bootstrappers 数组,我们可以看到它的一些系统引导方法,其中的RegisterFacades便是用来注册facade门面类的了。

protected $bootstrappers = [        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,        \Illuminate\Foundation\Bootstrap\BootProviders::class,    ];

 

 同样是有一个register类,通过这个类进行别名等注册操作

namespace Illuminate\Foundation\Bootstrap;use Illuminate\Foundation\AliasLoader;use Illuminate\Support\Facades\Facade;use Illuminate\Foundation\PackageManifest;use Illuminate\Contracts\Foundation\Application;class RegisterFacades{    /**     * Bootstrap the given application.     *     * @param  \Illuminate\Contracts\Foundation\Application  $app     * @return void     */    public function bootstrap(Application $app)    {        //清除facade所有已绑定实例        Facade::clearResolvedInstances();        //将app存入对象        Facade::setFacadeApplication($app);        //将这些别名数组通过构造函数存入对象中        AliasLoader::getInstance(array_merge(            //通过Illuminate\Config\Repository获取config/app.php中的aliases数组            $app->make('config')->get('app.aliases', []),            //还记得最开始的博文中提到的那个包清单吗,这里也从中获取了它的aliases            $app->make(PackageManifest::class)->aliases()        //通过spl_autoload_register函数注册另一种自动加载函数        ))->register();    }}
public static function getInstance(array $aliases = [])    {        //注册时的实例是空的,会通过构造方法把刚刚传入的别名数组存入对象        if (is_null(static::$instance)) {            return static::$instance = new static($aliases);        }        $aliases = array_merge(static::$instance->getAliases(), $aliases);        static::$instance->setAliases($aliases);        return static::$instance;    }    private function __construct($aliases)    {        $this->aliases = $aliases;    }
public function register()    {        if (! $this->registered) {            $this->prependToLoaderStack();            $this->registered = true;        }    }    /**     * Prepend the load method to the auto-loader stack.     *     * @return void     */    protected function prependToLoaderStack()    {        //最后通过自动加载函数将本对象中的load方法放入自动加载队列的前端,在我们通过类名调用方法时,会触发自动加载函数队列,会优先触发这个函数,查找到对应文件的路径然后加载相应文件        spl_autoload_register([$this, 'load'], true, true);    }
public function load($alias)    {        //若传入的命名空间不为当前facade数组内才会通过这个方法加载        if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {            $this->loadFacade($alias);            return true;        }        //否则直接返回其别名        if (isset($this->aliases[$alias])) {            return class_alias($this->aliases[$alias], $alias);        }    }    /**     * Load a real-time facade for the given alias.     *     * @param  string  $alias     * @return void     */    protected function loadFacade($alias)    {        require $this->ensureFacadeExists($alias);    }    /**     * Ensure that the given alias has an existing real-time facade class.     *     * @param  string  $alias     * @return string     */    protected function ensureFacadeExists($alias)    {        //从缓存中返回路径        if (file_exists($path = storage_path('framework/cache/facade-'.sha1($alias).'.php'))) {            return $path;        }                file_put_contents($path, $this->formatFacadeStub(            $alias, file_get_contents(__DIR__.'/stubs/facade.stub')        ));        return $path;    }

 由于laravel中composer的执行过程过于繁琐,这里就不做深究了。原理是一样的,通过别名找到命名空间的类名,再由composer的类名与文件路径映射关系,自动加载函数找到相应文件加载进来。

 

那么我们来自定义一个门面类试一下

1、新建一个facade类,这里返回的test是上一篇博客中定义的对象

namespace App\Facades;use Illuminate\Support\Facades\Facade;class Test extends Facade{    protected static function getFacadeAccessor()    {        return 'App\Contracts\Test';    }}

2、将它添加到config/app.php的aliases别名数组中

'aliases' => [        'App' => Illuminate\Support\Facades\App::class,        'Artisan' => Illuminate\Support\Facades\Artisan::class,        'Auth' => Illuminate\Support\Facades\Auth::class,        'Blade' => Illuminate\Support\Facades\Blade::class,        'Broadcast' => Illuminate\Support\Facades\Broadcast::class,        'Bus' => Illuminate\Support\Facades\Bus::class,        'Cache' => Illuminate\Support\Facades\Cache::class,        'Config' => Illuminate\Support\Facades\Config::class,        'Cookie' => Illuminate\Support\Facades\Cookie::class,        'Crypt' => Illuminate\Support\Facades\Crypt::class,        'DB' => Illuminate\Support\Facades\DB::class,        'Eloquent' => Illuminate\Database\Eloquent\Model::class,        'Event' => Illuminate\Support\Facades\Event::class,        'File' => Illuminate\Support\Facades\File::class,        'Gate' => Illuminate\Support\Facades\Gate::class,        'Hash' => Illuminate\Support\Facades\Hash::class,        'Lang' => Illuminate\Support\Facades\Lang::class,        'Log' => Illuminate\Support\Facades\Log::class,        'Mail' => Illuminate\Support\Facades\Mail::class,        'Notification' => Illuminate\Support\Facades\Notification::class,        'Password' => Illuminate\Support\Facades\Password::class,        'Queue' => Illuminate\Support\Facades\Queue::class,        'Redirect' => Illuminate\Support\Facades\Redirect::class,        'Redis' => Illuminate\Support\Facades\Redis::class,        'Request' => Illuminate\Support\Facades\Request::class,        'Response' => Illuminate\Support\Facades\Response::class,        'Route' => Illuminate\Support\Facades\Route::class,        'Schema' => Illuminate\Support\Facades\Schema::class,        'Session' => Illuminate\Support\Facades\Session::class,        'Storage' => Illuminate\Support\Facades\Storage::class,        'URL' => Illuminate\Support\Facades\URL::class,        'Validator' => Illuminate\Support\Facades\Validator::class,        'View' => Illuminate\Support\Facades\View::class,        //刚刚新建的facades        'Test' => \App\Facades\Test::class,    ],

3、在路由文件中调用它

Route::any('/index', function (){    Test::doing();});

我们会发现,即使我们没有通过app对象进行make也没有任何命名空间的引入,它就这样被调用了。

如果是在类中调用,那么就要麻烦一些了,需要ues这个别名,注意这一点

namespace App\Http\Controllers;use Illuminate\Http\Request;//use App\Contracts\Test;//注意这里只引入了别名,由于命名空间冲突,所以我注释了其他部分use Test;class IndexController extends Controller{//    public function __construct(Test $test)//    {//        $this->test = $test;//    }    public function index(Test $test)    {        Test::doing();//        app()->make('App\Contracts\Test')->doing();//        echo '
';//// //只有通过构造方法进行自动加载依赖的方式才能触发契约的when绑定// $this->test->doing();//// echo '
';// //因为laravel中的上下文绑定只能具体到类,所以这里的$test实例依然为普通绑定// $test->doing(); }}

 通过这个demo的实践,facade还是比较简单的。

转载于:https://www.cnblogs.com/wyycc/p/9888927.html

你可能感兴趣的文章
原因和证明
查看>>
VC6.0图像处理2--图像的反色
查看>>
Snoop, 对WPF程序有效的SPY++机制
查看>>
JAVA程序猿怎么才干高速查找到学习资料?
查看>>
使用axel下载百度云文件
查看>>
Qt中图像的显示与基本操作
查看>>
详解软件工程之软件测试
查看>>
WCF(二) 使用配置文件实现WCF应用程序
查看>>
【CodeForces 803 C】Maximal GCD(GCD+思维)
查看>>
python 去掉换行符或者改为其他方式结尾的方法(end='')
查看>>
数据模型(LP32 ILP32 LP64 LLP64 ILP64 )
查看>>
REST构架风格介绍:状态表述转移
查看>>
struct {0}初始化
查看>>
c++ operator
查看>>
apache 添加 ssl_module
查看>>
java小技巧
查看>>
POJ 3204 Ikki's Story I - Road Reconstruction
查看>>
JavaScript笔记——正则表达式
查看>>
网页消息类
查看>>
【BZOJ】2959: 长跑(lct+缩点)(暂时弃坑)
查看>>