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参数有什么用
不同拓展 拓展代码放的地方不一样 ,需要实现的方法也不要