作为程序员一定要保持良好的睡眠,才能好编程

第八课 laravel门面模式运行原理(一)

发布时间:2018-07-20


use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;

Cache::add('user','bbb',100);

$vv=app();
dd(Cache::getFacadeApplication() instanceof  $vv);



lumen门面模式实现原理:

在项目启动时,lumen启动了 Laravel\Lumen\Application 容器,调用了 withAliases() 这个方法,将系统使用的容器把门面类加载进来。

我们在项目中,use Illuminate\Support\Facades\Log;

就可以使用 Log::info('使用门面模式写一个日志'); 就可以使用这样的方法写日志了。

那么打开 Illuminate\Support\Facades\Log 这个文件,也看不到 info 这个方法啊,这到底怎么回事?

下面听我一一道来:

门面模式 简单来说就是类的静态方法调用(个人理解、大神勿喷)


要理解门面模式离不开:Illuminate\Support\Facades\Facade; 这个类,这是门面模式的核心。

lumne实现门面模式用到了两个技术点   __callStatic($method, $args)  静态方法找不到 调用这个方法  还有一点是 ...$args   变长参数  、class_alias() 这个函数


bootstarp/app.php 启动框架





系统启动,会实例化
Laravel\Lumen\Application  这个对象




会加载 门面类
use Illuminate\Support\Facades\Facade;




$app->withFacades();  加载门面类



方法如下:

/**
 * Register the facades for the application.
 *
 * @param  bool  $aliases
 * @param  array $userAliases
 * @return void
 */
public function withFacades($aliases = true, $userAliases = [])
{
    Facade::setFacadeApplication($this);
    if ($aliases) {
        $this->withAliases($userAliases);
    }
}
方法中调用了下面这个方法:
/**
 * Register the aliases for the application.
 *
 * @param  array  $userAliases
 * @return void
 */
public function withAliases($userAliases = [])
{
    $defaults = [
        'Illuminate\Support\Facades\Auth' => 'Auth',
        'Illuminate\Support\Facades\Cache' => 'Cache',
        'Illuminate\Support\Facades\DB' => 'DB',
        'Illuminate\Support\Facades\Event' => 'Event',
        'Illuminate\Support\Facades\Gate' => 'Gate',
        'Illuminate\Support\Facades\Log' => 'Log',
        'Illuminate\Support\Facades\Queue' => 'Queue',
        'Illuminate\Support\Facades\Route' => 'Route',
        'Illuminate\Support\Facades\Schema' => 'Schema',
        'Illuminate\Support\Facades\URL' => 'URL',
        'Illuminate\Support\Facades\Validator' => 'Validator',
    ];
    if (! static::$aliasesRegistered) {
        static::$aliasesRegistered = true;
        $merged = array_merge($defaults, $userAliases);
        foreach ($merged as $original => $alias) {
            class_alias($original, $alias);
        }
    }
}



把门面类注册到系统中....



 

再看看门面类:
Illuminate\Support\Facades\Facade.php

//其实 和 app() 获取到的对象是一个  instanceof   true
public static function getFacadeApplication(){
    return static::$app;
}

//设置app容器进来,在哪里注册进来的呢? 向上看 withFacades 这个方法中 有这么一句: Facade::setFacadeApplication($this);
public static function setFacadeApplication($app){
    static::$app = $app;
}


/**
 * Handle dynamic, static calls to the object.
 *
 * @param  string  $method
 * @param  array   $args
 * @return mixed
 *
 * @throws \RuntimeException
 */
public static function __callStatic($method, $args)
{
    //去app容器中拿已经注册的服务
    $instance = static::getFacadeRoot();
    
    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }
    
    //动态去调用方法,把结果返回
    return $instance->$method(...$args);
}




这就是门面模式的运行原理。

再简单概述一下:(需要搞清楚一点,门面模式是使用静态方法去调用动态类的方法 把结果返回)


Log::info('门面模式log 写入');