欢迎了解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();
location / {
index index.php;
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php?$1 last;
}
}
//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));
//当前环镜
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
)
)
)
);
namespace example;
use restphp\http\RestHttpResponse;/**
* @RequestMapping("")
*/
class ControllerIndex {
/**
* @RequestMapping("/hello", method="GET")
* @return void
*/
public function index() {
RestHttpResponse::html("hello world!");
}
}
/**
* 构建入口
* @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 构建路由映射关系
文件支持自动加载,不需要在逻辑代码中使用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!";
}
}
/**
* @RequestMapping("/users")
*/
class UserController {
/**
* @RequestMapping(value="/{userId}", method="GET")
*/
public function userInfo() {
$userId = RestHttpRequest::getGet("userId");
echo $userId;
}
}
/**
* @RequestMapping("/users")
*/
class UserController {
/**
* @RequestMapping(value="", method="GET")
*/
public function userList() {
$name = RestHttpRequest::getGet("name");
echo $name;
}
}
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);
}
}
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);
}
}
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);
}
}
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.
}
}
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');
}
}