facade的调用原理和过程

laravel 


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   //调用组件类的方法


....<?php namespace Illuminate\Support\Facades;
abstract class Facade {
  ....
    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }
blic static function __callStatic($method, $args)
        $instance = static::getFacadeRoot();
return $instance->$method();
</pre><pre name="code" class="php">
facade的大部分属性是static的
 

 

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调用该类的方法 过程就和前面说的一样 调用容器绑定类的方法


————————————————————————————————————————————————————

组件拓展

1

要建立自定义缓存驱动(组件),首先需要实现 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值