欢迎光临
我们一直在努力

laravel facade的调用原理和过程

1.创建一个类 如 ….CacheManager.php
默认的组件在
vendor/laravel/framework/src/Illuminate/xxx/
//如vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php
2.一个provider … CacheServiceProvider
默认与组件在同一个目录
vendor/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php
3.//provider类绑定组件

class CacheServiceProvider extends ServiceProvider
{ 
	public function register()
	{
//服务容器(this->app) 在 服务提供者(ServiceProvider) 内绑定 服务(cachemanager)
//容器...(生成提供者时就有容器??) 各种服务存储 提供者 像容器中注入服务 服务 类 实现某种功能的类
//contracts核心服务类实现的接口
//Facades提供一个静态接口给在应用程序的 服务容器 中可以取用的类 下面有详解

		$this->app->singleton('cache', function ($app) // this->app 是服务容器 (提供者内的调用方法)
		{
			return new CacheManager($app);
		});
	}
}

4. config/app.php //注册服务提供者

'providers' => [

/*
* Laravel Framework Service Providers...
*/

'Illuminate\Cache\CacheServiceProvider',

5 创建facades //调用容器方法

vendor/laravel/framework/src/Illuminate/Support/Facades/cache.php。

class Cache extends Facade {
  protected static function getFacadeAccessor() //唯一一个方法
    {
        return 'cache'; //返回组件的注册名称
    }
}

6.基类 Facade //调用组件类的方法

7.实际使用
use Illuminate\Support\Facades\Cache;
Cache::method() //Cache::get 调用可以被重写成像这样: $value = $app->make(‘cache’)->get(‘key’);
因为调用的是静态方法 所以也不要实体化
facade对应的是容器注册的组件

容器都是拓展与container
bind 绑定核心类
make实例化核心类 //$app就是入口文件一开始$app = new Illuminate\Foundation\Application(realpath(__DIR__.’/../’));创建的
//各种Facade继承与基类的Facade
// use 某Facade, 某Facade:xx 实际上是调用基类Facade的 callstatic方法
//Laravel 从服务容器解析缓存管理类出来,并对该类调用 xx 方法
// laravel Facades 是使用 Laravel 服务容器作为服务定位器的便捷语法。
//而 服务提供者用做绑定的存在 绑定后注册 facade通过绑定的名字“cache”来调用
//一开始全局的的app和后来注册的provider如何关联?
//bind $this->bindings[$abstract] = compact(‘concrete’, ‘shared’);
//make if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; }
//所有服务提供者绑定的类都同样绑定到了 app

结论: 我在一开始的app这个类中动态声明了一个属性mytest,然后在facade中输出他的app的mytest 值相同,说明是同一个最初声明的app
//然后我在xxserviceprovider里在输出 this->app->mytest依然是同一个值,所以容器都为一开始的app
serviceprovider内 绑定一个 实例类 到容器 $this->app->singleton(‘cache’, function($app) {return new CacheManager($app);
app->make(‘cache’)调用 CacheManager,并且通过facade也可以 Cache:xx调用该类的方法 过程就和前面说的一样 调用容器绑定类的方法

组件拓展

要建立自定义缓存驱动(组件),首先需要实现 Illuminate\Contracts\Cache\Store contract 。

//统一实现接口 自动注入

所以,我们的 MongoDB 缓存实现将会看起来像这样:

class MongoStore implements Illuminate\Contracts\Cache\Store {

public function get($key) {}
public function put($key, $value, $minutes) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function forget($key) {}
public function flush() {}

}

自定义缓存驱动代码放在哪里,请考虑把它放上 Packagist !或者,你可以在 app 的目录中建立 Extensions 命名空间
2 调用拓展组件方法方法

Cache::extend('mongo', function($app) { //$app是容器实体 repository方法中
   return Cache::repository(new MongoStore);
});

注册自己写的拓展
Cache::extend 的调用可以在新的 Laravel 应用程序默认附带的 App\Providers\AppServiceProvider 的 boot 方法中完成
或者你可以建立自己的服务提供者来放置这个扩展
config/xxx.php xxx都是系统的核心功能
extend 方法的第一个参数是驱动的名称。这将会对应到你的 config/cache.php 配置文件里的 driver 选项

问题 Cache::get中 CacheManager.php 中get方法有this关键字
静态方法中不能有this
所以要理解过程 get不是静态方法,Facade根据getFacadeAccessor实现了类然后调用非静态的方法
顺带一提 静态方法中调用 实体类自身用 self:: 不用this::

管理者是一个注册的实体类 用来管理创建基于驱动的组件(用来管理创建基于驱动的组件) 工厂脚本化生成实体类

疑问 extend闭包中 $app参数有什么用

不同拓展 拓展代码放的地方不一样 ,需要实现的方法也不要

赞(0)
版权归原作者所有,如有侵权请告知。达维营-前端网 » laravel facade的调用原理和过程

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址