阅读 450

PHP之__call()方法和__callStatic()方法

在php的面向对象里,用得最多的魔术方法一定是__construct方法。而在很多很多地方,__call方法和__callStatic方法用得地方一样很多,而且特别好用呢。下面举个应用的例子。

这里就拿yansongda pay来举例子。这个是集成了微信和支付宝的支付相关的插件。

class Pay {
    /**
     * 定义Config配置.
     *
     * @var Config
     */
    protected $config;
    
    /**
     * 构造.
     *
     * @param array $config
     */
    public function __construct(array $config) 
        {
        $this->config = new Config($config)
    }
    
     /**
     * Magic static call.
     *
     * @param string $method
     * @param array  $params
     *
     * @return GatewayApplicationInterface
     */
    public function __callStatic($method, $params) 
    {
        $app = new self(...$params);
        return $app->create($method);
    }
    
    /**
     * Create a instance. 创建一个实例
     *
     * @param string $method
     *
     * @return GatewayApplicationInterface
     */
    protected function create() 
    {
        // 这里简化一下 注册日志就不写了
        $gateway = __NAMESPACE__.'\\Gateways\\'.Str::studly($method);
        
        if (class_exists($gateway)) {
            return self::make($gateway);
        }
        throw new InvalidGatewayException("Gateway [{$method}] Not Exists");
    }
    
    /**
     * Make a gateway. 实现一个支付入口
     *
     * @param string $gateway
     *
     * @return GatewayApplicationInterface
     */
    protected function make($gateway) 
    {
        $app = new $gateway($this->config);
        
        if ($app instanceof GatewayApplicationInterface) {
            return $app;
        }
        
        throw new InvalidGatewayException("Gateway [$gateway] Must Be An Instance Of GatewayApplicationInterface")
    }
}
复制代码

上面就是一个比较完整的过程了。
这个名为class Pay的很好起到了一个将不同的支付需求分发出去。

// 假设这里已经写好了Pay类的命名空间
// 如果是微信支付,那么可以这么写
$config = [
    ...
];
$wechat = Pay::Wechat($config)  // 创建Wechat类的实例

// 如果是支付宝,那么..
$config = [
    ...
];
$alipay = Pay::Alipay($config)  // 创建Alipay类的实例
复制代码

为什么可以达到这个效果呢,整个流程:

  • 首先调用了Pay类的静态方法,比如是Wechat
  • 结果,没有找到,就会自动调用class Pay__callStatic魔术方法。
  • 然后new self(...$params) 这样就是为了调用后面的create($method),并且将传过来的$config进行储存。
  • 后面接着create方法里 找到对应的Wechat类,并进行instanceof判断。
  • 最后在make方法里 实例化 Wechat类

小总结:这样是为了对于有不同情况,想对它们进行清晰的分类,而实现的一个统一入口类Pay。后面比如,alipay,肯定会涉及到移动端支付,PC网页支付,app支付各种情况。那么同样又可以使用这个方法,找到对应的类,进行实例化,调用方法。以后如果是自己封装方法,大家可以尝试效仿。

最后__call方法其实和__callStatic类似 只是用->调用而已。

关注下面的标签,发现更多相似文章
评论