利用PHP反射机制,实现参数自动绑定

<?php
// 利用PHP反射机制,实现参数自动绑定
// 文件:php_testreflection.php

/**
 * 接口处理器基类
 * Class ApiBaseHandler
 */
class ApiBaseHandler {
    /**
     * 原始的参数
     * @var array
     */
    protected $params;

    public function __construct($params = []) {
        $this->params = $params;

        // 必须定义run方法,其为内部调用入口
        if (!method_exists($this, 'run')) {
            throw new \Exception('method [run] undefined');
        }
    }

    /**
     * 外部调用接口
     * @return ApiResult|mixed
     */
    public function call() {
        try {
            $method = 'run';
            $params = $this->getMethodParams($method);
            return call_user_func_array([$this, $method], $params);
        } catch(\Exception $e) {
            return ApiResult::error($e->getMessage());
        }
    }

    /**
     * 获取方法的参数
     * @param string $method
     * @return array
     * @throws ReflectionException
     */
    protected final function getMethodParams($method) {
        $params = [];
        $defines = $this->getMethodParamDefines($method);
        foreach ($defines as $define) {
            $name = $define->name;
            if (key_exists($name, $this->params)) {
                $params[$name] = $this->params[$name];
            } elseif ($define->isDefaultValueAvailable()) {
                $params[$name] = $define->getDefaultValue();
            } else {
                throw new \Exception("parameter [{$name}] undeined");
            }
        }
        return $params;
    }

    /**
     * 获取方法的参数定义
     * @param string $method
     * @return ReflectionParameter[]
     * @throws ReflectionException
     */
    protected final function getMethodParamDefines($method) {
        return (new \ReflectionMethod($this, $method))->getParameters();
    }
}

class ApiResult {
    const CODE_SUCCESS = 0;
    const CODE_ERROR = 1;

    private $code;
    private $msg;
    private $data;

    public function __construct($code, $msg, $data) {
        $this->code = $code;
        $this->msg = $msg;
        $this->data = $data;
    }

    public static function success($data = [], $msg = '') {
        return self::result(self::CODE_SUCCESS, $msg, $data);
    }

    public static function error($msg, $data = []) {
        return self::result(self::CODE_ERROR, $msg, $data);
    }

    private static function result($code, $msg, $data) {
        return new self($code, $msg, $data);
    }

    public function isSuccess() {
        return $this->code == self::CODE_SUCCESS;
    }

    public function isError() {
        return $this->code == self::CODE_ERROR;
    }

    public function toArray() {
        return [
            'code' => $this->code,
            'msg' => $this->msg,
            'data' => $this->data,
        ];
    }
}

/**
 * 用户信息获取接口处理器
 * Class UserInfoHandler
 */
class UserFindHandler extends ApiBaseHandler {
    /**
     * 内部调用入口
     * @param int $id
     * @param string $name
     * @return ApiResult
     */
    protected function run($id, $name) {
        $data = [ __METHOD__ . " id:{$id} name:{$name}"];
        return ApiResult::success($data);
    }
}

/**
 * 文档信息获取接口处理器
 * Class DocumentInfoHandler
 */
class DocumentFindHandler extends ApiBaseHandler {
    /**
     * 内部调用入口
     * @param int $id
     * @param string $title
     * @return ApiResult
     */
    protected function run($id, $title = '') {
        $data = [__METHOD__ . " id:{$id} title:{$title}"];
        return ApiResult::success($data);
    }
}

// 以上定义了一些类,接下来就测试一下
// 在命令行运行php php_testreflection.php即可

// 正常跑一跑
$params = ['id'=>1, 'age'=>12, 'name'=>'Li'];
$handler = new UserFindHandler($params);
print_r($handler->call()->toArray());

$params = ['id'=>1, 'title'=>'PHP document', 'noise'=>'wowowo'];
$handler = new DocumentFindHandler($params);
print_r($handler->call()->toArray());

// 这里出一下错
$params = ['noise'=>'wowowo'];
$handler = new DocumentFindHandler($params);
print_r($handler->call()->toArray());


// 最终输出如下:
/*
Array
(
    [code] => 0
    [msg] =>
    [data] => Array
    (
        [0] => UserFindHandler::run id:1 name:Li
    )
)
Array
(
    [code] => 0
    [msg] =>
    [data] => Array
    (
        [0] => DocumentFindHandler::run id:1 title:PHP document
    )
)
Array
(
    [code] => 1
    [msg] => parameter [id] undeined
    [data] => Array
    (
    )
)
*/

 

很多框架的action都支持自动绑定参数,估计就是类似方式实现的,^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值