简单实现类似laravel的Facades『静态代理』

神手小生

在 Laravel 应用中,Facade 就是一个可以从容器访问对象的类。其中核心的部件就是 Facade 类。不管是 Laravel 自带的 Facades,还是自定义的 Facades,都继承自 Illuminate\Support\Facades\Facade 类。

Facade 基类使用了__callStatic() 魔术方法,直到对象从容器中被解析出来后,才会进行调用。

webman已经有安装Illuminate相关扩展包,我们只要重写__callStatic() 魔术方法即可实现,其实很简单,就是把自定义的xxFacade类注入到容器中即可。

废话不多说,开整

1,安装illuminate/container 扩展

composer require illuminate/container

2,创建app\Facade\Facade.php 门面类

<?php
namespace app\Facade;

use Illuminate\Support\Facades\Facade as MainFacade;
use support\Container;

/**
 * 以服务容器方式重写
 *
 * @package app\Facade
 */
class Facade extends MainFacade
{
    /**
     * 重写私有魔术方法
     *
     * @return mixed
     */
    public static function __callStatic($method, $args)
    {
        if (!Container::has(static::getFacadeAccessor())) {
            Container::make(static::getFacadeAccessor(), $args);
        }
        return Container::get(static::getFacadeAccessor())->$method(...$args);
    }
}

3,创建一个 app\Facade\TestFacade,只要继承重写的Facade即可

<?php
namespace app\Facade;

use app\Facade\Accessor\TestAccessor;

/**
 * Class TestFacade
 * @method static set($data)
 * @method static get()
 * @package app\Facade
 */
class TestFacade extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return TestAccessor::class;
    }
}

4,创建实现 app\Facade\Accessor\TestAccessor 实现类

<?php
namespace app\Facade\Accessor;

/**
 * Class TestAccessor
 * @package app\Facade\Accessor
 */
class TestAccessor
{
    /**
     * @var $data
     */
    private $data;

    /**
     * 设置
     * 
     * @param $data
     * @return $this
     */
    public function set($data): TestAccessor
    {
        $this->data = $data;
        return $this;
    }

    /**
     * 获取
     * 
     * @return mixed
     */
    public function get()
    {
        return $this->data;
    }
}

5,现在就可以像laravel一样使用门面类了

## 设置数据
TestFacade::set('hello');

## 获取数据
TestFacade::get()

昨天用webman做一个小业务,看了下社区没有合适的插件和分享,就简单的处理下。不对的地方望指正,有时间的伙伴可以按这个思路将其封装插件或扩展包,方便需要用的伙伴使用。

感谢

429 4 2
4个评论

lake

Facades 解决了什么问题

  • 暂无评论
holly188

不建议使用这种方式,会影响IDE的代码分析,反而降低了开发体验。

释永战

很好,但是推荐使用webman

  • 暂无评论
ersic

感谢分享

  • 暂无评论

神手小生

220
积分
0
获赞数
0
粉丝数
2023-11-30 加入
×
🔝