@@ -0,0 +1,129 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2016/10/12 | |||
* Time: 10:56 | |||
*/ | |||
require_once __DIR__ . '/../Utils/commonUtil.class.php'; | |||
class DataBaseConfig | |||
{ | |||
//正式数据库 | |||
private $MYSQL_HOST = "180.168.4.58"; | |||
private $MYSQL_USER = "root"; | |||
private $MYSQL_PASSWORD = "123456"; | |||
private $MYSQL_DB = "ctsdata"; | |||
private $MYSQL_PORT = "8090"; | |||
//测试数据库 | |||
private $MYSQL_HOST1 = "180.168.4.58"; | |||
private $MYSQL_USER1 = "root"; | |||
private $MYSQL_PASSWORD1 = "123456"; | |||
private $MYSQL_DB1 = "ctsdata_test"; | |||
private $MYSQL_PORT1 = "8090"; | |||
//waice数据库 | |||
private $MYSQL_HOST2 = "180.168.4.58"; | |||
private $MYSQL_USER2 = "root"; | |||
private $MYSQL_PASSWORD2 = "123456"; | |||
private $MYSQL_DB2 = "waice"; | |||
private $MYSQL_PORT2 = "8090"; | |||
//waice2数据库 | |||
private $MYSQL_HOST3 = "192.168.6.245"; | |||
private $MYSQL_USER3 = "root"; | |||
private $MYSQL_PASSWORD3 = "123456"; | |||
private $MYSQL_DB3 = "waice2"; | |||
private $MYSQL_PORT3 = "3306"; | |||
//Memcache配置 | |||
private $MEMCACHE_HOST = "139.224.30.29"; | |||
private $MEMCACHE_PORT = "11211"; | |||
private $MEMCACHE_USER = "memcached"; | |||
private $API_GPS_ACCOUNT = "15618818219"; | |||
private $API_GPS_PASSWORD = "123456"; | |||
/** | |||
* 链接正式数据库 | |||
* @return PDO | |||
*/ | |||
function conn() | |||
{ | |||
try { | |||
$pdo = new PDO("mysql:host=" . $this->MYSQL_HOST . ";port=" . $this->MYSQL_PORT . ";dbname=" . $this->MYSQL_DB, $this->MYSQL_USER, $this->MYSQL_PASSWORD, array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8")); | |||
return $pdo; | |||
} catch (PDOException $e) { | |||
utils::writeLog('new PDO failed:' . $e->getMessage()); | |||
} | |||
} | |||
/** | |||
* 链接测试数据库 | |||
* @return PDO | |||
*/ | |||
function conn_test() | |||
{ | |||
try { | |||
$pdo = new PDO("mysql:host=" . $this->MYSQL_HOST1 . ";port=" . $this->MYSQL_PORT1 . ";dbname=" . $this->MYSQL_DB1, $this->MYSQL_USER1, $this->MYSQL_PASSWORD1, array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8")); | |||
return $pdo; | |||
} catch (PDOException $e) { | |||
utils::writeLog('new PDO failed:' . $e->getMessage()); | |||
} | |||
} | |||
/** | |||
* 链接waice数据库 | |||
* @return PDO | |||
*/ | |||
function conn_waice() | |||
{ | |||
try { | |||
$pdo = new PDO("mysql:host=" . $this->MYSQL_HOST3 . ";port=" . $this->MYSQL_PORT3 . ";dbname=" . $this->MYSQL_DB3, $this->MYSQL_USER3, $this->MYSQL_PASSWORD3, array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8")); | |||
return $pdo; | |||
} catch (PDOException $e) { | |||
utils::writeLog('new PDO failed:' . $e->getMessage()); | |||
} | |||
} | |||
/** | |||
* 添加缓存 | |||
* @param $key | |||
* @param $value | |||
*/ | |||
public function set_memcache($key, $value) | |||
{ | |||
$mem = new Memcache; | |||
$mem->connect($this->MEMCACHE_HOST, $this->MEMCACHE_PORT); | |||
$mem->set($key, $value); | |||
} | |||
/** | |||
* 获取内存中的数据 | |||
* @param $key | |||
* @return array|string | |||
*/ | |||
public function get_memcache($key) | |||
{ | |||
$mem = new Memcache; | |||
$mem->connect($this->MEMCACHE_HOST, $this->MEMCACHE_PORT); | |||
$value = $mem->get($key); | |||
return $value; | |||
} | |||
/** | |||
* 删除键值对应的数据 | |||
* @param $key | |||
* @return bool | |||
*/ | |||
public function delete_memcache($key) | |||
{ | |||
$mem = new Memcache; | |||
$mem->connect($this->MEMCACHE_HOST, $this->MEMCACHE_PORT); | |||
$value = $mem->delete($key); | |||
return $value; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
<?php | |||
/** | |||
* 请在下面放置任何您需要的应用配置 | |||
*/ | |||
return array( | |||
/** | |||
* 应用接口层的统一参数 | |||
*/ | |||
'apiCommonRules' => array( | |||
//'sign' => array('name' => 'sign', 'require' => true), | |||
//客户端App版本号,如:1.0.1 | |||
'version' => array( | |||
'name' => 'version', 'default' => '', | |||
), | |||
), | |||
); |
@@ -0,0 +1,45 @@ | |||
<?php | |||
/** | |||
* 分库分表的自定义数据库路由配置 | |||
*/ | |||
return array( | |||
/** | |||
* DB数据库服务器集群 | |||
*/ | |||
'servers' => array( | |||
'db_demo' => array( //服务器标记 | |||
'host' => '106.14.56.77', //数据库域名 | |||
'name' => 'ctsdata_mirror', //数据库名字 | |||
'user' => 'spider', //数据库用户名 | |||
'password' => 'PjGPWNUgOYe6i1Ef', //数据库密码 | |||
'port' => '3306', //数据库端口 | |||
'charset' => 'UTF8', //数据库字符集 | |||
), | |||
), | |||
/** | |||
* 自定义路由表 | |||
*/ | |||
'tables' => array( | |||
//通用路由 | |||
'__default__' => array( | |||
'prefix' => '', | |||
'key' => 'id', | |||
'map' => array( | |||
array('db' => 'db_demo'), | |||
), | |||
), | |||
/** | |||
'demo' => array( //表名 | |||
'prefix' => 'pa_', //表名前缀 | |||
'key' => 'id', //表主键名 | |||
'map' => array( //表路由配置 | |||
array('db' => 'db_demo'), //单表配置:array('db' => 服务器标记) | |||
array('start' => 0, 'end' => 2, 'db' => 'db_demo'), //分表配置:array('start' => 开始下标, 'end' => 结束下标, 'db' => 服务器标记) | |||
), | |||
), | |||
*/ | |||
), | |||
); |
@@ -0,0 +1,26 @@ | |||
<?php | |||
/** | |||
* 以下配置为系统级的配置,通常放置不同环境下的不同配置 | |||
*/ | |||
return array( | |||
/** | |||
* 默认环境配置 | |||
*/ | |||
'debug' => true, | |||
/** | |||
* MC缓存服务器参考配置 | |||
*/ | |||
'mc' => array( | |||
'host' => '127.0.0.1', | |||
'port' => 11211, | |||
), | |||
/** | |||
* 加密 | |||
*/ | |||
'crypt' => array( | |||
'mcrypt_iv' => '12345678', //8位 | |||
), | |||
); |
@@ -0,0 +1,35 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/9 | |||
* Time: 22:52 | |||
* 默认接口服务类 | |||
*/ | |||
class Api_Default extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'index' => array( | |||
'username' => array('name' => 'username', 'default' => 'PHPer', ), | |||
), | |||
); | |||
} | |||
/** | |||
* 默认接口服务 | |||
* @return string title 标题 | |||
* @return string content 内容 | |||
* @return string version 版本,格式:X.X.X | |||
* @return int time 当前时间戳 | |||
*/ | |||
public function index() { | |||
return array( | |||
'title' => 'Hello World11111111!', | |||
'content' => T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), | |||
'version' => PHALAPI_VERSION, | |||
'time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
} | |||
} |
@@ -0,0 +1,320 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/12 | |||
* Time: 0:40 | |||
* 接口调用方:携程 | |||
* 接口返回方:合作方(us) | |||
*/ | |||
require_once dirname(__DIR__) . '/Common/Utils.php'; | |||
class Hotel | |||
{ | |||
public $obj_utils = ''; | |||
public $Currency = 'RMB'; | |||
public function __construct() | |||
{ | |||
$this->obj_utils = new roomOrderUtils(); | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:DomesticCheckRoomAvail (可定检查) | |||
* 1.接口调用方:携程 | |||
* 2.接口返回方:合作方 | |||
* 3.调用频率:订单量的10倍以上 | |||
* 4.使用说明:携程在给酒店下订单前,调用合作方接口。通过传入客人入住信息,得 到该房型是否可订。该接口响应时间(含网络)需要在3秒以内 | |||
*/ | |||
public function DomesticCheckRoomAvail() | |||
{ | |||
$rec_info = file_get_contents("php://input"); | |||
$OrderData = $this->obj_utils->data_to_xml($rec_info); //将xml转化成数组 | |||
$roomInfo = $OrderData['HotelGroupInterfaceRoomTypeListRequest']; | |||
$hotel = $roomInfo['Hotel']; //酒店编号 | |||
$Arrival = $roomInfo['Arrival ']; //到店日期 | |||
$Departure = $roomInfo['Departure ']; //离店日期 | |||
$Room = $roomInfo['Room ']; //房型编号 | |||
$CurrencyCode = $roomInfo['CurrencyCode ']; //币种(可空) | |||
$RoomNumber = $roomInfo['RoomNumber ']; //预定间数 | |||
$Person = $roomInfo['Person']; //入住人数 | |||
$BalanceType = $roomInfo['BalanceType']; //价格类型 | |||
foreach ($roomInfo['RoomPrices'] as $item) { | |||
$EffectDate = $item['EffectDate']; //入住日期 | |||
$Price = $item['Price']; //卖价 | |||
$CNYPrice = $item['CNYPrice']; //汇率后的卖价(可空) | |||
$Cost = $item['Cost']; //底价 | |||
$CNYCost = $item['CNYCost']; //汇率后的底价(可空) | |||
$BreakFast = $item['BreakFast']; //含早餐数 | |||
$pdo = conn(); | |||
//$sql="CALL HT_CHECKROOM_AVAIL($Arrival,$Departure,$Room,$RoomNumber)"; | |||
$sql = "CALL HT_CHECKROOM_AVAIL('2016-08-23','2016-08-28','152248',3)"; | |||
if (is_object($pdo)) { | |||
$result = $pdo->query($sql); | |||
$json2 = $result->fetchAll(PDO::FETCH_ASSOC); //返回一个包含结果集中所有行的数组 | |||
var_dump($json2); | |||
} | |||
} | |||
$roomInfo_arr['RequestResponse']['RequestResult'] = array(); | |||
$RequestResult = $roomInfo_arr['RequestResponse']['RequestResult']; | |||
$pdo = conn(); | |||
//$sql="CALL HT_CHECKROOM_AVAIL($Arrival,$Departure,$Room,$RoomNumber)"; | |||
$sql = "CALL HT_CHECKROOM_AVAIL('2016-08-23','2016-08-23','152248',3,0,0)"; | |||
if (is_object($pdo)) { | |||
$result = $pdo->query($sql); | |||
$res_arr = $result->fetchAll(PDO::FETCH_ASSOC); //返回一个包含结果集中所有行的数组 | |||
//var_dump($res_arr); | |||
$RequestResult['Message'] = empty($res_arr) ? '不可定' : '可定'; | |||
$RequestResult['ResultCode'] = empty($res_arr) ? 101 : 0; | |||
$availInfo['IsBookable'] = empty($res_arr) ? 0 : 1; | |||
$availInfo['Room'] = empty($res_arr) ? '' : $res_arr[0]['PROD_ID']; | |||
$availInfo['InterFaceAmount'] = empty($res_arr) ? '' : '';//接口订单金额 | |||
$availInfo['ReturnDescript'] = empty($res_arr) ? '' : ''; //错误描述 | |||
if (!empty($res_arr) && is_array($res_arr) || count($res_arr) > 0) | |||
foreach ($res_arr as $item) { | |||
$roomPrice['RoomPrice'] = array(); | |||
$roomPrice['RoomPrice']['EffectDate'] = $item['RUN_DATE']; | |||
$roomPrice['RoomPrice']['Price'] = 0; | |||
$roomPrice['RoomPrice']['CNYPrice'] = 0; | |||
$roomPrice['RoomPrice']['Cost'] = $item['HT_ORDER_PRICE']; | |||
$roomPrice['RoomPrice']['CNYCost'] = 0; | |||
$roomPrice['RoomPrice']['BreakFast'] = $item['HT_BREAKFAST']; | |||
$availInfo['RoomPrices'][] = $roomPrice; | |||
} | |||
$RequestResult['DomesticCheckRoomAvailResponse'] = $availInfo; | |||
$roomInfo_arr['RequestResponse']['RequestResult'] = $RequestResult; | |||
} | |||
return $roomInfo_arr; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc: DomesticSubmitNewHotelOrder (新订订单) | |||
* 1-1.接口调用方:携程/合作方 | |||
* 1-2.接口返回方:合作方/携程 | |||
* 1-3.调用频率:频繁 | |||
* 1-4.使用说明:通过该接口,提交订单给对方系统 | |||
* @return mixed | |||
*/ | |||
public function DomesticSubmitNewHotelOrderRequest() | |||
{ | |||
$rec_info = file_get_contents("php://input"); | |||
$OrderData = $this->obj_utils->data_to_xml($rec_info); //将xml转化成数组 | |||
$orderInfo = $OrderData['DomesticSubmitNewHotelOrderRequest']; | |||
//var_dump($orderInfo); | |||
$OrderID = $orderInfo['OrderID']; //订单号 | |||
$InterFaceSendID = $orderInfo['InterFaceSendID']; //订单接口发送号,同一订单每次发送编号会不同,接收方需落地保存 | |||
$Hotel = $orderInfo['Hotel']; // 酒店编号 | |||
$HotelName = $orderInfo['HotelName']; //酒店名 | |||
$Arrival = $orderInfo['Arrival']; //入住日期 | |||
$Departure = $orderInfo['Departure']; //离店日期 | |||
$EarlyArrivalTime = $orderInfo['EarlyArrivalTime']; //最早到店时间 | |||
$LastArrivalTime = $orderInfo['LastArrivalTime']; //最晚到店时间 | |||
$Person = $orderInfo['Person']; //实际入住人数 | |||
foreach ($orderInfo['Guests']['GuestEntity'] as $item) { | |||
$FirstName = $item['FirstName']; | |||
$LastName = $item['LastName']; | |||
$ChinesName = $item['ChinesName']; | |||
} | |||
$MobilePhone = $orderInfo['MobilePhone']; //携程联系电话 | |||
$Currency = $orderInfo['Currency']; //订单币种 | |||
$Amount = $orderInfo['Amount']; //订单卖价总金额(原币种),预付一般不传或者传0 | |||
$CNYAmount = $orderInfo['CNYAmount']; //订单卖价总金额(人民币),预付一般不传或者传0 | |||
$GuaranteeType = $orderInfo['GuaranteeType']; //担保方式 | |||
$BalanceType = $orderInfo['BalanceType']; //支付方式 | |||
$Room = $orderInfo['Room']; //Ctrip房型编号,供应商需要转成自己的对应编号 | |||
$RoomPerson = $orderInfo['RoomPerson']; //房型最大入住人数 | |||
$RoomName = $orderInfo['RoomName']; //房型名称 | |||
$Quantity = $orderInfo['Quantity']; //预定间数 | |||
$CostAmount = $orderInfo['CostAmount']; //订单底价金额(原币种),现付一般不传或者传0 | |||
$CNYCostAmount = $orderInfo['CNYCostAmount']; //订单底价金额(人民币),现付一般不传或者传0 | |||
foreach ($orderInfo['RoomPrices']['RoomPrice'] as $item) { //每个RoomPrice对应一天价格 | |||
$EffectDate = $item['EffectDate']; | |||
$Price = $item['Price']; //订单卖价金额(原币种),预付一般不传或者传0 | |||
$CNYPrice = $item['CNYPrice']; //订单卖价金额(人民币),预付一般不传或者传0 | |||
$Cost = $item['Cost']; //订单底价金额(原币种),现付一般不传或者传0 | |||
$CNYCost = $item['CNYCost']; //-订单底价金额(人民币),现付一般不传或者传0 | |||
$BreakFast = $item['BreakFast']; //早餐数量 | |||
} | |||
//先判断此房间是否可定 | |||
$pdo = conn(); | |||
echo $sql = "CALL HT_CHECKROOM_AVAIL($Arrival,$Departure,$Room,$Quantity,$CostAmount,$BreakFast)"; | |||
//$sql = "CALL HT_CHECKROOM_AVAIL('2016-08-23','2016-08-23','152248',3,0,0)"; | |||
if (is_object($pdo)) { | |||
$result = $pdo->query($sql); | |||
$json = $result->fetchAll(PDO::FETCH_ASSOC); //返回一个包含结果集中所有行的数组 | |||
if ($json) { | |||
//TODO:添加订单信息 | |||
$sql = ""; | |||
//返回信息 | |||
$orderInfo_arr['RequestResponse']['RequestResult'] = array(); | |||
$RequestResult = $orderInfo_arr['RequestResponse']['RequestResult']; | |||
$RequestResult['Message'] = ""; | |||
$ResultCode['ResultCode'] = ""; | |||
$orderStatus['OrderStatus'] = ''; //订单状态(0:发送中;1:已发送;2:发送失败;3:酒店确认成功;4:酒店 拒绝;5其他) | |||
$orderStatus['InterFaceConfirmNO'] = ""; //接口确认号,酒店确认号 | |||
$orderStatus['HotelConfirmNo'] = ""; //供应商确认号 | |||
$orderStatus['InterFaceAmount'] = ""; //接口订单金额 | |||
$orderStatus['ReturnCode'] = ""; //错误代码 | |||
$orderStatus['ReturnDescript'] = ""; //返回描述 | |||
$RequestResult['DomesticSubmitNewHotelOrderResponse'] = $orderStatus; | |||
return $RequestResult; | |||
} | |||
} | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc: DomesticModifyHotelOrder(修改酒店订单) | |||
* 1-1.接口调用方:携程/合作方 | |||
* 1-2.接口返回方:合作方/携程 | |||
* 1-3.调用频率:频繁 | |||
* 1-4.使用说明:通过该接口,提交订单给对方系统 | |||
* @return mixed | |||
*/ | |||
public function DomesticModifyHotelOrder() | |||
{ | |||
$rec_info = file_get_contents("php://input"); | |||
$OrderData = $this->obj_utils->data_to_xml($rec_info); //将xml转化成数组 | |||
$orderInfo = $OrderData['DomesticModifyHotelOrderRequest']; | |||
$OrderID = $orderInfo['OrderID']; //订单号 | |||
$InterFaceSendID = $orderInfo['InterFaceSendID']; //订单接口发送号,同一订单每次发送编号会不同,接收方需落地保存 | |||
$OldOrderID = $orderInfo['OldOrderID']; //上一个订单号 | |||
$Ori_OrderID = $orderInfo['Ori_OrderID']; //原始订单号 | |||
$Hotel = $orderInfo['Hotel']; //-Ctrip酒店编号,供应商需要转成自己的对应编号 | |||
$HotelName = $orderInfo['HotelName']; | |||
$Arrival = $orderInfo['Arrival']; | |||
$Departure = $orderInfo['Departure']; | |||
$EarlyArrivalTime = $orderInfo['EarlyArrivalTime']; | |||
$LastArrivalTime = $orderInfo['LastArrivalTime']; | |||
$Person = $orderInfo['Person']; | |||
foreach ($orderInfo['Guests'] as $k => $v) { | |||
$FirstName = $v; | |||
$LastName = $v; | |||
$ChinesName = $v; | |||
} | |||
$MobilePhone = $orderInfo['MobilePhone']; //-携程联系电话 | |||
$Currency = $orderInfo['Currency']; | |||
$Amount = $orderInfo['Amount']; | |||
$CNYAmount = $orderInfo['CNYAmount']; | |||
$GuaranteeType = $orderInfo['GuaranteeType']; | |||
$BalanceType = $orderInfo['BalanceType']; | |||
$Room = $orderInfo['Room']; | |||
$OldRoom = $orderInfo['OldRoom']; //上个预订房型 | |||
$RoomPerson = $orderInfo['RoomPerson']; | |||
$RoomName = $orderInfo['RoomName']; | |||
$Quantity = $orderInfo['Quantity']; //预定间数 | |||
$CostAmount = $orderInfo['CostAmount']; //订单底价金额(原币种),现付一般不传或者传0 | |||
$CNYCostAmount = $orderInfo['CNYCostAmount']; //订单底价金额(人民币),现付一般不传或者传0 | |||
foreach ($orderInfo['RoomPrices'] as $item) { //每个RoomPrice对应一天价格 | |||
$EffectDate = $item['EffectDate']; | |||
$Price = $item['Price']; //订单卖价金额(原币种),预付一般不传或者传0 | |||
$CNYPrice = $item['CNYPrice']; //订单卖价金额(人民币),预付一般不传或者传0 | |||
$Cost = $orderInfo['Cost']; //订单底价金额(原币种),现付一般不传或者传0 | |||
$CNYCost = $orderInfo['CNYCost']; //-订单底价金额(人民币),现付一般不传或者传0 | |||
$BreakFast = $orderInfo['BreakFast']; //早餐数量 | |||
$OldPrice = $orderInfo['OldPrice']; //-上个订单卖价金额(原币种),预付一般不传或者传0 | |||
} | |||
//检查修改后的房型是否可定 | |||
$pdo = conn(); | |||
//$sql="CALL HT_CHECKROOM_AVAIL($Arrival,$Departure,$Room,$Quantity,$CostAmount,$BreakFast)"; | |||
$sql = "CALL HT_CHECKROOM_AVAIL('2016-08-23','2016-08-23','152248',3,0,0)"; | |||
if (is_object($pdo)) { | |||
$result = $pdo->query($sql); | |||
$json = $result->fetchAll(PDO::FETCH_ASSOC); //返回一个包含结果集中所有行的数组 | |||
if ($json) { | |||
//TODO:修改订单信息 | |||
//返回信息 | |||
$orderInfo_arr['RequestResponse']['RequestResult'] = array(); | |||
$RequestResult = $orderInfo_arr['RequestResponse']['RequestResult']; | |||
$RequestResult['Message'] = ""; | |||
$ResultCode['ResultCode'] = ""; | |||
$orderStatus['OrderStatus'] = ''; //订单状态(0:发送中;1:已发送;2:发送失败;3:酒店确认成功;4:酒店 拒绝;5其他) | |||
$orderStatus['InterFaceConfirmNO'] = ""; //接口确认号,酒店确认号 | |||
$orderStatus['HotelConfirmNo'] = ""; //供应商确认号 | |||
$orderStatus['InterFaceAmount'] = ""; //接口订单金额 | |||
$orderStatus['ReturnCode'] = ""; //错误代码 | |||
$orderStatus['ReturnDescript'] = ""; //返回描述 | |||
$RequestResult['DomesticModifyHotelOrderResponse'] = $orderStatus; | |||
return $RequestResult; | |||
} | |||
} | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc: DomesticCancelHotelOrder (取消订单) | |||
* 1-1.接口调用方:携程/合作方 | |||
* 1-2.接口返回方:合作方/携程 | |||
* 1-3.调用频率:频繁 | |||
* 1-4.使用说明:通过该接口,提交订单给对方系统 | |||
* @return mixed | |||
*/ | |||
public function DomesticCancelHotelOrder() | |||
{ | |||
$rec_info = file_get_contents("php://input"); | |||
$OrderData = $this->obj_utils->data_to_xml($rec_info); //将xml转化成数组 | |||
$cancelOrderInfo = $OrderData['DomesticCancelHotelOrderRequest']; | |||
$OrderID = $cancelOrderInfo['OrderID']; | |||
$OldOrderID = $cancelOrderInfo['OldOrderID']; | |||
$Ori_OrderID = $cancelOrderInfo['Ori_OrderID']; | |||
$InterFaceSendID = $cancelOrderInfo['InterFaceSendID']; | |||
$InterFaceConfirmNO = $cancelOrderInfo['InterFaceConfirmNO']; | |||
$Hotel = $cancelOrderInfo['Hotel']; | |||
$HotelName = $cancelOrderInfo['HotelName']; | |||
$Arrival = $cancelOrderInfo['Arrival']; | |||
$Departure = $cancelOrderInfo['Departure']; | |||
$Person = $cancelOrderInfo['Person']; | |||
$ClientName = $cancelOrderInfo['ClientName']; | |||
$Room = $cancelOrderInfo['Room']; | |||
$RoomName = $cancelOrderInfo['RoomName']; | |||
$Quantity = $cancelOrderInfo['Quantity']; //注意确认几个半闭合标签是否存在 | |||
//TODO:取消订单逻辑; | |||
//返回结果 | |||
$orderInfo_arr['RequestResponse']['RequestResult'] = array(); | |||
$RequestResult = $orderInfo_arr['RequestResponse']['RequestResult']; | |||
$RequestResult['Message'] = ""; | |||
$RequestResult['ResultCode'] = ""; | |||
$orderStatus['OrderStatus'] = ''; //订单状态(0:发送中;1:已发送;2:发送失败;3:酒店确认成功;4:酒店 拒绝;5其他) | |||
$orderStatus['OrderID'] = ""; | |||
$orderStatus['InterFaceConfirmNO'] = ""; | |||
$orderStatus['ReturnCode'] = ""; | |||
$orderStatus['ReturnDescript'] = ""; //错误代码 | |||
$RequestResult['DomesticCancelhotelOrderResponse'] = $orderStatus; | |||
return $RequestResult; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc: DomesticPushOrderStatus(订单状态推送) | |||
* 1-1.接口调用方:携程/合作方 | |||
* 1-2.接口返回方:合作方/携程 | |||
* 1-3.调用频率:频繁 | |||
* 1-4.使用说明:订单非立即确认时调用该接口,接收方收到订单后,当订单状态变化时, 需及时推送订单状 | |||
*/ | |||
public function DomesticPushOrderStatus() | |||
{ | |||
} | |||
} |
@@ -0,0 +1,202 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/13 | |||
* Time: 18:42 | |||
* 接口调用方:合作方 | |||
* 接口返回方:携程 | |||
*/ | |||
require_once dirname(__DIR__) . '/Common/Utils.php'; | |||
class Api_HotelPush extends PhalApi_Api | |||
{ | |||
public $obj_utils = ''; | |||
public $Currency = 'RMB'; | |||
public function __construct() | |||
{ | |||
$this->obj_utils = new roomOrderUtils(); | |||
} | |||
public function getRules() | |||
{ | |||
return array(/* '*' => array( //通用接口参数 | |||
'code' => array('name' => 'code', 'require' => true, 'min' => 4, 'max' => 4), | |||
), | |||
'index' => array( //指定接口参数 | |||
'username' => array('name' => 'username', 'default' => 'PHPer',), | |||
),*/ | |||
); | |||
} | |||
/** | |||
* 默认接口服务 | |||
* @return string title 标题 | |||
* @return string content 内容 | |||
* @return string version 版本,格式:X.X.X | |||
* @return int time 当前时间戳 | |||
*/ | |||
public function index() | |||
{ | |||
return array( | |||
'title' => 'Hello Worl!', | |||
'content' => T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), | |||
'version' => PHALAPI_VERSION, | |||
'time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:GetCtripRoomTypeInfo(获得房型对照) | |||
* 1-1. 接口调用方:合作方 | |||
* 1-2. 接口返回方:携程 | |||
* 1-3. 调用频率:不限制,建议每天早晚各一次 | |||
* 1-4. 使用说明:合作方通过自己的酒店信息、房型信息、房价套系等获得携程的房型对 照信息 | |||
*/ | |||
public function GetCtripRoomTypeInfo() | |||
{ | |||
$RoomTypeList = array( | |||
'HotelGroupHotelCode' => "", | |||
'HotelGroupRoomTypeCode' => "", | |||
'HotelGroupBrand' => "", | |||
'HotelGroupRatePlanCode' => '' | |||
); | |||
$RoomTypeInfo['HotelGroupInterfaceRoomTypeListRequest'] = $RoomTypeList; | |||
$res = $this->obj_utils->xml_encode($RoomTypeInfo, 'GetCtripRoomTypeInfo'); | |||
$result = $this->obj_utils->soapRequest('GetCtripRoomTypeInfo', $res); //发送soap请求 | |||
//TODO:得到请求结果,处理 | |||
return $result; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:SetRoomPrice(设置房型价格) | |||
* 1.接口调用方:合作方 | |||
* 2.接口返回方:携程 | |||
* 3.调用频率:不限制,建议不大于50万次/分钟(QPS<1万) | |||
* 4.使用说明:携程建议当价格变化时,立即进行推送。携程方面是异步处理价格。 | |||
*/ | |||
public function SetRoomPrice() | |||
{ | |||
$Prices['Price'] = array( | |||
'AmountBeforeTaxFee' => '', //税前 | |||
'AmountAfterTaxFee' => '', //税后 | |||
'CostAmountBeforeTaxFee' => '',//税前成本 | |||
'CostAmountAfterTaxFee' => '', //税后成本 | |||
'Day' => '' //连住天数,暂不用,默认为1 | |||
); | |||
//PriceInfo节点代表一天的价格,每天的价格可以不 同 | |||
$PriceInfos['PriceInfo'][] = array( | |||
'Prices' => $Prices, | |||
'Stays' => '', //连住,暂不用,默认为1 | |||
'BlanceType' => '', //支付类型 | |||
'PriceType' => '', //价格类型 | |||
'Breakfast' => '', //早餐 | |||
'Applicability' => '' //适用人群 | |||
); | |||
//根据日期范围生成多天的 SetRoomPriceItem | |||
$SetRoomPriceItem['SetRoomPriceItem'][] = array( | |||
'PriceInfos' => $PriceInfos, | |||
'RoomID' => '', | |||
'StartDate' => '', | |||
'EndDate' => '', | |||
'Currency' => $this->Currency, | |||
); | |||
$RoomTypeList = array( | |||
'SetRoomPriceItems' => $SetRoomPriceItem, | |||
'HotelID' => "", //酒店ID | |||
'Submitor' => "", //提交人,集团名拼音 | |||
'Title' => '', | |||
'Priority' => '' //是否优先处理,暂不用,默认为N | |||
); | |||
$RoomPriceRequest['SetAdaperRoomPriceRequest'] = $RoomTypeList; //设置多房型多天房价 | |||
$res = $this->obj_utils->xml_encode($RoomPriceRequest, 'SetRoomPrice'); | |||
$result = $this->obj_utils->soapRequest('SetRoomPrice', $res); //发送soap请求 | |||
return $result; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:SetRoomInfo(设置房态) | |||
* 1.接口调用方:合作方 | |||
* 2.接口返回方:携程 | |||
* 3.调用频率:不限制,建议不大于50万次/分钟(QPS<1万) | |||
* 4.使用说明:携程建议当房态变化时(开或关),立即进行推送。携程方面是异步处 理房态。 | |||
*/ | |||
public function SetRoomInfo() | |||
{ | |||
//设置房态信息请求,设置一个房型单天或多天房态,不支持多房型同时 设置 | |||
$RoomInfoItem['RoomInfoItem'][] = array( | |||
'Stays' => '', //连住,暂不用,默认为1 | |||
'ChangeDefault' => '', //是否同时修改房态默认值(F-否,T-是) | |||
'Recommend' => '', //国内推荐级别(5-特推,4-主推,3-可推,2-可订,1-不推,0-不可 订) | |||
'Recommend_Intl' => '', //国外推荐级别(5-特推,4-主推,3-可推,2-可订,1-不推,0-不可 订) | |||
'HoldDeadline' => '', //保留时间(9999-无规定,1000-10:00,...,2330-23:30) | |||
'Roomstatus' => '', //房态(N-满房,G-良好) | |||
'RoomsInv' => '', //临时保留房总数 | |||
'UserLimited' => '', //预订限制(2-超时担保,3-一律担保,9999-无限制) | |||
'Note' => '', //备注 | |||
'ReserveTime' => '', //保留房用最晚预订时间,计算公式:订单入住日24点向后推 算,如果设置为6,则当天保留房最晚预订时间为24点向后倒推6小时,为18点。 如果设置为36,则保留房最晚预订时间为24点向后倒推36小时,表示入住日前一 天的中午12点。 | |||
'Restorable' => '', //保留房可否恢复(T-可,F-不可) | |||
'Guarantee' => '', //担保(此字段暂时不维护) | |||
'CheckType' => '', //住店控制(C-进店统计,S-住店统计) | |||
'GuaranteeLCT' => '', //担保最晚取消时间,计算公式同ReserveTime,不可取消设置 为23988 | |||
'PrepayLCT' => '', //预付最晚取消时间,计算公式同ReserveTime, 不可取消设置 为23988 | |||
'AllNeedGuarantee' => '', //全额/峰时担保(F-否,T-全额担保,B-峰时担保)- | |||
'RoomGiftID' => '', //房型礼品ID,默认值-2147483648 | |||
'LateReserveTime' => '', //订单最晚预订时间,计算公式同ReserveTime | |||
'DeductType' => '', //预付房型扣款类型(C-全部扣款,F-首日扣款) | |||
); | |||
$RoomInfoRequest['SetRoomInfoRequest'] = array( | |||
'RoomInfoItems' => $RoomInfoItem, | |||
'RoomID' => '', //房型ID | |||
'StartDate' => '', //开始日期 | |||
'EndDate' => '', //结束日期,设置多天表示多天房态 | |||
'Editer' => '', //修改者,集团名拼音 | |||
); | |||
$res = $this->obj_utils->xml_encode($RoomInfoRequest, 'SetRoomInfo'); | |||
$result = $this->obj_utils->soapRequest('SetRoomInfo', $res); //发送soap请求 | |||
return $result; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:UpdateRoomQuantity(更新保留房数量) | |||
* 1-1.接口调用方:合作方 | |||
* 1-2.接口返回方:携程 | |||
* 1-3.调用频率:限制, 建议10次/分钟,并会视情况调整 | |||
* 1-4.使用说明:携程建议当房量变化时,立即进行推送。携程方面是异步处理房量更新操作。 | |||
* 一个请求最多只允许更新 10 个酒店下的房型,一个请求只允许 120 天内的房量, 一个请求 只允许发送少于 100 个房型。 | |||
*/ | |||
public function UpdateRoomQuantity() | |||
{ | |||
//多个房型 | |||
$RoomQuantityEntityList['RoomQuantityEntity'][] = array( | |||
'RoomTypeID' => '', | |||
'RoomQuantityCount' => '', | |||
'RoomQuantityUpdateType' => '', | |||
'StartDate' => '', | |||
'EndDate' => '' | |||
); | |||
//一个酒店 | |||
$UpdateRoomQuantityRequest['UpdateRoomQuantityRequest'] = array( | |||
'SequenceID' => '', | |||
'HotelID' => '', | |||
'RoomQuantityEntityList' => $RoomQuantityEntityList, | |||
'Editer' => '', | |||
); | |||
$res = $this->obj_utils->xml_encode($UpdateRoomQuantityRequest, 'UpdateRoomQuantityRequest '); | |||
$result = $this->obj_utils->soapRequest('UpdateRoomQuantityRequest ', $res); //发送soap请求 | |||
return $result; | |||
} | |||
} |
@@ -0,0 +1,93 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/14 | |||
* Time: 18:46 | |||
* Ctrip 自助Mapping | |||
*/ | |||
require_once dirname(__DIR__) . '/Common/Utils.php'; | |||
class Api_Mapping extends PhalApi_Api | |||
{ | |||
public $obj_utils = ''; | |||
public $SupplierID = 77; //供应商编码 | |||
public $Brand = 1; //品牌编码 | |||
public function __construct() | |||
{ | |||
$this->obj_utils = new roomOrderUtils(); | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:、GetHotelInfo(获得Ctrip的酒店信息) | |||
* 1-1. 接口调用方:合作方 | |||
* 1-2. 接口返回方:携程 | |||
* 1-3. 调用频率:不限制 | |||
* 1-4. 使用说明:合作方获取ctrip的酒店对接信息,用于自助Mapping。 SupplierID或Brand会线下提供 | |||
*/ | |||
public function GetHotelInfo() | |||
{ | |||
/*$GetHotelInfoRequest['GetHotelInfoRequest'] = array( | |||
'SupplierID' => $this->SupplierID, //供应商编码 | |||
'Brand' => $this->Brand, | |||
'CurrentPage' => '' | |||
); | |||
$res = $this->obj_utils->xml_encode($GetHotelInfoRequest, 'GetHotelInfo'); | |||
$GetHotelInfo = $this->obj_utils->soapRequest('GetHotelInfo', $res); //发送soap请求 | |||
$result = $this->obj_utils->xml_to_array($GetHotelInfo);*/ | |||
//测试 | |||
$HotelList[0] = array( | |||
'Hotel' => 12121, | |||
'HotelName' => 'casdas', | |||
'CountryName' => 'sadas', | |||
'CityName' => 'dsadas', | |||
'Address' => 'asdasd', | |||
'Telephone' => 'sadas' | |||
); | |||
$HotelList[1] = array( | |||
'Hotel' => 'weqeqwewq', | |||
'HotelName' => 'casdas', | |||
'CountryName' => 'sadas', | |||
'CityName' => 'dsadas', | |||
'Address' => 'asdasd', | |||
'Telephone' => 'sadas' | |||
); | |||
$GetHotelInfoResponse = array( | |||
'TotalPage' => 10, | |||
'CurrentPage' => 1, | |||
'TotalNum' => 1000, | |||
'HotelList' => $HotelList, | |||
); | |||
$Response = array( | |||
'HeaderInfo' => '', | |||
'GetHotelInfoResponse' => $GetHotelInfoResponse | |||
); | |||
$RequestResponse['RequestResult'] = array( | |||
'Message' => '', | |||
'ResultCode' => '', | |||
'Response' => $Response | |||
); | |||
$result['RequestResponse'] = $RequestResponse; | |||
return $result; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc: | |||
*/ | |||
public function getZzHotelInfo() | |||
{ | |||
$domain = new Domain_hotel(); | |||
$res=$domain->getHotelInfo(); | |||
return $res; | |||
} | |||
} | |||
?> | |||
@@ -0,0 +1,128 @@ | |||
<?php | |||
/** | |||
* Copyright (c) 2005, Braulio Jos?Solano Rojas | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without modification, are | |||
* permitted provided that the following conditions are met: | |||
* | |||
* Redistributions of source code must retain the above copyright notice, this list of | |||
* conditions and the following disclaimer. | |||
* Redistributions in binary form must reproduce the above copyright notice, this list of | |||
* conditions and the following disclaimer in the documentation and/or other materials | |||
* provided with the distribution. | |||
* Neither the name of the Solsoft de Costa Rica S.A. nor the names of its contributors may | |||
* be used to endorse or promote products derived from this software without specific | |||
* prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | |||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* | |||
* | |||
* @version $Id$ | |||
* @copyright 2005 | |||
*/ | |||
/** | |||
* SoapDiscovery Class that provides Web Service Definition Language (WSDL). | |||
* | |||
* @package SoapDiscovery | |||
* @author Braulio Jos?Solano Rojas | |||
* @copyright Copyright (c) 2005 Braulio Jos?Solano Rojas | |||
* @version $Id$ | |||
* @access public | |||
* */ | |||
class SoapDiscovery { | |||
private $class_name = ''; | |||
private $service_name = ''; | |||
/** | |||
* SoapDiscovery::__construct() SoapDiscovery class Constructor. | |||
* | |||
* @param string $class_name | |||
* @param string $service_name | |||
* */ | |||
public function __construct($class_name = '', $service_name = '') { | |||
$this->class_name = $class_name; | |||
$this->service_name = $service_name; | |||
} | |||
/** | |||
* SoapDiscovery::getWSDL() Returns the WSDL of a class if the class is instantiable. | |||
* | |||
* @return string | |||
* */ | |||
public function getWSDL() { | |||
if (empty($this->service_name)) { | |||
throw new Exception('No service name.'); | |||
} | |||
$headerWSDL = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; | |||
$headerWSDL.= "<definitions name=\"$this->service_name\" targetNamespace=\"urn:$this->service_name\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:tns=\"urn:$this->service_name\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns=\"http://schemas.xmlsoap.org/wsdl/\">\n"; | |||
$headerWSDL.= "<types xmlns=\"http://schemas.xmlsoap.org/wsdl/\" />\n"; | |||
if (empty($this->class_name)) { | |||
throw new Exception('No class name.'); | |||
} | |||
$class = new ReflectionClass($this->class_name); | |||
if (!$class->isInstantiable()) { | |||
throw new Exception('Class is not instantiable.'); | |||
} | |||
$methods = $class->getMethods(); | |||
$portTypeWSDL = '<portType name="' . $this->service_name . 'Port">'; | |||
$bindingWSDL = '<binding name="' . $this->service_name . 'Binding" type="tns:' . $this->service_name . "Port\">\n<soap:binding style=\"rpc\" transport=\"http://schemas.xmlsoap.org/soap/http\" />\n"; | |||
$serviceWSDL = '<service name="' . $this->service_name . "\">\n<documentation />\n<port name=\"" . $this->service_name . 'Port" binding="tns:' . $this->service_name . "Binding\"><soap:address location=\"http://" . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF'] . "\" />\n</port>\n</service>\n"; | |||
$messageWSDL = ''; | |||
foreach ($methods as $method) { | |||
if ($method->isPublic() && !$method->isConstructor()) { | |||
$portTypeWSDL.= '<operation name="' . $method->getName() . "\">\n" . '<input message="tns:' . $method->getName() . "Request\" />\n<output message=\"tns:" . $method->getName() . "Response\" />\n</operation>\n"; | |||
$bindingWSDL.= '<operation name="' . $method->getName() . "\">\n" . '<soap:operation soapAction="urn:' . $this->service_name . '#' . $this->class_name . '#' . $method->getName() . "\" />\n<input><soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n</input>\n<output>\n<soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n</output>\n</operation>\n"; | |||
$messageWSDL.= '<message name="' . $method->getName() . "Request\">\n"; | |||
$parameters = $method->getParameters(); | |||
foreach ($parameters as $parameter) { | |||
$messageWSDL.= '<part name="' . $parameter->getName() . "\" type=\"xsd:string\" />\n"; | |||
} | |||
$messageWSDL.= "</message>\n"; | |||
$messageWSDL.= '<message name="' . $method->getName() . "Response\">\n"; | |||
$messageWSDL.= '<part name="' . $method->getName() . "\" type=\"xsd:string\" />\n"; | |||
$messageWSDL.= "</message>\n"; | |||
} | |||
} | |||
$portTypeWSDL.= "</portType>\n"; | |||
$bindingWSDL.= "</binding>\n"; | |||
//return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>'); | |||
//生成wsdl文件,将上面的return注释 | |||
$fso = fopen($this->class_name . ".wsdl", "w"); | |||
fwrite($fso, sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '</definitions>')); | |||
fclose($fso); | |||
@chmod($fso,0777); | |||
} | |||
/** | |||
* SoapDiscovery::getDiscovery() Returns discovery of WSDL. | |||
* | |||
* @return string | |||
* */ | |||
public function getDiscovery() { | |||
return "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<disco:discovery xmlns:disco=\"http://schemas.xmlsoap.org/disco/\" xmlns:scl=\"http://schemas.xmlsoap.org/disco/scl/\">\n<scl:contractRef ref=\"http://" . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF'] . "?wsdl\" />\n</disco:discovery>"; | |||
} | |||
} | |||
?> |
@@ -0,0 +1,138 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/13 | |||
* Time: 15:17 | |||
*/ | |||
class roomOrderUtils | |||
{ | |||
public $ctrip_url = 'http://127.0.0.1:20083/Ctrip/Service.php?wsdl'; | |||
public $UserID = "123456"; //合作方编码 | |||
public $RequestorId = "Ctrip.com"; //请求对象的编码,后备字段, 暂不处理,默认值Ctrip.com | |||
public $AsyncRequest = "false"; //是否异步请求 | |||
public $UserName = "Zhilianjishuzhuanshu"; //用户名 | |||
public $Password = "zhilianzhuanshu11!!"; //密码 | |||
public $Version = "1.0"; //API版本号 | |||
public $url = ""; //请求URL | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:发生soap请求 | |||
* @param $request_fun | |||
* @param $param | |||
* @return Exception|SoapFault | |||
*/ | |||
public function soapRequest($request_fun, $param) | |||
{ | |||
$soap = new SoapClient($this->ctrip_url, array('soap_version' => SOAP_1_2, 'trace' => TRUE, 'exceptions' => FALSE)); | |||
try { | |||
$response = $soap->{$request_fun}($param); | |||
return $response; | |||
} catch (SoapFault $sf) { | |||
return $sf; | |||
/*print ($soap->__getLastRequest()); | |||
print ($soap->__getLastResponse());*/ | |||
} | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:发送post请求(xml) | |||
* @param $url | |||
* @param $xmlData | |||
* @return mixed | |||
*/ | |||
public function xml_post_request($url, $xmlData) | |||
{ | |||
$header[] = "Content-type: text/xml"; //定义content-type为xml,注意是数组 | |||
$ch = curl_init($url); | |||
curl_setopt($ch, CURLOPT_URL, $url); | |||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | |||
curl_setopt($ch, CURLOPT_POST, 1); | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData); | |||
$response = curl_exec($ch); | |||
if (curl_errno($ch)) { | |||
print curl_error($ch); | |||
} | |||
curl_close($ch); | |||
return $response; | |||
} | |||
public function execute($request, $session = null) | |||
{ | |||
$this->data = $this->format == 'json' ? json_encode($request) : $this->xml_encode($request); | |||
$this->Url = 'http://' . str_replace(array('http://', 'https://'), '', $this->Url); | |||
$postUrl = $this->Url . "?method={$this->requestMethod}&data=" . urlencode($this->data); | |||
return $this->request_by_curl($postUrl); | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:编辑符合携程需要的XML格式 | |||
* @param $data 请求体 | |||
* @param $RequestTypeName 请求方法名称 | |||
* @return string | |||
*/ | |||
public function xml_encode($data, $RequestTypeName) | |||
{ | |||
$timeStamp = date("Y-m-d H:i:s", time()); | |||
$xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; | |||
$xml .= "<request>"; | |||
$xml .= "<HeaderInfo UserID=\"$this->UserID\" RequestorId=\"$this->RequestorId\" AsyncRequest=\"$this->AsyncRequest\" TimeStamp=\"$timeStamp\"><Authentication UserName=\"$this->UserName\" Password=\"$this->Password\"/><RequestType Name=\"$RequestTypeName\" Version=\"$this->Version\"/></HeaderInfo> "; | |||
$xml .= $this->data_to_xml($data); | |||
$xml .= "</request>"; | |||
return $xml; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:将xml转换为数组 | |||
* @param $xml | |||
* @return mixed | |||
*/ | |||
public function xml_to_array($xml) | |||
{ | |||
$ob = simplexml_load_string($xml); | |||
$json = json_encode($ob); | |||
$array = json_decode($json, true); | |||
return $array; | |||
} | |||
/** | |||
* User:Steven | |||
* | |||
* Desc:将数组转化成xml | |||
* @param $data | |||
* @return string | |||
*/ | |||
public function data_to_xml($data) | |||
{ | |||
if (is_object($data)) { | |||
$data = get_object_vars($data); | |||
} | |||
$xml = ''; | |||
foreach ($data as $key => $val) { | |||
if (is_null($val)) { | |||
$xml .= "<$key/>\n"; | |||
} else { | |||
if (!is_numeric($key)) { | |||
$xml .= "<$key>"; | |||
} | |||
$xml .= (is_array($val) || is_object($val)) ? $this->data_to_xml($val) : $val; | |||
if (!is_numeric($key)) { | |||
$xml .= "</$key>"; | |||
} | |||
} | |||
} | |||
return $xml; | |||
} | |||
} | |||
@@ -0,0 +1,19 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/15 | |||
* Time: 13:43 | |||
* | |||
*/ | |||
class Domain_hotel | |||
{ | |||
public function getHotelInfo() | |||
{ | |||
$model = new Model_hotel(); | |||
$res = $model->getHotelInfo(); | |||
return $res; | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
<?php | |||
/** | |||
* Created by PhpStorm. | |||
* User: Steven | |||
* Date: 2017/3/15 | |||
* Time: 13:20 | |||
* | |||
*/ | |||
class Model_hotel extends PhalApi_Model_NotORM | |||
{ | |||
public function getHotelInfo() | |||
{ | |||
//原生SQL | |||
/* $sql = 'select HOTEL_ID,HOTEL_NAME,HOTEL_ADDRESS fROM opera_hotel where CANCEL_FLAG=0'; | |||
$rows = $this->getORM()->queryAll($sql, array());*/ | |||
$rs = DI()->notorm->opera_hotel->select('hotel_id,hotel_name,hotel_address')->where('CANCEL_FLAG = ?', 0)->fetchAll(); | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
CREATE TABLE `phalapi_test`.`tbl_user` ( | |||
`id` INT NOT NULL, | |||
`name` VARCHAR(45) NULL, | |||
`note` VARCHAR(45) NULL, | |||
PRIMARY KEY (`id`)); | |||
INSERT INTO `phalapi_test`.`tbl_user` (`id`, `name`, `note`) VALUES ('1', 'dogstar', 'oschina'); | |||
@@ -0,0 +1,2 @@ | |||
`name` VARCHAR(45) NULL, | |||
`note` VARCHAR(45) NULL, |
@@ -0,0 +1,39 @@ | |||
<?php | |||
/** | |||
* 默认接口服务类 | |||
* | |||
* @author: dogstar <chanzonghuang@gmail.com> 2014-10-04 | |||
*/ | |||
class Api_Default extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'*' => array( //通用接口参数 | |||
'code' => array('name' => 'code', 'require' => true, 'min' => 4, 'max' => 4), | |||
), | |||
'index' => array( //指定接口参数 | |||
'username' => array('name' => 'username', 'default' => 'PHPer', ), | |||
), | |||
); | |||
} | |||
/** | |||
* 默认接口服务 | |||
* @return string title 标题 | |||
* @return string content 内容 | |||
* @return string version 版本,格式:X.X.X | |||
* @return int time 当前时间戳 | |||
*/ | |||
public function index() { | |||
return array( | |||
'title' => 'Hello World!', | |||
'content' => T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), | |||
'version' => PHALAPI_VERSION, | |||
'time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
} | |||
} |
@@ -0,0 +1,70 @@ | |||
<?php | |||
/** | |||
* 用户信息类 | |||
*/ | |||
class Api_User extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'getBaseInfo' => array( | |||
'userId' => array('name' => 'user_id', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'), | |||
), | |||
'getMultiBaseInfo' => array( | |||
'userIds' => array('name' => 'user_ids', 'type' => 'array', 'format' => 'explode', 'require' => true, 'desc' => '用户ID,多个以逗号分割'), | |||
), | |||
); | |||
} | |||
/** | |||
* 获取用户基本信息 | |||
* @desc 用于获取单个用户基本信息 | |||
* @return int code 操作码,0表示成功, 1表示用户不存在 | |||
* @return object info 用户信息对象 | |||
* @return int info.id 用户ID | |||
* @return string info.name 用户名字 | |||
* @return string info.note 用户来源 | |||
* @return string msg 提示信息 | |||
*/ | |||
public function getBaseInfo() { | |||
$rs = array('code' => 0, 'msg' => '', 'info' => array()); //定义返回值 | |||
$domain = new Domain_User(); | |||
$info = $domain->getBaseInfo($this->userId); | |||
if (empty($info)) { | |||
DI()->logger->debug('user not found', $this->userId); | |||
$rs['code'] = 1; | |||
$rs['msg'] = T('user not exists'); | |||
return $rs; | |||
} | |||
$rs['info'] = $info; | |||
return $rs; | |||
} | |||
/** | |||
* 批量获取用户基本信息 | |||
* @desc 用于获取多个用户基本信息 | |||
* @return int code 操作码,0表示成功 | |||
* @return array list 用户列表 | |||
* @return int list[].id 用户ID | |||
* @return string list[].name 用户名字 | |||
* @return string list[].note 用户来源 | |||
* @return string msg 提示信息 | |||
* @exception 400 参数传递错误 | |||
* @exception 500 服务器内部错误 | |||
*/ | |||
public function getMultiBaseInfo() { | |||
$rs = array('code' => 0, 'msg' => '', 'list' => array()); | |||
$domain = new Domain_User(); | |||
foreach ($this->userIds as $userId) { | |||
$rs['list'][] = $domain->getBaseInfo($userId); | |||
} | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
<?php | |||
//领域层主要是关注复杂业务的处理,以及缓存的处理、耗时操作后台异步处理等,并调用Model持久层获取需要的数据。因此,是Api与Model层之间的桥梁。 | |||
class Domain_User { | |||
public function getBaseInfo($userId) { | |||
$rs = array(); | |||
$userId = intval($userId); | |||
if ($userId <= 0) { | |||
return $rs; | |||
} | |||
// 版本1:简单的获取 | |||
$model = new Model_User(); | |||
$rs = $model->getByUserId($userId); | |||
// 版本2:使用单点缓存/多级缓存 (应该移至Model层中) | |||
/** | |||
$model = new Model_User(); | |||
$rs = $model->getByUserIdWithCache($userId); | |||
*/ | |||
// 版本3:缓存 + 代理 | |||
/** | |||
$query = new PhalApi_ModelQuery(); | |||
$query->id = $userId; | |||
$modelProxy = new ModelProxy_UserBaseInfo(); | |||
$rs = $modelProxy->getData($query); | |||
*/ | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
class Model_User extends PhalApi_Model_NotORM { | |||
public function getByUserId($userId) { | |||
return $this->getORM() | |||
->select('*') | |||
->where('id = ?', $userId) | |||
->fetch(); | |||
} | |||
public function getByUserIdWithCache($userId) { | |||
$key = 'userbaseinfo_' . $userId; | |||
$rs = DI()->cache->get($key); | |||
if ($rs === NULL) { | |||
$rs = $this->getByUserId($userId); | |||
DI()->cache->set($key, $rs, 600); | |||
} | |||
return $rs; | |||
} | |||
/** | |||
protected function getTableName($id) { | |||
return 'user'; | |||
} | |||
*/ | |||
} |
@@ -0,0 +1,21 @@ | |||
<?php | |||
/** | |||
* @author dogstar <chanzonghuang@gmail.com> 2015-02-22 | |||
*/ | |||
class ModelProxy_UserBaseInfo extends PhalApi_ModelProxy { | |||
protected function doGetData($query) { | |||
$model = new Model_User(); | |||
return $model->getByUserId($query->id); | |||
} | |||
protected function getKey($query) { | |||
return 'userbaseinfo_' . $query->id; | |||
} | |||
protected function getExpire($query) { | |||
return 600; | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ApiDefault_Test | |||
* | |||
* 针对 ../../Api/Default.php Api_Default 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150201 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Api_Default')) { | |||
require dirname(__FILE__) . '/../../Api/Default.php'; | |||
} | |||
class PhpUnderControl_ApiDefault_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $apiDefault; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->apiDefault = new Api_Default(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetRules | |||
*/ | |||
public function testGetRules() | |||
{ | |||
$rs = $this->apiDefault->getRules(); | |||
$this->assertNotEmpty($rs); | |||
} | |||
public function testIndex() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=Default.Index&username=dogstar'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('title', $rs); | |||
$this->assertArrayHasKey('content', $rs); | |||
$this->assertArrayHasKey('version', $rs); | |||
$this->assertArrayHasKey('time', $rs); | |||
$this->assertEquals('dogstar您好,欢迎使用PhalApi!', $rs['content']); | |||
} | |||
} |
@@ -0,0 +1,84 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ApiUser_Test | |||
* | |||
* 针对 ../../Demo/Api/User.php Api_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150128 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Api_User')) { | |||
require dirname(__FILE__) . '/../../Demo/Api/User.php'; | |||
} | |||
class PhpUnderControl_ApiUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $apiUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->apiUser = new Api_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetRules | |||
*/ | |||
public function testGetRules() | |||
{ | |||
$rs = $this->apiUser->getRules(); | |||
} | |||
/** | |||
* @group testGetBaseInfo | |||
*/ | |||
public function testGetBaseInfo() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=User.GetBaseInfo&user_id=1'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('code', $rs); | |||
$this->assertArrayHasKey('msg', $rs); | |||
$this->assertArrayHasKey('info', $rs); | |||
$this->assertEquals(0, $rs['code']); | |||
$this->assertEquals('dogstar', $rs['info']['name']); | |||
$this->assertEquals('oschina', $rs['info']['note']); | |||
} | |||
public function testGetMultiBaseInfo() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=User.GetMultiBaseInfo&user_ids=1,2,3'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('code', $rs); | |||
$this->assertArrayHasKey('msg', $rs); | |||
$this->assertArrayHasKey('list', $rs); | |||
foreach ($rs['list'] as $item) { | |||
$this->assertArrayHasKey('id', $item); | |||
$this->assertArrayHasKey('name', $item); | |||
$this->assertArrayHasKey('note', $item); | |||
} | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_DomainUser_Test | |||
* | |||
* 针对 ./Demo/Domain/User.php Domain_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150208 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Domain_User')) { | |||
require dirname(__FILE__) . '/./Demo/Domain/User.php'; | |||
} | |||
class PhpUnderControl_DomainUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $domainUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->domainUser = new Domain_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetBaseInfo | |||
*/ | |||
public function testGetBaseInfo() | |||
{ | |||
$userId = '1'; | |||
$rs = $this->domainUser->getBaseInfo($userId); | |||
$this->assertArrayHasKey('id', $rs); | |||
$this->assertArrayHasKey('name', $rs); | |||
$this->assertArrayHasKey('note', $rs); | |||
$this->assertEquals('dogstar', $rs['name']); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ModelUser_Test | |||
* | |||
* 针对 ./Demo/Model/User.php Model_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150208 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Model_User')) { | |||
require dirname(__FILE__) . '/./Demo/Model/User.php'; | |||
} | |||
class PhpUnderControl_ModelUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $modelUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->modelUser = new Model_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetByUserId | |||
*/ | |||
public function testGetByUserId() | |||
{ | |||
$userId = '1'; | |||
$rs = $this->modelUser->getByUserId($userId); | |||
$this->assertArrayHasKey('id', $rs); | |||
$this->assertArrayHasKey('name', $rs); | |||
$this->assertArrayHasKey('note', $rs); | |||
$this->assertEquals('dogstar', $rs['name']); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<phpunit backupGlobals="false" | |||
backupStaticAttributes="false" | |||
colors="true" | |||
convertErrorsToExceptions="true" | |||
convertNoticesToExceptions="true" | |||
convertWarningsToExceptions="true" | |||
processIsolation="false" | |||
stopOnFailure="false" | |||
syntaxCheck="false" | |||
> | |||
<php> | |||
<ini name="intl.default_locale" value="en"/> | |||
<ini name="intl.error_level" value="0"/> | |||
<ini name="memory_limit" value="-1"/> | |||
</php> | |||
<testsuites> | |||
<testsuite name="common"> | |||
<directory suffix="Test.php">./Common</directory> | |||
</testsuite> | |||
<testsuite name="api"> | |||
<directory suffix="Test.php">./Api</directory> | |||
</testsuite> | |||
<testsuite name="Domain"> | |||
<directory suffix="Test.php">./Domain</directory> | |||
</testsuite> | |||
<testsuite name="Model"> | |||
<directory suffix="Test.php">./Model</directory> | |||
</testsuite> | |||
</testsuites> | |||
</phpunit> | |||
@@ -0,0 +1,25 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<phpunit backupGlobals="false" | |||
backupStaticAttributes="false" | |||
colors="true" | |||
convertErrorsToExceptions="true" | |||
convertNoticesToExceptions="true" | |||
convertWarningsToExceptions="true" | |||
processIsolation="false" | |||
stopOnFailure="false" | |||
syntaxCheck="false" | |||
> | |||
<php> | |||
<ini name="intl.error_level" value="0"/> | |||
<ini name="memory_limit" value="-1"/> | |||
</php> | |||
<testsuites> | |||
<testsuite name="Test Suite"> | |||
<file>./Api/Api_User_Test.php</file> | |||
<file>./Domain/Domain_User_Test.php</file> | |||
<file>./Model/Model_User_Test.php</file> | |||
</testsuite> | |||
</testsuites> | |||
</phpunit> |
@@ -0,0 +1,16 @@ | |||
<?php | |||
/** | |||
* demo接口测试入口 | |||
* @author dogstar 2015-01-28 | |||
*/ | |||
/** ---------------- 根目录定义,自动加载 ---------------- **/ | |||
require_once dirname(__FILE__) . '/../../Public/init.php'; | |||
DI()->loader->addDirs('Demo'); | |||
//日记纪录 - Explorer | |||
DI()->logger = new PhalApi_Logger_Explorer( | |||
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR); | |||
@@ -0,0 +1,10 @@ | |||
##协议许可的权利 - GPL协议 | |||
PhalApi官方网站为 http://www.phalapi.net,依法独立拥有 PhalApi 及官网发布的PhalApi衍生产品著作权。 | |||
PhalApi及其衍生产品著作权受到法律和国际公约保护。使用者需仔细阅读本协议,在理解、同意、并遵守本协 | |||
议的全部条款后,方可开始使用 PhalApi及其衍生 软件。 | |||
本授权协议适用于 http://www.phalapi.net 发布的所有应用程序,PhalApi官方网站拥有对本授权协议的最终 | |||
解释权。 | |||
PhalApi是一个PHP轻量级开源接口框架,并承诺永久免费!请放心使用! |
@@ -0,0 +1,6 @@ | |||
<?php | |||
return array( | |||
'Hello {name}, Welcome to use PhalApi!' => 'Hello {name}, Welcome to use PhalApi!', | |||
'user not exists' => 'user not exists', | |||
); |
@@ -0,0 +1,14 @@ | |||
<?php | |||
/** | |||
* 翻译说明: | |||
* | |||
* 1、带大括号的保留原来写法,如:{name},会被系统动态替换 | |||
* 2、没在以下出现的,可以自行追加 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 2015-02-09 | |||
*/ | |||
return array( | |||
'Hi {name}, welcome to use PhalApi!' => '{name}您好,欢迎使用PhalApi!', | |||
'user not exists' => '用户不存在', | |||
); |
@@ -0,0 +1,6 @@ | |||
<?php | |||
return array( | |||
'Hi {name}, welcome to use PhalApi!' => '{name}您好,歡迎使用PhalApi!', | |||
'user not exists' => '用戶不存在', | |||
); |
@@ -0,0 +1,7 @@ | |||
##扩展类库 | |||
请查看: | |||
``` | |||
http://git.oschina.net/dogstar/PhalApi-Library | |||
``` |
@@ -0,0 +1,33 @@ | |||
<?php | |||
return array( | |||
//请将以下配置拷贝到 ./Config/app.php 文件中 | |||
/** | |||
* 计划任务配置 | |||
*/ | |||
'Task' => array( | |||
//MQ队列设置,可根据使用需要配置 | |||
'mq' => array( | |||
'file' => array( | |||
'path' => API_ROOT . '/Runtime', | |||
'prefix' => 'phalapi_task', | |||
), | |||
'redis' => array( | |||
'host' => '127.0.0.1', | |||
'port' => 6379, | |||
'prefix' => 'phalapi_task', | |||
'auth' => '', | |||
), | |||
), | |||
//Runner设置,如果使用远程调度方式,请加此配置 | |||
'runner' => array( | |||
'remote' => array( | |||
'host' => 'http://library.phalapi.net/demo/', | |||
'timeoutMS' => 3000, | |||
), | |||
), | |||
), | |||
); |
@@ -0,0 +1,21 @@ | |||
<?php | |||
return array( | |||
'tables' => array( | |||
//请将以下配置拷贝到 ./Config/dbs.php 文件对应的位置中,未配置的表将使用默认路由 | |||
//10张表,可根据需要,自行调整表前缀、主键名和路由 | |||
'task_mq' => array( | |||
'prefix' => 'phalapi_', | |||
'key' => 'id', | |||
'map' => array( | |||
array('db' => 'db_demo'), | |||
array('start' => 0, 'end' => 9, 'db' => 'db_demo'), | |||
), | |||
), | |||
) | |||
); | |||
@@ -0,0 +1,109 @@ | |||
CREATE TABLE `phalapi_task_mq` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_0` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_1` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_2` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_3` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_4` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_5` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_6` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_7` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_8` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_9` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
@@ -0,0 +1,13 @@ | |||
CREATE TABLE `phalapi_task_progress` ( | |||
`id` bigint(20) NOT NULL AUTO_INCREMENT, | |||
`title` varchar(200) DEFAULT '' COMMENT '任务标题', | |||
`trigger_class` varchar(50) DEFAULT '' COMMENT '触发器类名', | |||
`fire_params` varchar(255) DEFAULT '' COMMENT '需要传递的参数,格式自定', | |||
`interval_time` int(11) DEFAULT '0' COMMENT '执行间隔,单位:秒', | |||
`enable` tinyint(1) DEFAULT '1' COMMENT '是否启动,1启动,0禁止', | |||
`result` varchar(255) DEFAULT '' COMMENT '运行的结果,以json格式保存', | |||
`state` tinyint(1) DEFAULT '0' COMMENT '进程状态,0空闲,1运行中,-1异常退出', | |||
`last_fire_time` int(11) DEFAULT '0' COMMENT '上一次运行时间', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
@@ -0,0 +1,3 @@ | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', |
@@ -0,0 +1,8 @@ | |||
`title` varchar(200) DEFAULT '' COMMENT '任务标题', | |||
`trigger_class` varchar(50) DEFAULT '' COMMENT '触发器类名', | |||
`fire_params` varchar(255) DEFAULT '' COMMENT '需要传递的参数,格式自定', | |||
`interval_time` int(11) DEFAULT '0' COMMENT '执行间隔,单位:秒', | |||
`enable` tinyint(1) DEFAULT '1' COMMENT '是否启动,1启动,0禁止', | |||
`result` varchar(255) DEFAULT '' COMMENT '运行的结果,以json格式保存', | |||
`state` tinyint(1) DEFAULT '0' COMMENT '进程状态,0空闲,1运行中,-1异常退出', | |||
`last_fire_time` int(11) DEFAULT '0' COMMENT '上一次运行时间', |
@@ -0,0 +1,44 @@ | |||
<?php | |||
/** | |||
* 计划任务客户端类 Task_Lite | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_Lite { | |||
/** | |||
* Task_MQ $mq MQ队列 | |||
*/ | |||
protected $mq; | |||
public function __construct(Task_MQ $mq) { | |||
$this->mq = $mq; | |||
DI()->loader->addDirs('./Library/Task/Task'); | |||
} | |||
/** | |||
* 添加一个计划任务到MQ队列 | |||
* @param string $service 接口服务名称,如:Default.Index | |||
* @param array $params 接口服务参数 | |||
*/ | |||
public function add($service, $params = array()) { | |||
if (empty($service) || count(explode('.', $service)) < 2) { | |||
return FALSE; | |||
} | |||
if (!is_array($params)) { | |||
return FALSE; | |||
} | |||
$rs = $this->mq->add($service, $params); | |||
if (!$rs) { | |||
DI()->logger->debug('task add a new mq', | |||
array('service' => $service, 'params' => $params)); | |||
return FALSE; | |||
} | |||
return TRUE; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
<?php | |||
/** | |||
* MQ队列接口 | |||
* | |||
* - 单个添加,批量弹出 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
interface Task_MQ { | |||
/** | |||
* 单个添加 | |||
* @param string $service 接口服务名称,如:Default.Index | |||
* @param array $params 接口服务参数 | |||
*/ | |||
public function add($service, $params = array()); | |||
/** | |||
* 批量弹出 | |||
* @param string $service 需要获取的接口服务名称 | |||
* @param int $num 弹出的个数 | |||
*/ | |||
public function pop($service, $num = 1); | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
/** | |||
* 数组MQ | |||
* | |||
* - 用于单元测试,或者临时一次性执行 | |||
* - 队列存放于内存的数组中 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_MQ_Array implements Task_MQ { | |||
protected $list = array(); | |||
public function add($service, $params = array()) { | |||
if (!isset($this->list[$service])) { | |||
$this->list[$service] = array(); | |||
} | |||
$this->list[$service][] = $params; | |||
return TRUE; | |||
} | |||
public function pop($service, $num = 1) { | |||
if (empty($this->list[$service])) { | |||
return array(); | |||
} | |||
$rs = array_splice($this->list[$service], 0, $num); | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
<?php | |||
/** | |||
* 数据库MQ | |||
* | |||
* - 队列存放于数据库表中,并支持分表 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_MQ_DB implements Task_MQ { | |||
public function add($service, $params = array()) { | |||
$model = new Model_Task_TaskMq(); | |||
return $model->add($service, $params); | |||
} | |||
public function pop($service, $num = 1) { | |||
$model = new Model_Task_TaskMq(); | |||
return $model->pop($service, $num); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
/** | |||
* 文件MQ | |||
* | |||
* - 队列存放于本地文件 中,不支持分布式MQ | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_MQ_File extends Task_MQ_KeyValue { | |||
public function __construct(PhalApi_Cache_File $fileCache = NULL) { | |||
if ($fileCache === NULL) { | |||
$config = DI()->config->get('app.Task.mq.file'); | |||
if (!isset($config['path'])) { | |||
$config['path'] = API_ROOT . '/Runtime'; | |||
} | |||
if (!isset($config['prefix'])) { | |||
$config['prefix'] = 'phalapi_task'; | |||
} | |||
$fileCache = new PhalApi_Cache_File($config); | |||
} | |||
parent::__construct($fileCache); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
<?php | |||
/** | |||
* 键-值对的 MQ | |||
* | |||
* - 队列存放于Key-Value的缓存中 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20160430 | |||
*/ | |||
class Task_MQ_KeyValue implements Task_MQ { | |||
/** | |||
* @var PhalApi_Cache_Memcached/PhalApi_Cache_Memcache/PhalApi_Cache_File $kvCache 缓存实例 | |||
*/ | |||
protected $kvCache; | |||
public function __construct(PhalApi_Cache $kvCache) { | |||
$this->kvCache = $kvCache; | |||
} | |||
public function add($service, $params = array()) { | |||
$list = $this->kvCache->get($service); | |||
if (empty($list)) { | |||
$list = array(); | |||
} | |||
$list[] = $params; | |||
$this->kvCache->set($service, $list, $this->getExpireTime()); | |||
$list = $this->kvCache->get($service); | |||
return true; | |||
} | |||
public function pop($service, $num = 1) { | |||
$rs = array(); | |||
if ($num <= 0) { | |||
return $rs; | |||
} | |||
$list = $this->kvCache->get($service); | |||
if (empty($list)) { | |||
$list = array(); | |||
} | |||
$rs = array_splice($list, 0, $num); | |||
$this->kvCache->set($service, $list, $this->getExpireTime()); | |||
return $rs; | |||
} | |||
/** | |||
* 最大缓存时间,一年 | |||
*/ | |||
protected function getExpireTime() { | |||
return 31536000; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
<?php | |||
/** | |||
* Memcached MQ | |||
* | |||
* - 队列存放于Memcached/Memcache,但须注意MC默认情况下单个key最大只支持1M大小 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20160430 | |||
*/ | |||
class Task_MQ_Memcached extends Task_MQ_KeyValue { | |||
public function __construct(PhalApi_Cache $mcCache = NULL) { | |||
if ($mcCache === NULL) { | |||
$config = DI()->config->get('app.Task.mq.mc'); | |||
if (!isset($config['host'])) { | |||
$config['host'] = '127.0.0.1'; | |||
} | |||
if (!isset($config['port'])) { | |||
$config['port'] = 11211; | |||
} | |||
//优先使用memcached | |||
$mcCache = extension_loaded('memcached') | |||
? new PhalApi_Cache_Memcached($config) | |||
: new PhalApi_Cache_Memcache($config); | |||
} | |||
$mcCache->set('123123', time(), 31536000); | |||
parent::__construct($mcCache); | |||
} | |||
/** | |||
* 最大缓存时间,29天,因为MC的过期时间不能超过30天 | |||
*/ | |||
protected function getExpireTime() { | |||
return 2505600; | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
<?php | |||
class Task_MQ_Redis implements Task_MQ { | |||
protected $redisCache; | |||
public function __construct(PhalApi_Cache_Redis $redisCache= NULL) { | |||
if ($redisCache === NULL) { | |||
$config = DI()->config->get('app.Task.mq.redis'); | |||
if (!isset($config['host'])) { | |||
$config['host'] = '127.0.0.1'; | |||
} | |||
if (!isset($config['port'])) { | |||
$config['port'] = 6379; | |||
} | |||
if (!isset($config['prefix'])) { | |||
$config['prefix'] = 'phalapi_task'; | |||
} | |||
$redisCache = new PhalApi_Cache_Redis($config); | |||
} | |||
$this->redisCache = $redisCache; | |||
} | |||
public function add($service, $params = array()) { | |||
$num = $this->redisCache->rPush($service, $params); | |||
return $num > 0 ? TRUE : FALSE; | |||
} | |||
public function pop($service, $num = 1) { | |||
$rs = array(); | |||
while($num > 0) { | |||
$params = $this->redisCache->lPop($service); | |||
if ($params === NULL) { | |||
break; | |||
} | |||
$rs[] = $params; | |||
$num--; | |||
} | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
<?php | |||
/** | |||
* 计划任务进程类 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150520 | |||
*/ | |||
class Task_Progress { | |||
/** | |||
* @var int MAX_LAST_FIRE_TIME_INTERVAL 修复的最大时间间隔 | |||
*/ | |||
const MAX_LAST_FIRE_TIME_INTERVAL = 86400; | |||
/** | |||
* @var Model_Task_TaskProgress 对数据库的操作 | |||
*/ | |||
protected $model; | |||
public function __construct() { | |||
$this->model = new Model_Task_TaskProgress(); | |||
} | |||
/** | |||
* 进行进程调度 | |||
* | |||
* - 1、尝试修复异常的任务 | |||
* - 2、执行全部空闲的任务 | |||
*/ | |||
public function run() { | |||
$this->tryToResetWrongItems(); | |||
$this->runAllWaittingItems(); | |||
return TRUE; | |||
} | |||
protected function tryToResetWrongItems() { | |||
$maxLastFireTime = $_SERVER['REQUEST_TIME'] - self::MAX_LAST_FIRE_TIME_INTERVAL; | |||
$wrongItems = $this->model->getWrongItems($maxLastFireTime); | |||
foreach ($wrongItems as $item) { | |||
$this->model->resetWrongItems($item['id']); | |||
DI()->logger->debug('task try to reset wrong items', $item); | |||
} | |||
} | |||
protected function runAllWaittingItems() { | |||
$waittingItems = $this->model->getAllWaittingItems(); | |||
foreach ($waittingItems as $item) { | |||
// | |||
if (!$this->model->isRunnable($item['id'])) { | |||
continue; | |||
} | |||
$class = $item['trigger_class']; | |||
$params = $item['fire_params']; | |||
if (empty($class) || !class_exists($class)) { | |||
DI()->logger->error('Error: task can not run illegal class', $item); | |||
$this->model->updateExceptionItem($item['id'], 'task can not run illegal class'); | |||
continue; | |||
} | |||
$trigger = new $class(); | |||
if (!is_callable(array($class, 'fire'))) { | |||
DI()->logger->error('Error: task can not call fire()', $item); | |||
$this->model->updateExceptionItem($item['id'], 'task can not call fire()'); | |||
continue; | |||
} | |||
$this->model->setRunningState($item['id']); | |||
try { | |||
$result = call_user_func(array($trigger, 'fire'), $params); | |||
$this->model->updateFinishItem($item['id'], $result); | |||
} catch (Exception $ex) { | |||
throw $ex; | |||
$this->model->updateExceptionItem($item['id'], $ex->getMessage()); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
<?php | |||
/** | |||
* 触发器接口 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150520 | |||
*/ | |||
interface Task_Progress_Trigger { | |||
/** | |||
* 进程的具体操作 | |||
* @param string $params 对应数据库表task_progress.fire_params字段 | |||
*/ | |||
public function fire($params); | |||
} |
@@ -0,0 +1,22 @@ | |||
<?php | |||
/** | |||
* 通用 触发器接口 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150520 | |||
*/ | |||
class Task_Progress_Trigger_Common implements Task_Progress_Trigger { | |||
public function fire($params) { | |||
$paramsArr = explode('&', $params); | |||
$service = !empty($paramsArr[0]) ? trim($paramsArr[0]) : ''; | |||
$mqClass = !empty($paramsArr[1]) ? trim($paramsArr[1]) : 'Task_MQ_Redis'; | |||
$runnerClass = !empty($paramsArr[2]) ? trim($paramsArr[2]) : 'Task_Runner_Local'; | |||
$mq = new $mqClass(); | |||
$runner = new $runnerClass($mq); | |||
return $runner->go($service); | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
<?php | |||
/** | |||
* 计划任务调度器 | |||
* | |||
* - 异常失败,会轮循重试 | |||
* - 彩蛋式的抽象方法名 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
abstract class Task_Runner { | |||
/** | |||
* @var MQ队列实例 | |||
*/ | |||
protected $mq; | |||
/** | |||
* @var int $step 批次的数据,步长 | |||
*/ | |||
protected $step; | |||
/** | |||
* @param Task_MQ $mq MQ队列实例 | |||
* @param int $step 批次的数据,步长 | |||
*/ | |||
public function __construct(Task_MQ $mq, $step = 10) { | |||
$this->mq = $mq; | |||
$this->step = max(1, intval($step)); | |||
} | |||
/** | |||
* 执行任务 | |||
* @param string $service MQ中的接口服务名称,如:Default.Index | |||
* @return array('total' => 总数量, 'fail' => 失败数量) | |||
*/ | |||
public function go($service) { | |||
$rs = array('total' => 0, 'fail' => 0); | |||
$todoList = $this->mq->pop($service, $this->step); | |||
$failList = array(); | |||
while (!empty($todoList)) { | |||
$rs['total'] += count($todoList); | |||
foreach ($todoList as $params) { | |||
try { | |||
$isFinish = $this->youGo($service, $params); | |||
if (!$isFinish) { | |||
$rs['fail'] ++; | |||
} | |||
} catch (PhalApi_Exception_InternalServerError $ex) { | |||
$rs['fail'] ++; | |||
$failList[] = $params; | |||
DI()->logger->error('task occur exception to go', | |||
array('service' => $service, 'params' => $params, 'error' => $ex->getMessage())); | |||
} | |||
} | |||
$todoList = $this->mq->pop($service, $this->step); | |||
} | |||
foreach ($failList as $params) { | |||
$this->mq->add($service, $params); | |||
} | |||
return $rs; | |||
} | |||
/** | |||
* 具体的执行,这里使用了一个彩蛋的命名 | |||
* @param string $service MQ中的接口服务名称,如:Default.Index | |||
* @param array $params 参数 | |||
* @return boolean 成功返回TRUE,失败返回FALSE | |||
*/ | |||
abstract protected function youGo($service, $params); | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
/** | |||
* 本地调度器 Task_Runner_Local | |||
* | |||
* - 本地内部调度 | |||
* - 不能在Api请求时进行此调度 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_Runner_Local extends Task_Runner { | |||
protected function youGo($service, $params) { | |||
$params['service'] = $service; | |||
DI()->request = new PhalApi_Request($params); | |||
DI()->response = new PhalApi_Response_Json(); | |||
$phalapi = new PhalApi(); | |||
$rs = $phalapi->response(); | |||
$apiRs = $rs->getResult(); | |||
if ($apiRs['ret'] != 200) { | |||
DI()->logger->debug('task local go fail', | |||
array('servcie' => $service, 'params' => $params, 'rs' => $apiRs)); | |||
return FALSE; | |||
} | |||
return TRUE; | |||
} | |||
} | |||
@@ -0,0 +1,60 @@ | |||
<?php | |||
/** | |||
* 远程调度器 Task_Runner_Remote | |||
* | |||
* - 通过远程请求接口实现任务调度 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Task_Runner_Remote extends Task_Runner { | |||
/** | |||
* @var Task_Runner_Remote_Connector 远程接口连接器实例 | |||
*/ | |||
protected $contector; | |||
/** | |||
* @var int $timeoutMS 接口超时(单位:毫秒) | |||
*/ | |||
protected $timeoutMS; | |||
/** | |||
* @var int 默认最大接口超时 | |||
*/ | |||
const MAX_TIMEOUT_MS = 3000; | |||
public function __construct(Task_MQ $mq, $step = 10, Task_Runner_Remote_Connector $contector = NULL) { | |||
$config = DI()->config->get('app.Task.runner.remote'); | |||
if ($contector === NULL) { | |||
if (empty($config['host'])) { | |||
throw new PhalApi_Exception_InternalServerError(T('task miss api host for')); | |||
} | |||
$contector = new Task_Runner_Remote_Connector_Http($config); | |||
} | |||
$this->contector = $contector; | |||
$this->timeoutMS = isset($config['timeoutMS']) ? intval($config['timeoutMS']) : self::MAX_TIMEOUT_MS; | |||
parent::__construct($mq, $step); | |||
} | |||
protected function youGo($service, $params) { | |||
$rs = $this->contector->request($service, $params, $this->timeoutMS); | |||
if ($this->contector->getRet() == 404) { | |||
throw PhalApi_Exception_InternalServerError('task request api time out', | |||
array('url' => $this->contector->getUrl())); | |||
} | |||
$isOk = $this->contector->getRet() == 200 ? TRUE : FALSE; | |||
if (!$isOk) { | |||
DI()->logger->debug('task remote request not ok', | |||
array('url' => $this->contector->getUrl(), 'ret' => $this->contector->getRet(), 'msg' => $this->contector->getMsg())); | |||
} | |||
return $isOk; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
<?php | |||
/** | |||
* 远程接口连接器 Task_Runner_Remote_Connector | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
abstract class Task_Runner_Remote_Connector { | |||
protected $host; | |||
protected $params = array(); | |||
protected $moreParams = array(); | |||
protected $url; | |||
protected $ret; | |||
protected $msg; | |||
protected $data = array(); | |||
public function __construct($config) { | |||
$this->host = $config['host']; | |||
$this->moreParams = isset($config['params']) ? $config['params'] : array(); | |||
} | |||
/** | |||
* 接口请求,超时时ret为404 | |||
* @param string $service MQ中的接口服务名称,如:Default.Index | |||
* @param array $params 参数 | |||
* @param int $timeoutMS 接口超时(单位:毫秒) | |||
* @return array | |||
*/ | |||
public function request($service, $params = array(), $timeoutMs = 3000) { | |||
$this->url = $this->host . '?service=' . $service; | |||
$params = array_merge($this->moreParams, $params); | |||
$apiRs = $this->doRequest($this->url, $params, $timeoutMs); | |||
if ($apiRs === FALSE) { | |||
$this->ret = 404; | |||
$this->msg = T('time out'); | |||
DI()->logger->debug('task request api time out', array('url' => $this->url)); | |||
return $this->getData(); | |||
} | |||
$rs = json_decode($apiRs, true); | |||
if (empty($rs) || !isset($rs['ret'])) { | |||
$this->ret = 500; | |||
$this->msg = T('nothing return or illegal json: {rs}', array('rs' => $apiRs)); | |||
return $this->getData(); | |||
} | |||
$this->ret = $rs['ret']; | |||
$this->data = $rs['data']; | |||
$this->msg = $rs['msg']; | |||
return $this->getData(); | |||
} | |||
public function getRet() { | |||
return $this->ret; | |||
} | |||
public function getData() { | |||
return $this->data; | |||
} | |||
public function getMsg() { | |||
return $this->msg; | |||
} | |||
public function getUrl() { | |||
return $this->url; | |||
} | |||
abstract protected function doRequest($url, $data, $timeoutMs); | |||
} |
@@ -0,0 +1,10 @@ | |||
<?php | |||
class Task_Runner_Remote_Connector_Http extends Task_Runner_Remote_Connector { | |||
protected function doRequest($url, $data, $timeoutMs) { | |||
$curl = DI()->get('curl', 'PhalApi_CUrl'); | |||
return $curl->post($url, $data, $timeoutMs); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
<?php | |||
/** | |||
* 数据库MQ | |||
* | |||
* - 队列存放于数据库表中,并支持分表 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 20150516 | |||
*/ | |||
class Model_Task_TaskMq extends PhalApi_Model_NotORM { | |||
protected function getTableName($id = NULL) { | |||
$prefix = hexdec(substr(sha1($id), -1)) % 10; | |||
return 'task_mq_' . $prefix; | |||
} | |||
public function add($service, $params = array()) { | |||
$data = array( | |||
'service' => $service, | |||
'params' => json_encode($params), | |||
'create_time' => time(), | |||
); | |||
$id = $this->insert($data, $service); | |||
return $id > 0 ? TRUE : FALSE; | |||
} | |||
public function pop($service, $num = 1) { | |||
$rows = $this->getORM($service) | |||
->select('id, params') | |||
->where('service', $service) | |||
->order('id ASC') | |||
->limit(0, $num) | |||
->fetchAll(); | |||
if (empty($rows)) { | |||
return array(); | |||
} | |||
$ids = array(); | |||
foreach ($rows as $row) { | |||
$ids[] = $row['id']; | |||
} | |||
$this->getORM($service)->where('id', $ids)->delete(); | |||
$rs = array(); | |||
foreach ($rows as $row) { | |||
$params = json_decode($row['params'], TRUE); | |||
if (!is_array($params)) { | |||
$params = array(); | |||
} | |||
$rs[] = $params; | |||
} | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
<?php | |||
class Model_Task_TaskProgress extends PhalApi_Model_NotORM { | |||
const STATE_WAITTING = 0; | |||
const STATE_RUNNING = 1; | |||
const STATE_EXCEPTION = -1; | |||
const ENABLE_ON = 1; | |||
const ENABLE_OFF = 0; | |||
protected function getTableName($id = NULL) { | |||
return 'task_progress'; | |||
} | |||
public function getWrongItems($maxLastFireTime) { | |||
$rows = $this->getORM() | |||
->select('id, title') | |||
->where('state != ?', self::STATE_WAITTING) | |||
->where('last_fire_time < ?', $maxLastFireTime) | |||
->where('enable = ?', self::ENABLE_ON) | |||
->order('last_fire_time ASC') | |||
->fetchAll(); | |||
return !empty($rows) ? $rows : array(); | |||
} | |||
public function resetWrongItems($id) { | |||
return $this->update($id, array('state' => self::STATE_WAITTING)); | |||
} | |||
public function getAllWaittingItems() { | |||
$rows = $this->getORM() | |||
->select('id, title, trigger_class, fire_params') | |||
->where('state', self::STATE_WAITTING) | |||
->where('interval_time + last_fire_time < ?', $_SERVER['REQUEST_TIME']) | |||
->where('enable = ?', self::ENABLE_ON) | |||
->fetchAll(); | |||
return !empty($rows) ? $rows : array(); | |||
} | |||
public function isRunnable($id) { | |||
$row = $this->get($id, 'enable, state'); | |||
if (empty($row)) { | |||
return FALSE; | |||
} | |||
return ($row['state'] == self::STATE_WAITTING && $row['enable'] == self::ENABLE_ON) ? TRUE : FALSE; | |||
} | |||
public function setRunningState($id) { | |||
return $this->update($id, array('state' => self::STATE_RUNNING)); | |||
} | |||
public function updateFinishItem($id, $result) { | |||
$data = array( | |||
'result' => json_encode($result), | |||
'state' => self::STATE_WAITTING, | |||
'last_fire_time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
return $this->update($id, $data); | |||
} | |||
public function updateExceptionItem($id, $errorMsg) { | |||
$data = array( | |||
'result' => $errorMsg, | |||
'state' => self::STATE_EXCEPTION, | |||
'last_fire_time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
return $this->update($id, $data); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskMQArray_Test | |||
* | |||
* 针对 ../../MQ/Array.php Task_MQ_Array 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150516 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_MQ_Array')) { | |||
require dirname(__FILE__) . '/../../MQ/Array.php'; | |||
} | |||
class PhpUnderControl_TaskMQArray_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskMQArray; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskMQArray = new Task_MQ_Array(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'Demo.Test'; | |||
$params = array ( | |||
'id' => 1, | |||
); | |||
$rs = $this->taskMQArray->add($service, $params); | |||
$this->assertTrue($rs); | |||
} | |||
/** | |||
* @group testPop | |||
*/ | |||
public function testPop() | |||
{ | |||
$service = 'Demo.Update'; | |||
$num = '1'; | |||
$rs = $this->taskMQArray->pop($service, $num); | |||
$this->assertEmpty($rs); | |||
$rs = $this->taskMQArray->add($service, array('name' => 'phalapi')); | |||
$rs = $this->taskMQArray->add($service, array('name' => 'net')); | |||
$rs = $this->taskMQArray->pop($service, 1); | |||
$this->assertEquals(array(array('name' => 'phalapi')), $rs); | |||
$rs = $this->taskMQArray->pop($service, 1); | |||
$this->assertEquals(array(array('name' => 'net')), $rs); | |||
} | |||
} |
@@ -0,0 +1,70 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskMQDB_Test | |||
* | |||
* 针对 ../../MQ/DB.php Task_MQ_DB 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150516 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_MQ_DB')) { | |||
require dirname(__FILE__) . '/../../MQ/DB.php'; | |||
} | |||
class PhpUnderControl_TaskMQDB_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskMQDB; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskMQDB = new Task_MQ_DB(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'Demo.Test'; | |||
$params = array ( | |||
'id' => 1, | |||
); | |||
$rs = $this->taskMQDB->add($service, $params); | |||
$this->assertTrue($rs); | |||
} | |||
/** | |||
* @group testPop | |||
*/ | |||
public function testPop() | |||
{ | |||
$this->assertEmpty($this->taskMQDB->pop('NoThisServcie.Index')); | |||
$service = 'Demo.Update'; | |||
$num = '1'; | |||
$rs = $this->taskMQDB->add($service, array('name' => 'phalapi')); | |||
$rs = $this->taskMQDB->add($service, array('name' => 'net')); | |||
$rs = $this->taskMQDB->add($service, array('name' => 'net')); | |||
$rs = $this->taskMQDB->add($service, array('name' => 'net')); | |||
$rs = $this->taskMQDB->pop($service, 1); | |||
$this->assertEquals(array(array('name' => 'phalapi')), $rs); | |||
$rs = $this->taskMQDB->pop($service, 2); | |||
$this->assertEquals(array(array('name' => 'net'), array('name' => 'net')), $rs); | |||
$rs = $this->taskMQDB->pop($service, 10); | |||
$this->assertCount(1, $rs); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskMQFile_Test | |||
* | |||
* 针对 ../../MQ/File.php Task_MQ_File 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20160430 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_MQ_File')) { | |||
require dirname(__FILE__) . '/../../MQ/File.php'; | |||
} | |||
class PhpUnderControl_TaskMQFile_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskMQFile; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskMQFile = new Task_MQ_File(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'Task_MQ_File_Default.Index'; | |||
$params = array ( | |||
'username' => 'dogstar', | |||
); | |||
$rs = $this->taskMQFile->add($service, $params); | |||
$rs = $this->taskMQFile->add($service, $params); | |||
$rs = $this->taskMQFile->add($service, $params); | |||
} | |||
/** | |||
* @group testPop | |||
*/ | |||
public function testPop() | |||
{ | |||
$service = 'Task_MQ_File_Default.Index'; | |||
$num = 2; | |||
$rs = $this->taskMQFile->pop($service, $num); | |||
$this->assertCount($num, $rs); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskMQMemcached_Test | |||
* | |||
* 针对 ../../MQ/Memcached.php Task_MQ_Memcached 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20160430 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_MQ_Memcached')) { | |||
require dirname(__FILE__) . '/../../MQ/Memcached.php'; | |||
} | |||
class PhpUnderControl_TaskMQMemcached_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskMQMemcached; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskMQMemcached = new Task_MQ_Memcached(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'Task_MQ_Memcached_Default.Index'; | |||
$params = array ( | |||
'username' => 'dogstar', | |||
); | |||
$rs = $this->taskMQMemcached->add($service, $params); | |||
$rs = $this->taskMQMemcached->add($service, $params); | |||
$rs = $this->taskMQMemcached->add($service, $params); | |||
} | |||
/** | |||
* @group testPop | |||
*/ | |||
public function testPop() | |||
{ | |||
$service = 'Task_MQ_Memcached_Default.Index'; | |||
$num = 2; | |||
$rs = $this->taskMQMemcached->pop($service, $num); | |||
$this->assertCount($num, $rs); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskMQRedis_Test | |||
* | |||
* 针对 ../../MQ/Redis.php Task_MQ_Redis 类的PHPUnit单元测试 | |||
* | |||
* @author: Task_MQ_Redis 20150516 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_MQ_Redis')) { | |||
require dirname(__FILE__) . '/../../MQ/Redis.php'; | |||
} | |||
class PhpUnderControl_TaskMQRedis_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskMQRedis; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskMQRedis = new Task_MQ_Redis(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'TaskRedis.Test'; | |||
$params = array ( | |||
'id' => 1, | |||
); | |||
$rs = $this->taskMQRedis->add($service, $params); | |||
$this->taskMQRedis->add($service, array('id' => 2)); | |||
} | |||
/** | |||
* @group testPop | |||
*/ | |||
public function testPop() | |||
{ | |||
$service = 'TaskRedis.Test'; | |||
$num = 2; | |||
$rs = $this->taskMQRedis->pop($service, $num); | |||
$this->assertEquals(array(array('id' => 1), array('id' => 2)), $rs); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskRunnerLocal_Test | |||
* | |||
* 针对 ../../Runner/Local.php Task_Runner_Local 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150516 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_Runner_Local')) { | |||
require dirname(__FILE__) . '/../../Runner/Local.php'; | |||
} | |||
class PhpUnderControl_TaskRunnerLocal_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskRunnerLocal; | |||
public $mq; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->mq = new Task_MQ_Array(); | |||
$this->taskRunnerLocal = new Task_Runner_Local($this->mq); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
public function testHere() | |||
{ | |||
$service1 = 'TestTaskDemo.Update1'; | |||
$this->mq->add($service1, array('name' => 'phalapi')); | |||
$this->mq->add($service1, array('name' => 'net')); | |||
$service2 = 'TestTaskDemo.Update2'; | |||
$this->mq->add($service2, array('id' => 1)); | |||
$rs = $this->taskRunnerLocal->go($service1); | |||
$this->assertEquals(2, $rs['total']); | |||
$this->assertEquals(0, $rs['fail']); | |||
$rs = $this->taskRunnerLocal->go($service2); | |||
$this->assertEquals(1, $rs['total']); | |||
$this->assertEquals(1, $rs['fail']); | |||
$rs = $this->taskRunnerLocal->go('TestTaskDemo.Update3'); | |||
$this->assertEquals(0, $rs['total']); | |||
$this->assertEquals(0, $rs['fail']); | |||
} | |||
} | |||
class Api_TestTaskDemo extends PhalApi_Api { | |||
public function update1() { | |||
return array('code' => 0); | |||
} | |||
public function update2() { | |||
throw new PhalApi_Exception_InternalServerError('just for test'); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskRunnerRemote_Test | |||
* | |||
* 针对 ../../Runner/Remote.php Task_Runner_Remote 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150516 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Task_Runner_Remote')) { | |||
require dirname(__FILE__) . '/../../Runner/Remote.php'; | |||
} | |||
class PhpUnderControl_TaskRunnerRemote_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskRunnerRemote; | |||
protected $mq; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->mq = new Task_MQ_Array(); | |||
$this->taskRunnerRemote = new Task_Runner_Remote($this->mq); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
public function testHere() | |||
{ | |||
$service1 = 'Default.Index'; | |||
$this->mq->add($service1, array('username' => 'phalapi')); | |||
$this->mq->add($service1, array('username' => 'net')); | |||
$service2 = 'WrongUser.GetBaseInfo'; | |||
$this->mq->add($service2, array('userId' => 1)); | |||
$rs = $this->taskRunnerRemote->go($service1); | |||
$this->assertEquals(2, $rs['total']); | |||
$this->assertEquals(0, $rs['fail']); | |||
$rs = $this->taskRunnerRemote->go($service2); | |||
$this->assertEquals(1, $rs['total']); | |||
$this->assertEquals(1, $rs['fail']); | |||
$rs = $this->taskRunnerRemote->go('TestTaskDemo.Update'); | |||
$this->assertEquals(0, $rs['total']); | |||
$this->assertEquals(0, $rs['fail']); | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskLite_Test | |||
* | |||
* 针对 ../Lite.php Task_Lite 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150514 | |||
*/ | |||
require_once dirname(__FILE__) . '/test_env.php'; | |||
if (!class_exists('Task_Lite')) { | |||
require dirname(__FILE__) . '/../Lite.php'; | |||
} | |||
class PhpUnderControl_TaskLite_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskLite; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskLite = new Task_Lite(new Task_MQ_File()); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testAdd | |||
*/ | |||
public function testAdd() | |||
{ | |||
$service = 'Demo.Update'; | |||
$params = array ( | |||
'id' => 888 | |||
); | |||
$rs = $this->taskLite->add($service, $params); | |||
$this->assertTrue($rs); | |||
} | |||
public function testAddWrong() | |||
{ | |||
$service = 'Demo'; | |||
$rs = $this->taskLite->add($service); | |||
$this->assertFalse($rs); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskProgress_Test | |||
* | |||
* 针对 ../Progress.php Task_Progress 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150519 | |||
*/ | |||
require_once dirname(__FILE__) . '/test_env.php'; | |||
if (!class_exists('Task_Progress')) { | |||
require dirname(__FILE__) . '/../Progress.php'; | |||
} | |||
class PhpUnderControl_TaskProgress_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $taskProgress; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->taskProgress = new Task_Progress(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testRun | |||
*/ | |||
public function testRun() | |||
{ | |||
$rs = $this->taskProgress->run(); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_TaskRunner_Test | |||
* | |||
* 针对 ../Runner.php Task_Runner 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150515 | |||
*/ | |||
require_once dirname(__FILE__) . '/test_env.php'; | |||
if (!class_exists('Task_Runner')) { | |||
require dirname(__FILE__) . '/../Runner.php'; | |||
} | |||
class PhpUnderControl_TaskRunner_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
protected $fileMq; | |||
public $taskRunner; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->fileMq = new Task_MQ_File(); | |||
$this->taskRunner = new Task_Runner_Mock($this->fileMq); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGo | |||
*/ | |||
public function testGo() | |||
{ | |||
$service = 'Demo.TestGo'; | |||
$this->fileMq->add($service, array()); | |||
$this->fileMq->add($service, array('id' => 123)); | |||
$this->fileMq->add($service, array('id' => 888, 'name' => 'phalapi')); | |||
$rs = $this->taskRunner->go($service); | |||
//var_dump($rs); | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('total', $rs); | |||
$this->assertArrayHasKey('fail', $rs); | |||
$this->assertEquals(3, $rs['total']); | |||
$this->assertEquals(0, $rs['fail']); | |||
} | |||
} | |||
class Task_Runner_Mock extends Task_Runner { | |||
protected function youGo($service, $params) { | |||
echo "Task_Runner_Mock::youGo(", $service , ", ", json_encode($params), ") ... \n"; | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
<?php | |||
$_GET['debug'] = $_GET['__sql__'] = 1; | |||
require_once dirname(__FILE__) . '/../../../Public/init.php'; | |||
//require_once '/home/dogstar/projects/library.phalapi.net/Public/init.php'; | |||
DI()->loader->addDirs('Demo'); | |||
DI()->loader->addDirs('Library'); | |||
DI()->loader->addDirs('./Library/Task/Task'); | |||
DI()->logger = new PhalApi_Logger_Explorer( | |||
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR); | |||
SL('en'); |
@@ -0,0 +1,32 @@ | |||
#!/usr/bin/env php | |||
<?php | |||
require_once dirname(__FILE__) . '/../../../../Public/init.php'; | |||
//require_once '/home/dogstar/projects/library.phalapi.net/Public/init.php'; | |||
DI()->loader->addDirs('Demo'); | |||
if ($argc < 2) { | |||
echo "Usage: $argv[0] <service> \n\n"; | |||
exit(1); | |||
} | |||
$service = trim($argv[1]); | |||
echo "Input params(json):\n"; | |||
$params = trim(fgets(STDIN)); | |||
$params = json_decode($params, true); | |||
if (is_array($params)) { | |||
$params = array(); | |||
} | |||
$mq = new Task_MQ_Array(); | |||
$taskLite = new Task_Lite($mq); | |||
$taskLite->add($service, $params); | |||
$runner = new Task_Runner_Local($mq); | |||
$rs = $runnter->go($service); | |||
echo "\nDone:\n", json_encode($rs), "\n\n"; | |||
@@ -0,0 +1,15 @@ | |||
<?php | |||
require_once dirname(__FILE__) . '/../../Public/init.php'; | |||
//require_once '/home/dogstar/projects/library.phalapi.net/Public/init.php'; | |||
DI()->loader->addDirs(array('Demo', 'Library', 'Library/Task/Task')); | |||
try { | |||
$progress = new Task_Progress(); | |||
$progress->run(); | |||
} catch (Exception $ex) { | |||
echo $ex->getMessage(); | |||
echo "\n\n"; | |||
echo $ex->getTraceAsString(); | |||
// notify ... | |||
} |
@@ -0,0 +1,23 @@ | |||
.settings | |||
.settings/* | |||
.buildpath | |||
.project | |||
*.log | |||
./Demo/Api/DogstarTest.php | |||
Demo/Api/DogstarTest.php | |||
*.bak | |||
*.dat | |||
*.zip | |||
*.tar | |||
*.swp | |||
.DS_Store | |||
*.DS_Store | |||
.idea |
@@ -0,0 +1,15 @@ | |||
<?php | |||
/** | |||
* 请在下面放置任何您需要的应用配置 | |||
*/ | |||
return array( | |||
/** | |||
* 应用接口层的统一参数 | |||
*/ | |||
'apiCommonRules' => array( | |||
//'sign' => array('name' => 'sign', 'require' => true), | |||
), | |||
); |
@@ -0,0 +1,45 @@ | |||
<?php | |||
/** | |||
* 分库分表的自定义数据库路由配置 | |||
*/ | |||
return array( | |||
/** | |||
* DB数据库服务器集群 | |||
*/ | |||
'servers' => array( | |||
'db_ctrip' => array( //服务器标记 | |||
'host' => 'localhost', //数据库域名 | |||
'name' => 'phalapi_Ctrip', //数据库名字 | |||
'user' => 'root', //数据库用户名 | |||
'password' => '123456', //数据库密码 | |||
'port' => '3306', //数据库端口 | |||
'charset' => 'UTF8', //数据库字符集 | |||
), | |||
), | |||
/** | |||
* 自定义路由表 | |||
*/ | |||
'tables' => array( | |||
//通用路由 | |||
'__default__' => array( | |||
'prefix' => 'Ctr_', | |||
'key' => 'id', | |||
'map' => array( | |||
array('db' => 'db_ctrip'), | |||
), | |||
), | |||
/** | |||
'demo' => array( //表名 | |||
'prefix' => 'Ctr_', //表名前缀 | |||
'key' => 'id', //表主键名 | |||
'map' => array( //表路由配置 | |||
array('db' => 'db_ctrip'), //单表配置:array('db' => 服务器标记) | |||
array('start' => 0, 'end' => 2, 'db' => 'db_ctrip'), //分表配置:array('start' => 开始下标, 'end' => 结束下标, 'db' => 服务器标记) | |||
), | |||
), | |||
*/ | |||
), | |||
); |
@@ -0,0 +1,26 @@ | |||
<?php | |||
/** | |||
* 以下配置为系统级的配置,通常放置不同环境下的不同配置 | |||
*/ | |||
return array( | |||
/** | |||
* 默认环境配置 | |||
*/ | |||
'debug' => false, | |||
/** | |||
* MC缓存服务器参考配置 | |||
*/ | |||
'mc' => array( | |||
'host' => '127.0.0.1', | |||
'port' => 11211, | |||
), | |||
/** | |||
* 加密 | |||
*/ | |||
'crypt' => array( | |||
'mcrypt_iv' => '12345678', //8位 | |||
), | |||
); |
@@ -0,0 +1,33 @@ | |||
<?php | |||
/** | |||
* 默认接口服务类 | |||
* | |||
* @author: dogstar <chanzonghuang@gmail.com> 2014-10-04 | |||
*/ | |||
class Api_Default extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'index' => array( | |||
'username' => array('name' => 'username', 'default' => 'PHPer', ), | |||
), | |||
); | |||
} | |||
/** | |||
* 默认接口服务 | |||
* @return string title 标题 | |||
* @return string content 内容 | |||
* @return string version 版本,格式:X.X.X | |||
* @return int time 当前时间戳 | |||
*/ | |||
public function index() { | |||
return array( | |||
'title' => 'Hello World!', | |||
'content' => T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), | |||
'version' => PHALAPI_VERSION, | |||
'time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ApiDefault_Test | |||
* | |||
* 针对 ../../Api/Default.php Api_Default 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150201 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Api_Default')) { | |||
require dirname(__FILE__) . '/../../Api/Default.php'; | |||
} | |||
class PhpUnderControl_ApiDefault_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $apiDefault; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->apiDefault = new Api_Default(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetRules | |||
*/ | |||
public function testGetRules() | |||
{ | |||
$rs = $this->apiDefault->getRules(); | |||
$this->assertNotEmpty($rs); | |||
} | |||
public function testIndex() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=Default.Index&username=dogstar'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('title', $rs); | |||
$this->assertArrayHasKey('content', $rs); | |||
$this->assertArrayHasKey('version', $rs); | |||
$this->assertArrayHasKey('time', $rs); | |||
$this->assertEquals('dogstar您好,欢迎使用PhalApi!', $rs['content']); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<phpunit backupGlobals="false" | |||
backupStaticAttributes="false" | |||
colors="true" | |||
convertErrorsToExceptions="true" | |||
convertNoticesToExceptions="true" | |||
convertWarningsToExceptions="true" | |||
processIsolation="false" | |||
stopOnFailure="false" | |||
syntaxCheck="false" | |||
> | |||
<php> | |||
<ini name="intl.default_locale" value="en"/> | |||
<ini name="intl.error_level" value="0"/> | |||
<ini name="memory_limit" value="-1"/> | |||
</php> | |||
<testsuites> | |||
<testsuite name="common"> | |||
<directory suffix="Test.php">./Common</directory> | |||
</testsuite> | |||
<testsuite name="api"> | |||
<directory suffix="Test.php">./Api</directory> | |||
</testsuite> | |||
<testsuite name="Domain"> | |||
<directory suffix="Test.php">./Domain</directory> | |||
</testsuite> | |||
<testsuite name="Model"> | |||
<directory suffix="Test.php">./Model</directory> | |||
</testsuite> | |||
</testsuites> | |||
</phpunit> | |||
@@ -0,0 +1,16 @@ | |||
<?php | |||
/** | |||
* demo接口测试入口 | |||
* @author dogstar 2015-01-28 | |||
*/ | |||
/** ---------------- 根目录定义,自动加载 ---------------- **/ | |||
require_once dirname(__FILE__) . '/../../Public/init.php'; | |||
DI()->loader->addDirs('Ctrip'); | |||
//日记纪录 - Explorer | |||
DI()->logger = new PhalApi_Logger_Explorer( | |||
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR); | |||
@@ -0,0 +1,9 @@ | |||
CREATE TABLE `phalapi_test`.`tbl_user` ( | |||
`id` INT NOT NULL, | |||
`name` VARCHAR(45) NULL, | |||
`note` VARCHAR(45) NULL, | |||
PRIMARY KEY (`id`)); | |||
INSERT INTO `phalapi_test`.`tbl_user` (`id`, `name`, `note`) VALUES ('1', 'dogstar', 'oschina'); | |||
@@ -0,0 +1,2 @@ | |||
`name` VARCHAR(45) NULL, | |||
`note` VARCHAR(45) NULL, |
@@ -0,0 +1,33 @@ | |||
<?php | |||
/** | |||
* 默认接口服务类 | |||
* | |||
* @author: dogstar <chanzonghuang@gmail.com> 2014-10-04 | |||
*/ | |||
class Api_Default extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'index' => array( | |||
'username' => array('name' => 'username', 'default' => 'PHPer', ), | |||
), | |||
); | |||
} | |||
/** | |||
* 默认接口服务 | |||
* @return string title 标题 | |||
* @return string content 内容 | |||
* @return string version 版本,格式:X.X.X | |||
* @return int time 当前时间戳 | |||
*/ | |||
public function index() { | |||
return array( | |||
'title' => 'Hello World!', | |||
'content' => T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), | |||
'version' => PHALAPI_VERSION, | |||
'time' => $_SERVER['REQUEST_TIME'], | |||
); | |||
} | |||
} |
@@ -0,0 +1,70 @@ | |||
<?php | |||
/** | |||
* 用户信息类 | |||
*/ | |||
class Api_User extends PhalApi_Api { | |||
public function getRules() { | |||
return array( | |||
'getBaseInfo' => array( | |||
'userId' => array('name' => 'user_id', 'type' => 'int', 'min' => 1, 'require' => true, 'desc' => '用户ID'), | |||
), | |||
'getMultiBaseInfo' => array( | |||
'userIds' => array('name' => 'user_ids', 'type' => 'array', 'format' => 'explode', 'require' => true, 'desc' => '用户ID,多个以逗号分割'), | |||
), | |||
); | |||
} | |||
/** | |||
* 获取用户基本信息 | |||
* @desc 用于获取单个用户基本信息 | |||
* @return int code 操作码,0表示成功, 1表示用户不存在 | |||
* @return object info 用户信息对象 | |||
* @return int info.id 用户ID | |||
* @return string info.name 用户名字 | |||
* @return string info.note 用户来源 | |||
* @return string msg 提示信息 | |||
*/ | |||
public function getBaseInfo() { | |||
$rs = array('code' => 0, 'msg' => '', 'info' => array()); | |||
$domain = new Domain_User(); | |||
$info = $domain->getBaseInfo($this->userId); | |||
if (empty($info)) { | |||
DI()->logger->debug('user not found', $this->userId); | |||
$rs['code'] = 1; | |||
$rs['msg'] = T('user not exists'); | |||
return $rs; | |||
} | |||
$rs['info'] = $info; | |||
return $rs; | |||
} | |||
/** | |||
* 批量获取用户基本信息 | |||
* @desc 用于获取多个用户基本信息 | |||
* @return int code 操作码,0表示成功 | |||
* @return array list 用户列表 | |||
* @return int list[].id 用户ID | |||
* @return string list[].name 用户名字 | |||
* @return string list[].note 用户来源 | |||
* @return string msg 提示信息 | |||
* @exception 400 参数传递错误 | |||
* @exception 500 服务器内部错误 | |||
*/ | |||
public function getMultiBaseInfo() { | |||
$rs = array('code' => 0, 'msg' => '', 'list' => array()); | |||
$domain = new Domain_User(); | |||
foreach ($this->userIds as $userId) { | |||
$rs['list'][] = $domain->getBaseInfo($userId); | |||
} | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
<?php | |||
class Domain_User { | |||
public function getBaseInfo($userId) { | |||
$rs = array(); | |||
$userId = intval($userId); | |||
if ($userId <= 0) { | |||
return $rs; | |||
} | |||
// 版本1:简单的获取 | |||
$model = new Model_User(); | |||
$rs = $model->getByUserId($userId); | |||
// 版本2:使用单点缓存/多级缓存 (应该移至Model层中) | |||
/** | |||
$model = new Model_User(); | |||
$rs = $model->getByUserIdWithCache($userId); | |||
*/ | |||
// 版本3:缓存 + 代理 | |||
/** | |||
$query = new PhalApi_ModelQuery(); | |||
$query->id = $userId; | |||
$modelProxy = new ModelProxy_UserBaseInfo(); | |||
$rs = $modelProxy->getData($query); | |||
*/ | |||
return $rs; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
class Model_User extends PhalApi_Model_NotORM { | |||
public function getByUserId($userId) { | |||
return $this->getORM() | |||
->select('*') | |||
->where('id = ?', $userId) | |||
->fetch(); | |||
} | |||
public function getByUserIdWithCache($userId) { | |||
$key = 'userbaseinfo_' . $userId; | |||
$rs = DI()->cache->get($key); | |||
if ($rs === NULL) { | |||
$rs = $this->getByUserId($userId); | |||
DI()->cache->set($key, $rs, 600); | |||
} | |||
return $rs; | |||
} | |||
/** | |||
protected function getTableName($id) { | |||
return 'user'; | |||
} | |||
*/ | |||
} |
@@ -0,0 +1,21 @@ | |||
<?php | |||
/** | |||
* @author dogstar <chanzonghuang@gmail.com> 2015-02-22 | |||
*/ | |||
class ModelProxy_UserBaseInfo extends PhalApi_ModelProxy { | |||
protected function doGetData($query) { | |||
$model = new Model_User(); | |||
return $model->getByUserId($query->id); | |||
} | |||
protected function getKey($query) { | |||
return 'userbaseinfo_' . $query->id; | |||
} | |||
protected function getExpire($query) { | |||
return 600; | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ApiDefault_Test | |||
* | |||
* 针对 ../../Api/Default.php Api_Default 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150201 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Api_Default')) { | |||
require dirname(__FILE__) . '/../../Api/Default.php'; | |||
} | |||
class PhpUnderControl_ApiDefault_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $apiDefault; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->apiDefault = new Api_Default(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetRules | |||
*/ | |||
public function testGetRules() | |||
{ | |||
$rs = $this->apiDefault->getRules(); | |||
$this->assertNotEmpty($rs); | |||
} | |||
public function testIndex() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=Default.Index&username=dogstar'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('title', $rs); | |||
$this->assertArrayHasKey('content', $rs); | |||
$this->assertArrayHasKey('version', $rs); | |||
$this->assertArrayHasKey('time', $rs); | |||
$this->assertEquals('dogstar您好,欢迎使用PhalApi!', $rs['content']); | |||
} | |||
} |
@@ -0,0 +1,84 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ApiUser_Test | |||
* | |||
* 针对 ../../Demo/Api/User.php Api_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150128 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Api_User')) { | |||
require dirname(__FILE__) . '/../../Demo/Api/User.php'; | |||
} | |||
class PhpUnderControl_ApiUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $apiUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->apiUser = new Api_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetRules | |||
*/ | |||
public function testGetRules() | |||
{ | |||
$rs = $this->apiUser->getRules(); | |||
} | |||
/** | |||
* @group testGetBaseInfo | |||
*/ | |||
public function testGetBaseInfo() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=User.GetBaseInfo&user_id=1'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('code', $rs); | |||
$this->assertArrayHasKey('msg', $rs); | |||
$this->assertArrayHasKey('info', $rs); | |||
$this->assertEquals(0, $rs['code']); | |||
$this->assertEquals('dogstar', $rs['info']['name']); | |||
$this->assertEquals('oschina', $rs['info']['note']); | |||
} | |||
public function testGetMultiBaseInfo() | |||
{ | |||
//Step 1. 构建请求URL | |||
$url = 'service=User.GetMultiBaseInfo&user_ids=1,2,3'; | |||
//Step 2. 执行请求 | |||
$rs = PhalApi_Helper_TestRunner::go($url); | |||
//Step 3. 验证 | |||
$this->assertNotEmpty($rs); | |||
$this->assertArrayHasKey('code', $rs); | |||
$this->assertArrayHasKey('msg', $rs); | |||
$this->assertArrayHasKey('list', $rs); | |||
foreach ($rs['list'] as $item) { | |||
$this->assertArrayHasKey('id', $item); | |||
$this->assertArrayHasKey('name', $item); | |||
$this->assertArrayHasKey('note', $item); | |||
} | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_DomainUser_Test | |||
* | |||
* 针对 ./Demo/Domain/User.php Domain_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150208 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Domain_User')) { | |||
require dirname(__FILE__) . '/./Demo/Domain/User.php'; | |||
} | |||
class PhpUnderControl_DomainUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $domainUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->domainUser = new Domain_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetBaseInfo | |||
*/ | |||
public function testGetBaseInfo() | |||
{ | |||
$userId = '1'; | |||
$rs = $this->domainUser->getBaseInfo($userId); | |||
$this->assertArrayHasKey('id', $rs); | |||
$this->assertArrayHasKey('name', $rs); | |||
$this->assertArrayHasKey('note', $rs); | |||
$this->assertEquals('dogstar', $rs['name']); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?php | |||
/** | |||
* PhpUnderControl_ModelUser_Test | |||
* | |||
* 针对 ./Demo/Model/User.php Model_User 类的PHPUnit单元测试 | |||
* | |||
* @author: dogstar 20150208 | |||
*/ | |||
require_once dirname(__FILE__) . '/../test_env.php'; | |||
if (!class_exists('Model_User')) { | |||
require dirname(__FILE__) . '/./Demo/Model/User.php'; | |||
} | |||
class PhpUnderControl_ModelUser_Test extends PHPUnit_Framework_TestCase | |||
{ | |||
public $modelUser; | |||
protected function setUp() | |||
{ | |||
parent::setUp(); | |||
$this->modelUser = new Model_User(); | |||
} | |||
protected function tearDown() | |||
{ | |||
} | |||
/** | |||
* @group testGetByUserId | |||
*/ | |||
public function testGetByUserId() | |||
{ | |||
$userId = '1'; | |||
$rs = $this->modelUser->getByUserId($userId); | |||
$this->assertArrayHasKey('id', $rs); | |||
$this->assertArrayHasKey('name', $rs); | |||
$this->assertArrayHasKey('note', $rs); | |||
$this->assertEquals('dogstar', $rs['name']); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<phpunit backupGlobals="false" | |||
backupStaticAttributes="false" | |||
colors="true" | |||
convertErrorsToExceptions="true" | |||
convertNoticesToExceptions="true" | |||
convertWarningsToExceptions="true" | |||
processIsolation="false" | |||
stopOnFailure="false" | |||
syntaxCheck="false" | |||
> | |||
<php> | |||
<ini name="intl.default_locale" value="en"/> | |||
<ini name="intl.error_level" value="0"/> | |||
<ini name="memory_limit" value="-1"/> | |||
</php> | |||
<testsuites> | |||
<testsuite name="common"> | |||
<directory suffix="Test.php">./Common</directory> | |||
</testsuite> | |||
<testsuite name="api"> | |||
<directory suffix="Test.php">./Api</directory> | |||
</testsuite> | |||
<testsuite name="Domain"> | |||
<directory suffix="Test.php">./Domain</directory> | |||
</testsuite> | |||
<testsuite name="Model"> | |||
<directory suffix="Test.php">./Model</directory> | |||
</testsuite> | |||
</testsuites> | |||
</phpunit> | |||
@@ -0,0 +1,25 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<phpunit backupGlobals="false" | |||
backupStaticAttributes="false" | |||
colors="true" | |||
convertErrorsToExceptions="true" | |||
convertNoticesToExceptions="true" | |||
convertWarningsToExceptions="true" | |||
processIsolation="false" | |||
stopOnFailure="false" | |||
syntaxCheck="false" | |||
> | |||
<php> | |||
<ini name="intl.error_level" value="0"/> | |||
<ini name="memory_limit" value="-1"/> | |||
</php> | |||
<testsuites> | |||
<testsuite name="Test Suite"> | |||
<file>./Api/Api_User_Test.php</file> | |||
<file>./Domain/Domain_User_Test.php</file> | |||
<file>./Model/Model_User_Test.php</file> | |||
</testsuite> | |||
</testsuites> | |||
</phpunit> |
@@ -0,0 +1,16 @@ | |||
<?php | |||
/** | |||
* demo接口测试入口 | |||
* @author dogstar 2015-01-28 | |||
*/ | |||
/** ---------------- 根目录定义,自动加载 ---------------- **/ | |||
require_once dirname(__FILE__) . '/../../Public/init.php'; | |||
DI()->loader->addDirs('Demo'); | |||
//日记纪录 - Explorer | |||
DI()->logger = new PhalApi_Logger_Explorer( | |||
PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR); | |||
@@ -0,0 +1,10 @@ | |||
##协议许可的权利 - GPL协议 | |||
PhalApi官方网站为 http://www.phalapi.net,依法独立拥有 PhalApi 及官网发布的PhalApi衍生产品著作权。 | |||
PhalApi及其衍生产品著作权受到法律和国际公约保护。使用者需仔细阅读本协议,在理解、同意、并遵守本协 | |||
议的全部条款后,方可开始使用 PhalApi及其衍生 软件。 | |||
本授权协议适用于 http://www.phalapi.net 发布的所有应用程序,PhalApi官方网站拥有对本授权协议的最终 | |||
解释权。 | |||
PhalApi是一个PHP轻量级开源接口框架,并承诺永久免费!请放心使用! |
@@ -0,0 +1,6 @@ | |||
<?php | |||
return array( | |||
'Hello {name}, Welcome to use PhalApi!' => 'Hello {name}, Welcome to use PhalApi!', | |||
'user not exists' => 'user not exists', | |||
); |
@@ -0,0 +1,14 @@ | |||
<?php | |||
/** | |||
* 翻译说明: | |||
* | |||
* 1、带大括号的保留原来写法,如:{name},会被系统动态替换 | |||
* 2、没在以下出现的,可以自行追加 | |||
* | |||
* @author dogstar <chanzonghuang@gmail.com> 2015-02-09 | |||
*/ | |||
return array( | |||
'Hi {name}, welcome to use PhalApi!' => '{name}您好,欢迎使用PhalApi!', | |||
'user not exists' => '用户不存在', | |||
); |
@@ -0,0 +1,6 @@ | |||
<?php | |||
return array( | |||
'Hi {name}, welcome to use PhalApi!' => '{name}您好,歡迎使用PhalApi!', | |||
'user not exists' => '用戶不存在', | |||
); |
@@ -0,0 +1,7 @@ | |||
##扩展类库 | |||
请查看: | |||
``` | |||
http://git.oschina.net/dogstar/PhalApi-Library | |||
``` |
@@ -0,0 +1,33 @@ | |||
<?php | |||
return array( | |||
//请将以下配置拷贝到 ./Config/app.php 文件中 | |||
/** | |||
* 计划任务配置 | |||
*/ | |||
'Task' => array( | |||
//MQ队列设置,可根据使用需要配置 | |||
'mq' => array( | |||
'file' => array( | |||
'path' => API_ROOT . '/Runtime', | |||
'prefix' => 'phalapi_task', | |||
), | |||
'redis' => array( | |||
'host' => '127.0.0.1', | |||
'port' => 6379, | |||
'prefix' => 'phalapi_task', | |||
'auth' => '', | |||
), | |||
), | |||
//Runner设置,如果使用远程调度方式,请加此配置 | |||
'runner' => array( | |||
'remote' => array( | |||
'host' => 'http://library.phalapi.net/demo/', | |||
'timeoutMS' => 3000, | |||
), | |||
), | |||
), | |||
); |
@@ -0,0 +1,21 @@ | |||
<?php | |||
return array( | |||
'tables' => array( | |||
//请将以下配置拷贝到 ./Config/dbs.php 文件对应的位置中,未配置的表将使用默认路由 | |||
//10张表,可根据需要,自行调整表前缀、主键名和路由 | |||
'task_mq' => array( | |||
'prefix' => 'phalapi_', | |||
'key' => 'id', | |||
'map' => array( | |||
array('db' => 'db_demo'), | |||
array('start' => 0, 'end' => 9, 'db' => 'db_demo'), | |||
), | |||
), | |||
) | |||
); | |||
@@ -0,0 +1,109 @@ | |||
CREATE TABLE `phalapi_task_mq` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_0` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_1` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_2` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_3` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_4` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_5` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_6` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_7` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_8` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
CREATE TABLE `phalapi_task_mq_9` ( | |||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', | |||
`ext_data` text COMMENT 'json data here', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
@@ -0,0 +1,13 @@ | |||
CREATE TABLE `phalapi_task_progress` ( | |||
`id` bigint(20) NOT NULL AUTO_INCREMENT, | |||
`title` varchar(200) DEFAULT '' COMMENT '任务标题', | |||
`trigger_class` varchar(50) DEFAULT '' COMMENT '触发器类名', | |||
`fire_params` varchar(255) DEFAULT '' COMMENT '需要传递的参数,格式自定', | |||
`interval_time` int(11) DEFAULT '0' COMMENT '执行间隔,单位:秒', | |||
`enable` tinyint(1) DEFAULT '1' COMMENT '是否启动,1启动,0禁止', | |||
`result` varchar(255) DEFAULT '' COMMENT '运行的结果,以json格式保存', | |||
`state` tinyint(1) DEFAULT '0' COMMENT '进程状态,0空闲,1运行中,-1异常退出', | |||
`last_fire_time` int(11) DEFAULT '0' COMMENT '上一次运行时间', | |||
PRIMARY KEY (`id`) | |||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||
@@ -0,0 +1,3 @@ | |||
`service` varchar(200) DEFAULT '' COMMENT '接口服务名称', | |||
`params` text COMMENT 'json格式的参数', | |||
`create_time` int(11) DEFAULT '0', |