特性 快速上手 框架工作流程 文件引用加载 访问路由编写 请求参数获取 表单数据验证 数据响应 AOP快速上手

 欢迎了解RestPHP,当前版本为3.1.0。

核心工程:https://gitee.com/sofical/restphp-core

应用工程:https://gitee.com/sofical/restphp

特性

支持路径参数,如:/users/{userId} 或 /users/{userId}/orders/{orderId}

支持AOP,通过使用@Aspect,可以快速实现切面逻辑开发

支持各种HTTP Method,支持Form表单、json、Xml的报文请求处理和响应

支持多语言设置

支持表单注解验证

快速上手

1.使用composer引入sofical/restphp-core到您的项目,参考命令:composer require sofical/restphp-core:dev-master

2.项目脚手架搭建(例:https://gitee.com/sofical/restphp ):
2.1.构建入口文件,如:bootstrap/index.php

                        
    define('PROJECT_ROOT', '../');

    // 自动加载composer包
    require(PROJECT_ROOT . 'vendor/autoload.php');

    //引入RESTPHP配置
    require(PROJECT_ROOT . 'config/rest.config.php');

    //引入项目配置
    require(PROJECT_ROOT . 'config/proj.config.php');

    //引入框架
    require(DIR_RESTPHP . '/Rest.php');

    \restphp\Rest::run();

                        
                    

2.2.将运行容器根目录配置到程序入口文件所在目录,如:bootstrap
配置URL重新规则,将所有请求地址重写到第一步的程序入口文件。如,Nginx重写配置:

    location / {
        index  index.php;
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php?$1 last;
        }
    }

                        


2.3.项目配置文件,必要内容为(目录建议为:config):
RESTPHP环镜配置文件,名称可自定义,如:rest.config.php

    //RESTPHP 相关配置
    define('REST_PHP_VERSION', '3.0');
    define('DIR_LIB', PROJECT_ROOT . 'lib');
    define('DIR_RESTPHP', PROJECT_ROOT . 'vendor/sofical/restphp-core/src');
    define('DIR_BUILD', PROJECT_ROOT . 'src/php');
    define('DIR_BUILD_TARGET', PROJECT_ROOT . 'runtime/target');
    define('HTTP_VERSION', '1.1');
    define('CONTENT_TYPE', 'application/json');
    define('SYS_TIME', time());
    define('SYS_MICRO_TIME', microtime(true));

                    

项目配置文件,文件名称可自定义,如:proj.config.php

    //当前环镜
    define('PROJ_ENV', 'dev');

    //环镜参数
    $_EVN_PARAM_ALL = include('env.config.php');
    $_EVN_PARAM = $_EVN_PARAM_ALL[PROJ_ENV];
    $_DB_MYSQL = isset($_EVN_PARAM) ? $_EVN_PARAM['DATABASE_MYSQL'] : array();

    //加载多语言
    $_LANG = include('lang.config.php');

    //日志目录
    define('APP_LOG_DIR', PROJECT_ROOT . 'runtime/log');

                        
项目配置文件,文件名称可自定义,如:proj.config.php

    //当前环镜
    define('PROJ_ENV', 'dev');

    //环镜参数
    $_EVN_PARAM_ALL = include('env.config.php');
    $_EVN_PARAM = $_EVN_PARAM_ALL[PROJ_ENV];
    $_DB_MYSQL = isset($_EVN_PARAM) ? $_EVN_PARAM['DATABASE_MYSQL'] : array();

    //加载多语言
    $_LANG = include('lang.config.php');

    //日志目录
    define('APP_LOG_DIR', PROJECT_ROOT . 'runtime/log');

                    
多语言配置文件,文件名称和上一步$_LANG定义一致,如:lang.config.php

    return array(
        'zh-cn' => array(
            '[REST_DB_UNKNOWN_EXCEPTION]' => '数据库未知异常',
            '[REST_DB_NOT_SUPPORT_DB_LINK]' => '不支持的数据库链接方式',
            '[REST_DB_HOST_REFUSED]' => '数据库链接失败',
            '[REST_DB_CONFIG_NOT_EXISTS]' => '数据库配置不存在'
        )
    );

                    
项目环镜差异化配置文件。配置文件名称和2.3的$_EVN_PARAM定义一致,如:env.config.php

    return array(
        'dev' => array(
            'DATABASE_MYSQL' => array(
                'DB_PREFIX' => '', //表前缀
                    'Def_Select'	=> array(	//查询库,一般是从库或只读库
                    'dbhost'	=> '127.0.0.1',
                    'dbport'	=> 3306,
                    'dbuser'	=> 'root',
                    'dbpass'	=> '123456',
                    'dbname'	=> 'restphp-example',
                    'charset'	=> 'UTF8',
                    'dbtype'	=> 1,
                    'linktype'	=> 1,
                    'fetchtype'	=> 1
                ),
                'Def_Update'	=> array(	//有数据修改权限的库,一般指主库
                    'dbhost'	=> '127.0.0.1',
                    'dbport'	=> 3306,
                    'dbuser'	=> 'root',
                    'dbpass'	=> '123456',
                    'dbname'	=> 'restphp-example',
                    'charset'	=> 'UTF8',
                    'dbtype'	=> 1,
                    'linktype'	=> 1,
                    'fetchtype'	=> 1
                )
            )
        ),
        'pro' => array(
            'DATABASE_MYSQL' => array(
                'DB_PREFIX' => '', //表前缀
                'Def_Select'	=> array(	//查询库,一般是从库或只读库
                    'dbhost'	=> '127.0.0.1',
                    'dbport'	=> 3306,
                    'dbuser'	=> 'root',
                    'dbpass'	=> '123456',
                    'dbname'	=> 'restphp-example',
                    'charset'	=> 'UTF8',
                    'dbtype'	=> 1,
                    'linktype'	=> 1,
                    'fetchtype'	=> 1
                ),
                'Def_Update'	=> array(	//有数据修改权限的库,一般指主库
                    'dbhost'	=> '127.0.0.1',
                    'dbport'	=> 3306,
                    'dbuser'	=> 'root',
                    'dbpass'	=> '123456',
                    'dbname'	=> 'restphp-example',
                    'charset'	=> 'UTF8',
                    'dbtype'	=> 1,
                    'linktype'	=> 1,
                    'fetchtype'	=> 1
                )
            )
        )
    );

                    

2.4. 创建测试路由文件,src/php/example/ControllerIndex.php

    namespace example;

    use restphp\http\RestHttpResponse;/**
     * @RequestMapping("")
     */
    class ControllerIndex {
        /**
         * @RequestMapping("/hello", method="GET")
         * @return void
         */
        public function index() {
            RestHttpResponse::html("hello world!");
        }
    }

                    

2.5. 构建路由,项目根目录下创建一个文件,如:build.php

    /**
     * 构建入口
     * @author sofical
     * @date 2017-03-17
     */

    define('PROJECT_ROOT', '');

    // 自动加载composer包
    require(PROJECT_ROOT . 'vendor/autoload.php');

    //引入目录配置
    require('config/rest.config.php');

    //引入框架
    require(DIR_RESTPHP . '/Rest.php');

    \restphp\Rest::build();

                        
运行命令:php build.php 构建路由映射关系

2.6. 访问项目地址,如:http://127.0.0.1/hello 。输出:hello world!

框架工作流程

使用说明

文件引用加载

文件支持自动加载,不需要在逻辑代码中使用require或include。其中自动加载的区域分为了两块区域。

1、项目代码区,即 DIR_BUILD 下的项目文件。

2、lib区,即DIR_LIB下的文件。lib区一般用于第三方引用插件代码。

文件加载机制是通过命名空间和类名进行自动查询匹配,因此 类名需要和文件名保持一致

访问路由编写

使用注解@RequestMapping,参数:value、method

现在也可以使用动作关键词注解,如:@Get,@Post,@Put,@Delete,@Patch,不需要method参数。

value 在class和function中都有效,值可以是一个或多,一个时,可以直接写为:value="/index.html"。多个时,应该写为:value=["/", "/index.html", "/index"]

method HTTP谓词(方法),即:GET、POST、PUT、DELETE、PATCH等,不区分大小写,建议使用大写。

完整示例:


    /**
    * 首页路由.
    * @RequestMapping("")
    */
    class IndexController {
        /**
        * 首页.
        * @RequestMapping(value=["/", "/index.html", "/index"], method="GET")
        */
        public function index() {
            // put your logic here
            echo "hello moto!";
        }
    }

                    

请求参数获取

路径参数
路径参数使用RestHttpRequest::getPathValue()方法获取。注:多路由不支持路径参数。

访问地址/users/97,获取用户ID:97


    /**
     * @RequestMapping("/users")
     */
    class UserController {
        /**
         * @RequestMapping(value="/{userId}", method="GET")
         */
        public function userInfo() {
            $userId = RestHttpRequest::getGet("userId");
            echo $userId;
        }
    }

                            
Query参数
Query参数使用RestHttpRequest::getGet() 或 RestHttpRequest::getParameterAsObject() 获取;使用 RestHttpRequest::getPageParam() 获取分页对象。

其中RestHttpRequest::getGet() 用于获取单个路径参数,RestHttpRequest::getParameterAsObject() 用于以对象的形式获取一个或多个参数。

1.RestHttpRequest::getGet()应用举例

访问地址/users?name=张,获取name参数值:


    /**
     * @RequestMapping("/users")
     */
    class UserController {
        /**
         * @RequestMapping(value="", method="GET")
         */
        public function userList() {
            $name = RestHttpRequest::getGet("name");
            echo $name;
        }
    }

                            


2.RestHttpRequest::getParameterAsObject()应用举例

访问路径`/users?name=张&mobile=1360000`,获取name和mobile的查询对象

定义接收对象,QueryForm:

    final class QueryForm {
        private $_name;
        private $_mobile;
        public function getName() {
            return $this->_name;
        }
        public function setName($name) {
            $this->_name = $name;
        }
        public function getMobile() {
            return $this->_mobile;
        }
        public function setMobile($mobile) {
            $this->_mobile = $mobile;
        }
    }

                            
在UserController中,使用RestHttpRequest::getParameterAsObject()方法获取QueryForm对象:

    /**
     * @RequestMapping("/users")
     */
    class UserController {
        /**
         * @RequestMapping(value="", method="GET")
         */
        public function userList() {
            $queryForm = RestHttpRequest::getParameterAsObject(new QueryForm());
            var_export($queryForm);
        }
    }

                            
Body参数
Body 参数使用 RestHttpRequest::getBody() 获取。

应用举例,获取body内容:{"username":"小红","mobile":"13800000000","age":"18"}

定义接收对象,UserForm:

    final class UserForm {
        private $_name;
        private $_mobile;
        private $_age;
        public function getName() {
            return $this->_name;
        }
        public function setName($name) {
            $this->_name = $name;
        }
        public function getMobile() {
            return $this->_mobile;
        }
        public function setMobile($mobile) {
            $this->_mobile = $mobile;
        }
        public function getAge() {
            return $this->_age;
        }
        public function setAge($age) {
            $this->_age = $age;
        }
    }

                            
在UserController中,使用RestHttpRequest::getBody()方法获取UserForm对象,或者获取为数组:

    /**
     * @RequestMapping("/users")
     */
    class UserController {
        /**
         * @RequestMapping(value="", method="POST")
         */
        public function newUser() {
            //获取为对象
            $userForm = RestHttpRequest::getBody(new UserForm());
            var_export($userForm);
            //获取为数组
            $arrUser = RestHttpRequest::getBody();
            var_dump($arrUser);
        }
    }

                            

表单数据验证

框架提供了以下注解表单验:

@length(min=最小长度,max=最大长度,message=错误提示:xxx长度只能在[最小长度]至[最大长度]之间)

@notnull(message=错误提示:xxx不能为空)

@mobile(message=错误提示:xxx不是正确的手机号)

@email(message=错误提示:xxx不是正确的邮箱地址)

@domain(message=错误提示:xxx不是正确的域名)

@date(format=日期格式,message=错误提示:xxx不符合日期格式)

@range(min=最小值,max=最大值,message=错误提示:xxx的值不在[最小值]到[最大值]范围内)

@int(min=最小值,max=最大值,message=错误提示:xxx的值不在[最小值]到[最大值]范围内或不是整数)

@ipv4(message=错误提示:xxx不是正确的ipv4地址)

@ipv6(message=错误提示:xxx不是正确的ipv6地址)

@inArray(value=[可选值1|可选值2],message=错误提示:xxx不在取值范围内)

@notEmpty(message=错误提示:xxx不能为空)

@customer(method=自定义校验方法,message=错误提示)

使用示例:

创建MessageVo:

    namespace classes\controller\api\vo;

    /**
     * Class MessageVo
     * @package classes\controller\api\vo
     */
    class MessageVo {
        /**
         * 客户名称.
         * @length(min=1,max=20,message=名字输入长度为1~20个字符)
         * @var string.
         */
        private $_name;

        /**
         * 感兴趣的产品.
         * @length(min=1,max=50,message=感兴趣的产品输入长度为1-50个字符)
         * @var string
         */
        private $_product;

        /**
         * 手机号码.
         * @mobile(message=手机号不正确)
         * @var string
         */
        private $_mobile;

        /**
         * 更多说明
         * @length(max=255,message=更多说明长度不能超过255字)
         * @var string
         */
        private $_more;

        /**
         * @return string
         */
        public function getName()
        {
            return $this->_name;
        }

        /**
        * @param string $name
        */
        public function setName($name)
        {
            $this->_name = $name;
        }

        /**
        * @return string
        */
        public function getProduct()
        {
            return $this->_product;
        }

        /**
        * @param string $product
        */
        public function setProduct($product)
        {
            $this->_product = $product;
        }

        /**
        * @return string
        */
        public function getMobile()
        {
            return $this->_mobile;
        }

        /**
        * @param string $mobile
        */
        public function setMobile($mobile)
        {
            $this->_mobile = $mobile;
        }

        /**
        * @return string
        */
        public function getMore()
        {
            return $this->_more;
        }

        /**
        * @param string $more
        */
        public function setMore($more)
        {
            $this->_more = $more;
        }
    }

                            
在MessagesController使用:

    namespace classes\controller\api;

    use classes\controller\api\vo\MessageVo;
    use classes\service\CrmMessageService;
    use restphp\http\RestHttpRequest;
    use restphp\validate\RestValidate;

    /**
     * Class MessagesController
     * @RequestMapping(value="/api/messages")
     * @package classes\controller\api
     */
    class MessagesController {
        /**
         * 接收消息.
         * @RequestMapping(value="", method="POST")
         * @throws \ReflectionException
         */
        public function receiveMessage() {
            $message = RestHttpRequest::getRequestBody(new MessageVo(), true);

            CrmMessageService::saveMessage($message);
        }
    }

                            

数据响应

数据响应为开放自由式响应,无特殊固定规则和格式。

框架的RestHttpResponse类提供常用数据响应方法封状;RestTpl类提供了简单的模板引擎。

AOP快速上手

自定义一个切面逻辑片段:\example\annotation\AopExample

    namespace example\annotation;

    use restphp\aop\AopParam;
    use restphp\aop\Aspect;

    /**
     * @Aspect(name="AopExample")
     */
    class AopExample implements Aspect
    {
        /**
         * @param AopParam $aopParam
         * @return void
         */
        function before($aopParam)
        {
            // TODO: Implement before() method.
            echo "aop before executed with params:\n ";
            var_dump($aopParam->getProcessParam());
        }

        /**
         * @param AopParam $aopParam
         * @return void
         */
        function after($aopParam)
        {
            // TODO: Implement after() method.
        }

    }

                            


使用AOP(需构建后运行引用代码查看效果):

    namespace example\controller;

    use restphp\tpl\RestTpl;

    /**
     * @RequestMapping(value="/tpl")
     */
    class ControllerTplTest {
        private $_tpl;
        public function __construct() {
            $GLOBALS['_EVN_PARAM']['TPL_DIR'] = PROJECT_ROOT . 'src/resources/template/default';
            $GLOBALS['_EVN_PARAM']['TPL_CACHE_DIR'] = PROJECT_ROOT . 'runtime/template';
            $this->_tpl = new RestTpl();
            $this->_tpl->caching = false;
        }

        /**
         * @Get (value = "")
         * @AopExample(param1="test",param2="test2")
         * @return void
         */
        public function index() {
            $this->_tpl->assign('app_name', 'RESTPHP 3.0');
            $this->_tpl->display('index.tpl');
        }
    }

                            
闽ICP备20006964号-1