Lumen 5创建Facade类

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

/**
 * @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里看个究竟



namespace 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

代码大致如下


namespace 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类


namespace 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

你可能感兴趣的:(laravel5,php)