理解 laravel 的 facade
24 June 2018

facade 的好处

laravel facade 的好处是不用每次都去 new 一个 object ,而是通过静态调用,例如

// 不使用 facade
$route = new Route();
$route->get('/', function () {
    echo 'ok' . PHP_EOL;
});

// 使用 facade
Route::get('/', function () {
    echo 'ok' . PHP_EOL;
});


// 不使用 facade
$cache = new Cache();
$cache->set('key', 'value');
$cache->get('key');

// 使用 facade
Cache::set('key', 'value');
Cache::get('key');

如何实现 facade

Service/RouteService.php (#真正进行路由处理的类)

class RouteService
{
    /**
     * @var RouteInterface
     */
    protected $route;    // 这里可以注入 FastRoute 等路由实体

    public function __construct(RouteInterface $route)
    {
        $this->route = $route;
    }

    public function get($route, $handler)
    {
        // ...
        // return $this->route->get(route, $handler);
    }
}

Facade.php

abstract class Facade
{
    /**
     * @var ContainerInterface
     */
    private static $app;

    public static function setContainer(ContainerInterface $app)
    {
        static::$app = $app;
    }

    public static function getFacadeService()
    {

    }

    public static function __callStatic($method, $args)
    {
        $name = static::getFacadeService();
        $service = static::$app->get($name);  // 从容器里面取出对应的 service
        if (!$service) {
            throw new RuntimeException("facade service not found!");
        }

        return $service->$method(...$args);
    }
}

Facade/RouteFacade.php

class RouteFacade extends Facade
{
    public static function getFacadeService()
    {
        return 'route';
    }
}

bootstrap.php

$app = new Container();
Facade::setContainer($app);

$app->set('route', RouteService::class);

test.php

require '/path/to/bootstrap.php';

use RouteFacade as Route;

Route::get('/', function () {
    echo 'ok' . PHP_EOL;
});