Lumen 5创建Facade类

来源:互联网 发布:java获取时间毫秒数 编辑:程序博客网 时间:2024/05/29 13:41

Laravel的Facade,实际上是对service container中的service provider的一层包装,使用魔术方法__callStatic调用service provider类的方法。拿Log Facade来探究一下。

<?phpnamespace Illuminate\Support\Facades;/** * @see \Illuminate\Log\Writer */class Log extends Facade{    /**     * Get the registered name of the component.     *     * @return string     */    protected static function getFacadeAccessor()    {        return 'log';    }}

Facade类只需要重写父类中的getFacadeAccessor方法,返回一个字符串即可。
返回的log代表什么,有什么用?

到框架的service container里看个究竟

<?phpnamespace Laravel\Lumen;use Monolog\Logger;use Illuminate\Support\Str;use Illuminate\Http\Request;use Illuminate\Support\Composer;use Monolog\Handler\StreamHandler;use Illuminate\Container\Container;use Monolog\Formatter\LineFormatter;use Illuminate\Filesystem\Filesystem;use Illuminate\Support\Facades\Facade;use Illuminate\Support\ServiceProvider;use Zend\Diactoros\Response as PsrResponse;use Illuminate\Config\Repository as ConfigRepository;use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;class Application extends Container{    /**     * Register the core container aliases.     *     * @return void     */    protected function registerContainerAliases()    {        $this->aliases = [            'Illuminate\Contracts\Foundation\Application' => 'app',            'Illuminate\Contracts\Auth\Factory' => 'auth',            'Illuminate\Contracts\Auth\Guard' => 'auth.driver',            'Illuminate\Contracts\Cache\Factory' => 'cache',            'Illuminate\Contracts\Cache\Repository' => 'cache.store',            'Illuminate\Contracts\Config\Repository' => 'config',            'Illuminate\Container\Container' => 'app',            'Illuminate\Contracts\Container\Container' => 'app',            'Illuminate\Database\ConnectionResolverInterface' => 'db',            'Illuminate\Database\DatabaseManager' => 'db',            'Illuminate\Contracts\Encryption\Encrypter' => 'encrypter',            'Illuminate\Contracts\Events\Dispatcher' => 'events',            'Illuminate\Contracts\Hashing\Hasher' => 'hash',            'log' => 'Psr\Log\LoggerInterface',    // 重点在这里            'Illuminate\Contracts\Queue\Factory' => 'queue',            'Illuminate\Contracts\Queue\Queue' => 'queue.connection',            'request' => 'Illuminate\Http\Request',            'Laravel\Lumen\Routing\UrlGenerator' => 'url',            'Illuminate\Contracts\View\Factory' => 'view',        ];    }    /**     * Register container bindings for the application.     *     * @return void     */    protected function registerLogBindings()    {        $this->singleton('Psr\Log\LoggerInterface', function () {            if ($this->monologConfigurator) {                return call_user_func($this->monologConfigurator, new Logger('lumen'));            } else {                return new Logger('lumen', [$this->getMonologHandler()]);            }        });    }}

当我们调用Log::info时,实际上调用的是Psr\Log\LoggerInterface的info方法,Psr\Log\LoggerInterface可以看做Log的代理,Log有需要时,转发给代理,由代理决定具体的执行。有了Facade,代码可读性更高,不需要解具体的内部实现。

进一步说

Log::info()// 等同于app('log')->info()  // app('log')创建了什么?请看Application::registerLogBindings

开始创建一个Facade

第一步,实现一个service provider

代码大致如下

<?phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;use Illuminate\Http\Request;use App\Logger;/** * Class LogServiceProvider * @package App\Providers */class LogServiceProvider extends ServiceProvider{    public function register()    {        // TODO: Implement register() method.        $this->app->singleton('mylog', function($app) {            return new Logger();        });    }}

第二步,注册service provider

在bootstrap/app.php文件添加代码

$app->register(App\Providers\LogServiceProvider::class);

第三步,创建Facade类

<?phpnamespace App\Library\Facade;use Illuminate\Support\Facades\Facade;class Mylog extends Facade{    public static function getFacadeAccessor()    {        return 'mylog';    }}

就是这么简单。

容易看出,Facade类带来了好处,也带来了坏处,比如:PHPStorm的代码跟踪就拿Facade无能为力了。

关于Laravel 5 Service container与service provider,可以参考
Laravel5 container & service provider

0 0