@@ -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', |