• laravel5.5门面


    Facades为应用程序的 服务容器 中可用的类提供了一个 静态接口

    • 最直观的好处

    就是需记住必须手动注入或配置的长长的类名。因此有人也理解Facades就是一个“快捷别名”

    怎么变得更快捷呢?

    # 使用make 去访问注册日志对象的info方法
    $container->make('log')->info('message')
    
    # 使用arrayaccess的方式
    $container["log"]->info('message')
    
    # 使用Facade访问Logger对象的info方法, 不需要使用容器去获取一个对象。
    Log::info('message');
    
    • 主要风险

    会引起类作用范围的膨胀。因为 Facades 使用起来非常简单而且不需要注入,就会使得我们在不经意间在单个类中使用许多 Facades,从而导致类变的越来越大。
    而使用依赖注入的时候,使用的类越多,构造方法就会越长,在视觉上就会引起注意,提醒你这个类有点庞大了。

    • 在laravel中有许多辅助函数的功能都有与之对应的 Facade。

    例如,下面这个 Facade 的调用和辅助函数的作用是一样的:

    return View::make('profile');
    
    return view('profile');
    
    • Facades的工作原理

    文件位于IlluminateSupportFacades目录下

    我们分析Cache 类

    <?php
    
    namespace AppHttpControllers;
    
    use IlluminateSupportFacadesCache;
    use AppHttpControllersController;
    
    class UserController extends Controller
    {
        /**
         * 显示给定用户的信息。
         *
         * @param  int  $id
         * @return Response
         */
        public function showProfile($id)
        {
            $user = Cache::get('user:'.$id);
    
            return view('profile', ['user' => $user]);
        }
    }
    

    我们打开IlluminateSupportFacadesCache 这个类,你会发现类中根本没有 get 这个静态方法:

    <?php
    
    namespace IlluminateSupportFacades;
    
    /**
     * @see IlluminateCacheCacheManager
     * @see IlluminateCacheRepository
     */
    class Cache extends Facade
    {
        /**
         * Get the registered name of the component.
         *
         * @return string
         */
        protected static function getFacadeAccessor()
        {
            return 'cache';
        }
    }
    

    既然没有那么我们去他的父类看看,父类也没有get方法,但是有个魔术方法__callStatic(),当找到不method的时候自动调用这个方法,顺着这个方法继续探究

    Facades.php 的核心代码分析

        /**
         * Get the root object behind the facade.
         *
         * @return mixed
         */
        public static function getFacadeRoot()
        {
            //2. 这里调用了getFacadeAccessor() 也就是Cache.php中的这个方法,返回了字符串‘cache’
            return static::resolveFacadeInstance(static::getFacadeAccessor());
        }
    
        /**
         * Get the registered name of the component.
         *
         * @return string
         *
         * @throws RuntimeException
         */
        protected static function getFacadeAccessor()
        {
            throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
        }
    
        /**
         * Resolve the facade root instance from the container.
         *
         * @param  string|object  $name
         * @return mixed
         */
        protected static function resolveFacadeInstance($name)
        {
            if (is_object($name)) {
                return $name;
            }
    
            if (isset(static::$resolvedInstance[$name])) {
                return static::$resolvedInstance[$name];
            }
            
            // 3. 调用了当前类的静态属性,其实最终获取的就是$app['cache'],那么这个属性是怎么初始化的呢,原来在laravel启动的时候调用了setFacadeApplication()
            
            return static::$resolvedInstance[$name] = static::$app[$name];
        }
    
        /**
         * Get the application instance behind the facade.
         *
         * @return IlluminateContractsFoundationApplication
         */
        public static function getFacadeApplication()
        {
            return static::$app;
        }
    
        /**
         * Set the application instance.
         *
         * @param  IlluminateContractsFoundationApplication  $app
         * @return void
         */
        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)
        {
            //1. 当找不到method的时候,调用__callStatic()
            $instance = static::getFacadeRoot();  
            
            //4. 通过分析返回的$instance就是容器中的$app['cache']实例
            if (! $instance) {
                throw new RuntimeException('A facade root has not been set.');
            }
    
            //5。 调用上面实例的方法
            return $instance->$method(...$args);
        }
    

    继续分析上面标注4得到的$app['cache'],我们找到IlluminateCacheCacheServiceProvider.php

        public function register()
        {
            $this->app->singleton('cache', function ($app) {
                return new CacheManager($app);
            });
    
            $this->app->singleton('cache.store', function ($app) {
                return $app['cache']->driver();
            });
    
            $this->app->singleton('memcached.connector', function () {
                return new MemcachedConnector;
            });
        }
    

    会发现绑定了单例,返回了new CacheManager($app)对象,想进一步探究可以查看这个CacheManager类,再次不再继续探究。

    通过以上我们其实已经明白了门面的套路。

  • 相关阅读:
    研究动态扩容数据库解决方案
    研究分布式唯一ID生成,看完这篇就够
    聊聊心跳机制及netty心跳实现
    聊聊微服务熔断降级Hystrix
    聊聊ReentrantLock的内部实现
    Python迭代器和生成器
    Flask容器化部署原理与实现
    WSGI到底是什么?
    Tensorflow基础
    Python字典 你必须知道的用法系列
  • 原文地址:https://www.cnblogs.com/redirect/p/8658702.html
Copyright © 2020-2023  润新知