Commit 54810809 authored by wanjilong's avatar wanjilong

add: 项目初始化

parent 04b2ff49
<?php
use Yaf\Bootstrap_Abstract;
use Yaf\Dispatcher;
use App\Plugins\Hook;
use Yaf\Registry;
class Bootstrap extends Bootstrap_Abstract {
/**
* 项目基本初始化操作.
*
* @param Dispatcher $dispatcher
*/
public function _initProject(Dispatcher $dispatcher)
{
date_default_timezone_set('PRC');
//是否返回Response对象, 如果启用, 则Response对象在分发完成以后不会自动输出给请求端, 而是交给程序员自己控制输出.
$dispatcher->returnResponse(true);
$dispatcher->disableView();
}
/**
* autoload.
*
* @param Dispatcher $dispatcher
*/
public function _initLoader(Dispatcher $dispatcher)
{
$loader = Yaf\Loader::getInstance();
$loader->import(ROOT_PATH.'/vendor/autoload.php');
$loader->import(APP_PATH.'/library/helper.php');
}
public function _initConfig() {
//把配置保存起来
$arrConfig = Yaf\Application::app()->getConfig();
Registry::set('config', $arrConfig);
}
public function _initPlugin(Dispatcher $dispatcher) {
//注册一个插件
$objSamplePlugin = new Hook();
$dispatcher->registerPlugin($objSamplePlugin);
}
public function _initRoute(Dispatcher $dispatcher) {
//在这里注册自己的路由协议,默认使用简单路由
}
}
\ No newline at end of file
<?php
class Bootstrap extends Yaf\Bootstrap_Abstract{
/**
* 初始化配置文件
* 全局配置文件 ,环境配置文件 错误码配置文件等
*/
public function _initConfig() {
$globalConfig = Yaf\Application::app()->getConfig();
Yaf\Registry::set('cliConfig', $globalConfig);
}
/**
* 禁用视图
*/
public function _initView(\Yaf\Dispatcher $dispatcher) {
$dispatcher->disableView();
}
}
<?php
use Yaf\Controller_Abstract;
/**
* 每个项目按需定义异常处理,记录日志等,确定的异常请在自定义异常处理,详细在exception目录中查看
*/
class ErrorController extends Controller_Abstract
{
use \Helpers\ApiResponse;
public function errorAction($exception)
{
if (\Yaf\Application::app()->environ() == 'dev') {
// var_dump($exception);
}
if ($exception->getPrevious() !== NULL) {
$exception = $exception->getPrevious();
}
switch ($exception->getCode()) {
// 404
case YAF\ERR\NOTFOUND\MODULE:
case YAF\ERR\NOTFOUND\CONTROLLER:
case YAF\ERR\NOTFOUND\ACTION:
case YAF\ERR\NOTFOUND\VIEW:
// todo 各项目自定义
// log
// LogUtil::ERROR('error code'.$exc->getCode(), '', $exc);
$this->failed(10, 'failed', 'reason');
return false;
break;
default:
// todo 各项目自定义
// log
$reason = '服务器忙, 请稍后再试[' . $exception->getCode() . ']';
$this->failed($exception->getCode(), 'failed', $reason);
return false;
}
}
}
<?php
use Yaf\Controller_Abstract;
/**
* 不要删除默认的控制器,deploy等服务会调用此/indix/index接口,判断项目是否可用
*/
class IndexController extends Controller_Abstract
{
use \Helpers\ApiResponse;
public function IndexAction() {
$this->success();
}
}
<?php
namespace App\Exception;
use Helpers\ApiResponse;
use Yaf\Registry;
/**
* Class BaseException
* 自定义异常类的基类
*/
class BaseException extends \Exception
{
use ApiResponse;
public $msg;
public $code;
/**
* 构造函数,接收一个关联数组
* @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
*/
public function __construct($params = [])
{
if (!is_array($params)) {
return;
}
$this->code = $params['code'] ?? Registry::get('config')->exception->user->code;
$this->msg = $params['msg'] ?? Registry::get('config')->exception->user->msg;
if (isset($params['cus']) && $this->cus && isset($this->cus[intval($params['cus'])]) && $this->base_code) {
$cus_code = intval($params['cus']);
$base_code = intval($this->base_code);
$this->code = $base_code + $cus_code;
$this->msg = $this->cus[$cus_code];
}
}
public function __get($name): bool
{
return false;
}
}
<?php
namespace App\Exception;
/*
* 重写Handle的render方法,实现自定义异常消息
*/
use Helpers\ApiResponse;
use Yaf\Registry;
class ErrorHandler
{
use ApiResponse;
private $http_code;
private $msg;
private $code;
public function render($errno, $errstr, $errfile, $errline)
{
$msg = ' file_name : '.$errfile . '<br> line_num : '.$errline . '<br> message : ' . $errstr;
if(_IS_DEBUG){
echo $msg;
exit;
}
$this->msg = appConfig('exception.sys.msg');
$this->code = appConfig('exception.sys.code');
$this->recordErrorLog($msg);
$this->failed($this->code, $this->msg);
}
/*
* 将异常写入日志
*/
private function recordErrorLog($msg)
{
// LogUtil::error('Error handler', $msg);
}
}
\ No newline at end of file
<?php
namespace App\Exception;
class ExceptionErrorCatch
{
public static function register()
{
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
set_exception_handler([__CLASS__, 'appException']);
set_error_handler([__CLASS__, 'appError'], E_ALL & ~E_DEPRECATED);
}
public static function appException(\Throwable $e)
{
$handler = new ExceptionHandler();
$handler->render($e);
exit;
}
public static function appError($errno, $errstr, $errfile, $errline)
{
$handler = new ErrorHandler();
$handler->render($errno, $errstr, $errfile, $errline);
exit;
}
}
\ No newline at end of file
<?php
namespace App\Exception;
/*
* 重写Handle的render方法,实现自定义异常消息
*/
use Helpers\ApiResponse;
use Yaf\Registry;
class ExceptionHandler
{
use ApiResponse;
private $msg;
private $code;
public function render(\Throwable $e)
{
if ($e instanceof BaseException)
{
// 自定义异常
$this->code = $e->code;
$this->msg = $e->msg;
}
else{
// 服务器未处理异常
if(_IS_DEBUG){
$message = $e->getMessage();
$file_name = $e->getFile();
$line_num = $e->getLine();
echo ' file_name : '.$file_name . '<br> line_num : '.$line_num . '<br> message : ' . $message;
exit;
}
$this->msg = appConfig('exception.sys.msg');
$this->code = appConfig('exception.sys.code');
$this->recordErrorLog($e);
}
$this->failed($this->code, $this->msg);
}
/*
* 将异常写入日志
*/
private function recordErrorLog($e)
{
if($e instanceof \ErrorException || $e instanceof \Exception){
$message = $e->getMessage();
$file_name = $e->getFile();
$line_num = $e->getLine();
$msg = ' file_name : '.$file_name . ' line_num : '.$line_num . ' message : ' . $message;
// LogUtil::error('exception handler', $msg);
}
if(is_string($e) || is_int($e)){
// LogUtil::error('exception handler', $e);
}
}
}
\ No newline at end of file
<?php
namespace App\Exception\custom;
/**
* 异常code规则:前3位是大类,后三位是细分
* 比如 参数异常、验签异常、用户异常 三大类,分别是 101000、102000、103000
* 用户异常又细分,比如未登录103001、密码错误103002
*/
class Code
{
const PAY = 101000;
const REFUND = 102000;
}
\ No newline at end of file
<?php
namespace App\Exception\custom;
use App\Exception\BaseException;
class PayException extends BaseException
{
protected $base_code = Code::PAY;
protected $cus = [
0 => '用户已通过个人认证,无需重复认证',
1 => '企业已通过认证,无需重复认证'
];
}
<?php
namespace Enum;
class Second
{
const SECOND = 1; // 1秒
const ONE_MINUTE = 60; // 1分钟
const ONE_HOUR = 3600; // 1小时
const ONE_DAT = 86400; // 1天
const THREE_DAT = 259200; // 3天
const SEVEN_DAT = 604800; // 7天
const THIRTY_DAT = 2592000; // 30天
}
\ No newline at end of file
<?php
namespace Helpers;
/**
* AES 加密 解密类库
*/
class Aes {
/**
* 加密
* @param String content 加密的字符串
* @return string|string[]
*/
public static function encrypt($content = '') {
$key = appConfig('aes.key');
$iv = appConfig('aes.iv');
$data = openssl_encrypt($content, "AES-128-CBC", $key, 0, $iv);
return self::urlsafeEncrypt($data);
}
/**
* 解密
* @param String content 解密的字符串
* @return String
*/
public static function decrypt($content) {
$content = self::urlsafeDecrypt($content);
$key = appConfig('aes.key');
$iv = appConfig('aes.iv');
return openssl_decrypt($content, "AES-128-CBC", $key, 0, $iv);
}
public static function urlsafeEncrypt($string) {
return str_replace(array('+','/','='), array('-','_',''), $string);
}
public static function urlsafeDecrypt($string) {
$string = str_replace(array('-','_'), array('+','/'), $string);
$mod4 = strlen($string) % 4;
if ($mod4) {
$string .= substr('====', $mod4);
}
return $string;
}
// openssl AES 向量长度固定 16 位 这里为兼容建议固定长度为 16 位
// 随机字符串
public static function getRandomStr($length = 16) {
$char_set = array_merge(range('a', 'z'), range('A', 'Z'), range('0', '9'));
shuffle($char_set);
return implode('', array_slice($char_set, 0, $length));
}
/**
* 生成每次请求的sign
* @param array $data
* @return string
*/
public static function createSign($data = []) {
// 1 按字段排序
ksort($data);
// 2拼接字符串数据 &
$string = http_build_query($data);
// 3通过aes来加密
$string = self::encrypt($string);
return $string;
}
/**
* 检查sign是否正常
* @param array $data
* @param $data
* @return bool
*/
public static function checkSign($data) {
if(!isset($data['sign'])
|| empty($data['sign'])
|| !isset($data['reqid'])
|| !isset($data['appid'])
|| !isset($data['platform'])
) {
return false;
}
$str = self::decrypt($data['sign']);
if(empty($str)) {
return false;
}
// appid=xx&version=023300&....
parse_str($str, $arr);
if(!is_array($arr)
|| !isset($arr['reqid'])
|| !isset($arr['appid'])
|| !isset($arr['platform'])
|| $arr['reqid'] != $data['reqid']
|| $arr['appid'] != $data['appid']
|| $arr['platform'] != $data['platform']
) {
return false;
}
$timeout = appConfig('aes.timeout');
$switch = appConfig('aes.switch');
if($switch) {
if ((time() - ceil($arr['ts'] / 1000)) > $timeout) {
return false;
}
}
return true;
}
}
\ No newline at end of file
<?php
namespace Helpers;
trait ApiResponse
{
/**
* 成功返回格式
*
* @param array $data
* @param string $status
* @param array $headers
* $headers['content-type'] = 'application/json'
* @return void
* @throws \Exception
*/
public function success($data = [], $status = "success", $headers = [])
{
$this->respond(0, $status, '', $data, $headers);
}
/**
* 失败返回格式,有失败原因
*
* @param [type] $code
* @param string $reason
* @param array $headers
* @return void
* @throws \Exception
*/
public function failed($code, $reason = '', $status = "failed", $headers = [])
{
$this->respond($code, $status, $reason, [], $headers);
}
public function respond($code, $status, $reason, array $data = [], $headers = [])
{
$resp = [
'code' => $code,
'status' => $status
];
if ($reason) {
$resp['reason'] = $reason;
}
if ($data && ! is_array($data)) {
$data = json_decode(strval($data), true);
if ($data === NULL) {
throw new \Exception('非json格式', 13);
}
}
$response = \Yaf\Dispatcher::getInstance()->getResponse();
$response->setHeader('content-type', 'application/json');
if ($data) {
$apiHeader = "";
if (isset($data['code'])) {
$apiHeader = $apiHeader . strval($data['code']);
}
if (isset($_SESSION['userid'])) {
$apiHeader = $apiHeader . "_" . strval($_SESSION['userid']);
}
if (strlen($apiHeader) > 0) {
$response->setHeader('Api-Result', $apiHeader);
}
}
// headder中输出主要依赖服务的处理时间
if (isset($GLOBALS['DEPENDENT-REQUEST-TIME'])) {
$response->setHeader('Dependent-Request-Time', $GLOBALS['DEPENDENT-REQUEST-TIME']);
}
if (isset($GLOBALS['DEPENDENT-STATUS'])) {
$response->setHeader('Dependent-Status', $GLOBALS['DEPENDENT-STATUS']);
}
if (isset($GLOBALS['DEPENDENT-URI'])) {
$response->setHeader('Actual-Request-Url', $GLOBALS['DEPENDENT-URI']);
}
if ($headers) {
foreach ($headers as $name => $value) {
$response->setHeader($name, $value);
}
}
$data = array_merge($resp, $data);
$response->setBody(json_encode($data, JSON_UNESCAPED_UNICODE));
$response->response();
if (function_exists('fastcgi_finish_request')) {
ignore_user_abort(true);
fastcgi_finish_request();
}
}
}
\ No newline at end of file
This diff is collapsed.
<?php
namespace Validate;
use Api\PhpUtils\Validate\Validate;
use App\Exception\custom\Code;
use App\Exception\custom\ParamException;
use Yaf\Dispatcher;
class BaseValidate extends Validate
{
/**
* 参数校验
* @return array | boolean
* @throws
*/
public function validate()
{
$params = Dispatcher::getInstance()->getRequest()->getRequest();
$result = $this->batch()->check($params);
if (!$result) {
$msg = $this->getError() ? array_shift($this->error) : "参数错误";
throw new ParamException([
'msg' => $msg,
"code" => Code::PARAM
]);
} else {
return true;
}
}
protected function isPositiveInteger($value)
{
if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0) {
return true;
} else {
return false;
}
}
protected function isMobile($value)
{
$rule = '^1(3|4|5|7|8)[0-9]\d{8}$^';
$result = preg_match($rule, $value);
if ($result) {
return true;
} else {
return false;
}
}
protected function idcard($value){
$weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
$codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
if(strlen($value)!=18){
return false;
}
$validate = substr($value, 0, 17);
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += $validate[$i] * $weight[$i];
}
return $codes[$sum % 11] === substr($value, 17, 1);
}
}
\ No newline at end of file
<?php
namespace Validate;
class TestValidate extends BaseValidate
{
/**
* @var array
* 基础规则
* 可以自定义方法,比如 checkIDs
* 可以使用系统已定义的验证规则,在 Validate 基类的 $typeMsg 中查看
*/
protected $rule = [
'ids' => 'checkIDs',
'email' => 'email',
'age' => 'between:0,100',
];
/**
* 自定义某一规则不符合后,输出给用户的提示语
* @var string[]
*/
protected $message = [
"ids.require" => "ids 参数必填",
"ids.checkIDs" => "ids 格式有误",
"email.email" => "邮箱格式有误",
];
/**
* 场景定义
* edit 场景仅需要验证 email 与 age,并且不需要增加或删除验证条件
* @var \string[][]
*/
protected $scene = [
'edit' => ['email','age'],
];
/**
* 场景定义2
* 定义一个方法,scene 做前缀,驼峰的加上场景名
* only 定义需要验证的参数
* append 在 rule 定义的条件基础上,再增加其他验证条件
* remove 删除在 rule 中定义的某条件
* @return TestValidate
*/
public function sceneAdd()
{
return $this->only(['ids','email','age'])
->append('ids', 'require')
->append('email', 'require');
}
protected function checkIDs($params)
{
//id字符串转为id数组
$params = explode(',', $params);
if (empty($params)) {
return false;
}
//每个id只能由字母数字组成
foreach ($params as $param) {
if (!$this->regex($param, '/^[A-Za-z0-9]+$/')) {
return false;
}
}
return true;
}
}
\ No newline at end of file
<?php
namespace Validate;
class UserPhoneValidate extends BaseValidate
{
protected $rule = [
'user_id' => 'require',
'mobile' => 'require|isMobile'
];
protected $message = [
"user_id" => "用户信息获取失败",
"mobile" => "手机号格式错误"
];
}
\ No newline at end of file
<?php
namespace Validate;
class UseridValidate extends BaseValidate
{
protected $rule = [
'user_id' => 'require'
];
protected $message = [
"user_id" => "用户信息获取失败"
];
}
\ No newline at end of file
<?php
use Yaf\Application;
use Yaf\Dispatcher;
if (!function_exists('config')) {
/**
* 假设当前环境为 dev(在php.ini中配置)
* 当前 appid 为 ProgramA (在conf/application.ini中配置)
* 则 config("test", "a"); 将取到 yaconf/test.ini 中, [dev-ProgramA] 下定义的配置 a 的值
*
* @param $file
* @param string $param
* @return string
*/
function config($file, $param = ''){
if (empty($file) || !file_exists(ROOT_PATH."/yaconf/".$file.".ini")){
return "";
}
$env = Application::app()->environ() ?? "test";
$appid = Application::app()->getConfig()->get("appid");
$key = $file.'.'. (empty($appid) ? $env : $env.'-'.$appid);
$key = $param ==='' ? $key : $key.".".$param;
return \Yaconf::get($key);
}
if (!function_exists('appConfig')) {
/**
* 获取框架的 conf/application 中的配置
* @param $param
* @return mixed
*/
function appConfig($param){
return Application::app()->getConfig()->get($param);
}
}
if (!function_exists('getHeader')) {
function getHeader($name = null){
if($name){
return Dispatcher::getInstance()->getRequest()->getServer(strtoupper('HTTP_'.$name));
}
return Dispatcher::getInstance()->getRequest()->getServer();
}
}
if (!function_exists('page')) {
function page($param){
$page_start = 0;
$page_size = 20;
if(isset($param['page_size']) && $param['page_size']>0){
$page_size = intval($param['page_size']);
}
if (isset($param['page']) && $param['page']>0){
$page_start = (intval($param['page']) - 1) * $page_size;
}
return [
'start' => $page_start,
'size' => $page_size
];
}
}
if (!function_exists('filterArrByField')) {
/**
* 过滤数组,只留 $field 中的字段
* @param $array array
* @param $field array
* @return array
*/
function filterArrayByField(array $array, array $field, $recursive = true){
if(empty($field) || empty($array)){
return $array;
}
foreach ( $array as $key => $val ) {
if( $recursive && is_array($val)){
$array[$key] = filterArrayByField($val, $field);
} elseif(!in_array($key."", $field)){
unset($array[$key]);
}
}
return $array;
}
}
if (!function_exists('arrayGroupBy')) {
/**
* 二维数组转三维数组(指定键为三维数组的键名)
*
* @param [type] $arr [要排序的数组]
* @param [type] $key [指定的键]
* @return [type] $grouped [重排的数组]
*/
function arrayGroupBy($arr, $key)
{
$grouped = [];
foreach ($arr as $value) {
$grouped[$value[$key]][] = $value;
}
if (func_num_args() > 2) {
$args = func_get_args();
foreach ($grouped as $key => $value) {
$parms = array_merge([$value], array_slice($args, 2, func_num_args()));
$grouped[$key] = call_user_func_array('array_group_by', $parms);
}
}
return $grouped;
}
}
}
\ No newline at end of file
## library
#### 全局的处理函数请在heapler.php中编写
#### 验证器,工具类,其他类库请新建目录,指定命名空间,细节参考已有的类库文件
<?php
namespace App\Models;
/**
* Class Dictionary
* @package App\Models
* 项目通用字典及文案
*/
class Dictionary
{
public const O_PAY_STATUS_UNPAY = 0; //未支付
public const O_PAY_STATUS_WAIT = 1; //待确认
public const O_PAY_STATUS_PAYED = 2; //已支付
public const YES = 1; //是
public const NO = 0; //否
public const CHANNEL_WX = 1; //wx
public const CHANNEL_WX_PUB = 2; //wx_pub
public const CHANNEL_WX_LITE = 3; //wx_lite
public const CHANNEL_WX_ALIPAY = 10; //alipay
public const SOURCE_LIFE = 1; //生活圈
public const SOURCE_MAIN = 2; //主端
}
<?php
namespace App\Models\demo\mongo;
use Api\PhpUtils\Mongo\MongoBase;
class Test extends MongoBase
{
protected function getConfigIndex()
{
return "demo";
}
protected function getDatabaseName()
{
return "demo";
}
protected function getCollectionName()
{
return "user";
}
protected function getWhere($params)
{
return $params;
}
protected function getQueryOptions($fields = [], $sort = [], $limit = [])
{
$options = [
'maxTimeMS' => 800,
'limit' => 100
];
if (is_array($fields) && !empty($fields)) {
$options['projection'] = $fields;
}
if (is_array($sort) && !empty($sort)) {
$options['sort'] = $sort;
}
if (is_array($limit)) {
if (isset($limit['start'])) {
$options['skip'] = intval($limit['start']);
}
if (isset($limit['count'])) {
$options['limit'] = intval($limit['count']);
}
}
return $options;
}
}
<?php
namespace App\Models\demo\mongo;
use Api\PhpUtils\Mongo\Base;
class User extends Base
{
protected static $instance;
protected static $db_config_index = 'metro';
protected function getCollectionName()
{
return 'user';
}
protected function getWhere($params)
{
$where = [];
if (isset($params['name']) && !empty($params['name'])) {
$where['name'] = $params['name'];
}
return $where;
}
protected function getQueryOptions()
{
$options = [
'projection' => [
'mobile' => 1
],
'maxTimeMS' => 800,
'limit' => 5,
'sort' => ['mobile' => -1]
];
return $options;
}
}
<?php
namespace App\Models\demo\mysql;
use Api\PhpUtils\Mysql\MysqlBase2;
class TestMysql extends MysqlBase2
{
const TABLE_NAME = 'test';
const CONFIG_INDEX = 'merchant';
const LIFE_ACCOUNT_TYPE_PERSIONAL = 1; // 个人
const LIFE_ACCOUNT_TYPE_ENTERPRISE = 2; // 企业
const LIFE_ACCOUNT_STATUS_ON = 1; // 上线
const LIFE_ACCOUNT_STATUS_OFF = 2; // 下线
const LIFE_ACCOUNT_STATUS_UPGRADE = 3; // 升级中
const LIFE_ACCOUNT_AUTH_STATUS_NO = 1; // 未认证生活号
const LIFE_ACCOUNT_AUTH_STATUS_YES = 2; // 已认证生活号
const ENTERPRISE_AUTH_STATUS_ING = 1; // 升级审核中
const ENTERPRISE_AUTH_STATUS_FAIL = 2; // 升级失败
public static function getRecord($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::get($colums, $where);
}
public static function getRecordMaster($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::selectMaster($colums, $where);
}
public static function insertRecord($colums)
{
return self::insert($colums);
}
public static function updateRecord($colums, $where)
{
return self::update($colums, $where);
}
public static function save($data, $where = [])
{
if (empty($where)) {
return self::insert($data);
}
return self::update($data, $where);
}
public static function deleteRecord($where)
{
return self::delete($where);
}
public static function getAccountList($data, $colums = [])
{
$colums = " * ";
$where = " 1=1 ";
if (!empty($data['life_account_name'])) {
$where .= " and (`life_account_name` LIKE '%{$data['life_account_name']}%') ";
}
if (!empty($data['life_account_type'])) {
$where .= " and life_account_type = '{$data['life_account_type']}'";
}
if (!empty($data['ORDER'])) {
$where .= " ORDER BY `create_time` DESC ";
}
if (!empty($data['LIMIT'])) {
$where .= " LIMIT {$data['LIMIT'][1]} OFFSET {$data['LIMIT'][0]} ";
}
return $data = self::query("SELECT {$colums} FROM `life_account` WHERE $where ")->fetchAll();
}
public static function getAccountCount($data, $colums = [])
{
$colums = " * ";
$where = " 1=1 ";
if (!empty($data['life_account_name'])) {
$where .= " and (`life_account_name` LIKE '%{$data['life_account_name']}%') ";
}
if (!empty($data['life_account_type'])) {
$where .= " and life_account_type = '{$data['life_account_type']}'";
}
$data = self::query("SELECT COUNT(*) as count FROM `life_account` WHERE $where ")->fetch();
return !empty($data['count']) ? $data['count'] : 0;
}
public static function getRecords($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::select($colums, $where);
}
public static function getCount($where)
{
return self::count($where);
}
public static function duplicate($data, $duplicate)
{
return self::insertDuplicate($data, $duplicate);
}
public static function forupdate($columns, $where)
{
return self::selectForUpdate($columns, $where);
}
}
<?php
namespace App\Models\demo\mysql;
use Api\PhpUtils\Mysql\Base;
class User extends Base
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'user';
}
protected function getPKey()
{
return 'id';
}
protected function getWhere($params)
{
$where = [];
if (isset($params['ids']) && !empty($params['ids'])) {
$where['id'] = $params['ids'];
}
if (isset($params['name']) && !empty($params['name'])) {
$where['name'] = $params['name'];
}
if (isset($params['id[>]']) && !empty($params['id[>]'])) {
$where['id[>]'] = $params['id[>]'];
}
return $where;
}
}
<?php
namespace App\Models\order\mysql;
use Api\PhpUtils\Mysql\MysqlBase;
class PayOrder extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order';
}
protected function getPKey()
{
return 'pay_order_id';
}
public function selectForUpdate($id) {
$link = self::getConnection('write');
$link->pdo->
}
}
<?php
namespace App\Models\order\mysql;
use Api\PhpUtils\Mysql\Base;
class PayOrderClearing extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order_clearing';
}
protected function getPKey()
{
return 'pay_order_clearing_id';
}
}
<?php
namespace App\Models\order\mysql;
use Api\PhpUtils\Mysql\Base;
class PayOrderClearingItem extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order_clearing_item';
}
protected function getPKey()
{
return 'pay_order_clearing_item_id';
}
}
<?php
namespace App\Models\order\mysql;
use Api\PhpUtils\Mysql\Base;
class RefundOrder extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'refund_order';
}
protected function getPKey()
{
return 'refund_order_id';
}
}
## Models
#### 已有的demo请在开发时删除
<?php
namespace App\Base;
use Helpers\ApiResponse;
use Yaf\Controller_Abstract;
abstract class Base extends Controller_Abstract
{
use ApiResponse;
/**
* 前置操作方法列表
*
* protected $beforeActionList = [
* 'first', //在所有方法前执行
* 'second' => ['except'=>'hello'], //在除了hello以外的其它方法之前执行
* 'three' => ['only'=>'hello,data'] //只在hello,data方法前执行
* ];
*
* @var array $beforeActionList
* @access protected
*/
protected $beforeActionList = [];
/**
* @var mixed
*/
protected $params;
public function init(){
$this->setParam();
// 前置操作方法
if (!empty($this->beforeActionList)) {
foreach ($this->beforeActionList as $method => $options) {
is_numeric($method) ? $this->beforeAction($options) : $this->beforeAction($method, $options);
}
}
}
/**
* 前置操作
* @access protected
* @param string $method 前置操作方法名
* @param array $options 调用参数 ['only'=>[...]] 或者['except'=>[...]]
*/
private function beforeAction($method, $options = [])
{
$action = $this->getRequest()->getActionName();
if (isset($options['only'])) {
if (is_string($options['only'])) {
$options['only'] = explode(',', $options['only']);
}
if (!in_array($action, $options['only'])) {
return;
}
} elseif (isset($options['except'])) {
if (is_string($options['except'])) {
$options['except'] = explode(',', $options['except']);
}
if (in_array($action, $options['except'])) {
return;
}
}
call_user_func([$this, $method]);
}
private function setParam(){
$params = $this->getRequest()->getRequest();
unset($params['s']);
$this->params = $params;
}
}
<?php
namespace App\Base;
use Yaf\Controller_Abstract;
class Cli extends Controller_Abstract
{
public function init() {
\Yaf\Dispatcher::getInstance()->disableView();
}
}
\ No newline at end of file
<?php
use Api\PhpServices\Daemon\Daemon;
use App\Base\Cli;
use Yaf\Application;
/**
* 守护进程入口脚本
* conf/cli.ini 中配置脚本目录,默认在 /daemon
* 脚本必须继承 DaemonServiceInterface,参考 daemon/Test.php
* 以守护进程方式执行 Test 脚本命令参考:php public/cli.php daemon run "t=Test&n=2&j=abc"
* t : 脚本类名
* n : 进程数
* j : 进程别名,默认为脚本类名
*/
class DaemonController extends Cli
{
public function RunAction(){
$request = $this->getRequest();
$params = $request->getParams();
$task_name = $params['t'] ?? "";
$worker_num = $params['n'] ?? 4;
$rename = $params['j'] ?? $task_name;
if(empty($task_name)){
echo <<<EOD
usage: php cli.php daemon run "t=[string]&n=[int|default:4]&j=[string]"
t daemo 脚本类名
n 进程数
j 进程别名,默认同脚本类名
stop : kill -SIGUSR1 master进程id\n
EOD;
return;
}
$script_dir = Application::app()->getConfig()->get("daemon.script_dir");
$task_class = $script_dir.$task_name;
if(!class_exists($task_class)){
die("脚本不存在!");
}
$check = new ReflectionClass($task_class);
if(!$check->implementsInterface('Api\PhpServices\Daemon\DaemonServiceInterface')){
die("脚本需实现 DaemonServiceInterface 接口!");
}
(new Daemon($rename, $task_class, $worker_num))->start();
}
}
\ No newline at end of file
<?php
use App\Base\Cli;
class TestController extends Cli
{
public function IndexAction() {
$request = $this->getRequest();
$params = $request->getParams();
$res = [
"data" => $params,
"code" => 0
];
$response = $this->getResponse();
$response->setBody(json_encode($res));
}
}
\ No newline at end of file
This diff is collapsed.
<?php
use App\Base\Base;
use App\Exception\custom\LifeAccountException;
use App\Models\auth\mysql\LifeAccount;
use App\Models\auth\mysql\Merchant;
use App\Services\lifeaccount\LifeAccountService;
use Validate\RecruitValidate;
use App\Models\auth\mysql\RecruitAccount;
use App\Exception\custom\DataException;
use App\Models\auth\mysql\EnterpriseAuthRecord;
use Api\PhpServices\JwUser\JwUser;
class RecruitController extends Base
{
/**
* 创建招聘个人生活号
*/
public function create_recruitAction(){
// 验证参数
(new RecruitValidate())->validate();
$params = $this->params;
$uid = $params['ownerId'];
$name = $params['name'];
if(!isset($uid) || !isset($name)){
//添加招聘表数据
$params['lifeAccountId'] = -1; //uid、name为空 不具备创建生活号的条件
$recruit_id = RecruitAccount::insert($params);
if (!$recruit_id) {
throw new DataException(['cus' => 1]);
}
$this->success(['result'=>['life_account_id' => -1]]);
}
// 查询是否有创建资格
if(!LifeAccountService::permission($uid)['personal']){
throw new LifeAccountException(['cus'=>3]);
}
try {
RecruitAccount::beginTransaction();
//创建未认证的生活号
$life_account_id = LifeAccountService::unauth_account($uid, $name, 0, 'merchant-c');
if (!$life_account_id) {
throw new DataException(['cus' => 1]);
}
//添加招聘表数据
$recruit_id = RecruitAccount::insert($params);
if (!$recruit_id) {
throw new DataException(['cus' => 1]);
}
RecruitAccount::commit();
} catch (\Exception $exception) {
RecruitAccount::rollback();
throw $exception;
}
$this->success(['result'=>['life_account_id' => $life_account_id]]);
}
/**
* 更新招聘个人生活号
*/
public function update_recruitAction(){
// 验证参数
(new RecruitValidate())->scene('ent')->validate();
$params = $this->params;
$uid = $params['ownerId'];
$res = RecruitAccount::update($params, ['ownerId' => $uid]);
if ($res === false) {
throw new DataException(['cus' => 1]);
}
$this->success();
}
/**
* 查看招聘个人生活号
*/
public function get_recruitAction(){
// 验证参数
(new RecruitValidate())->scene('ent')->validate();
$params = $this->params;
$uid = $params['ownerId'];
$recruit_ret = RecruitAccount::get('*', ['ownerId' => $uid]);
if (empty($recruit_ret)) {
throw new DataException(['cus' => 0]);
}
foreach($recruit_ret as $key => $val){
if($val === 'NULL'){
unset($recruit_ret[$key]);
}
}
$this->success(['result'=>$recruit_ret]);
}
/**
* 检测未绑定招聘个人生活号,并创建个人未认证生活号 并绑定
*/
public function check_recruitAction(){
$recruit_ret = RecruitAccount::select('*', ['lifeAccountId ' => 0]);
if (empty($recruit_ret)) {
throw new DataException(['cus' => 0]);
}
foreach($recruit_ret as $key => $val){
//获取简网用户信息
$jwUser = new JwUser();
$user_info = $jwUser->getUserByUserId(['user_id' => $val['ownerId']]);
$avatar = $user_info['data']['avatar'] ?? 'http://qn.jwshq.cn/profile_unknown_2019_1';
// 查询是否有创建资格
if(!LifeAccountService::permission($val['ownerId'])['personal']){
throw new LifeAccountException(['cus'=>3]);
}
try {
RecruitAccount::beginTransaction();
//查询是否有重复的生活号名称,有重复的加一个随机数
$lifeInfo = LifeAccount::getRecord(['life_account_name' => $val['name']]);
if(!empty($lifeInfo)){
$rand_num = mt_rand(0,99);
$val['name'] = $val['name'].$rand_num;
}
//创建未认证的生活号
$life_account_id = LifeAccountService::unauth_account($val['ownerId'], $val['name'], 0,'batch', $avatar);
if (!$life_account_id) {
throw new DataException(['cus' => 1]);
}
//更新招聘表数据生活号ID
$res = RecruitAccount::update(['lifeAccountId' => $life_account_id], ['ownerId' => $val['ownerId']]);
if ($res === false) {
throw new DataException(['cus' => 1]);
}
RecruitAccount::commit();
} catch (\Exception $exception) {
RecruitAccount::rollback();
throw $exception;
}
sleep(1);
}
$this->success(['result'=>['life_account_id' => $life_account_id]]);
}
}
\ No newline at end of file
<?php
use App\Base\Base;
use App\Services\demo\MongoService;
class MongoController extends Base
{
public function addAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->addUser();
var_dump($ret);
exit;
}
public function addManyAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->addManyUser();
var_dump($ret);
exit;
}
public function deleteAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->deleteUser();
var_dump($ret);
exit;
}
public function updateAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->updateUser();
var_dump($ret);
exit;
}
public function getAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->getUser();
var_dump($ret);
exit;
}
public function getManyAction()
{
$mongo_service = new MongoService();
$ret = $mongo_service->getManyUser();
var_dump($ret);
exit;
}
}
<?php
use App\Base\Base;
use App\Services\demo\MysqlService;
class MysqlController extends Base
{
public function addAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->addUser();
var_dump($ret);
exit;
}
public function addManyAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->addManyUser();
var_dump($ret);
exit;
}
public function deleteAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->deleteUser();
var_dump($ret);
exit;
}
public function updateAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->updateUser();
var_dump($ret);
exit;
}
public function getAction()
{
$mysql_service = new MysqlService();
$ret = $mysql_service->getUser();
var_dump($ret);
exit;
}
public function getManyAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->getManyUser();
var_dump($ret);
exit;
}
public function countAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->countUser();
var_dump($ret);
exit;
}
public function maxAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->maxUser();
var_dump($ret);
exit;
}
public function minAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->minUser();
var_dump($ret);
exit;
}
public function avgAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->avgUser();
var_dump($ret);
exit;
}
public function sumAction(){
$mysql_service = new MysqlService();
$ret = $mysql_service->sumUser();
var_dump($ret);
exit;
}
}
<?php
use App\Base\Base;
use Api\PhpUtils\Http\Request;
class RequestController extends Base
{
public function GetAction()
{
$url = 'http://10.103.17.132:8007/adserver/goodsAds';
$options = [
'query' => [
'docIdList' => '0SQ0d3dH',
'appId' => 'pro',
'platform' => 0
],
'timeout' => 0.5 //自定义超时秒数,覆盖默认值
];
$request = new Request();
$ret = $request->get($url, $options);
var_dump($ret);
exit;
}
public function PostAction(){
$url = 'http://sso.dengwei4378.com/api/master/getInfoByMasterName';
$options = [
'form_params' => [
"masterName" => 'dengwei4378',
"system" => 'rbac'
],
'timeout' => 1 //自定义超时秒数,覆盖默认值
];
$request = new Request();
$post_ret = $request->post($url, $options);
var_dump($post_ret);
exit;
}
/**
* 并发GET
*/
public function ConGetAction(){
$params = [
0 => [
'url' => 'http://sso.dengwei4378.com',
'timeout' => 3 //自定义超时秒数,覆盖默认值
],
1 => [
'url' => 'https://api.github.com/',
'timeout' => 3 //自定义超时秒数,覆盖默认值
],
];
$request = new Request();
$ret = $request->concurrencyGet($params);
var_dump($ret);
exit;
}
public function ConPostAction(){
$params = [
0 => [
'url' => 'http://lock-screen-push.int.yidian-inc.com/lock-screen/list',
'headers' => [
'Content-type' => 'application/json',
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36'
],
'json' => [ //json格式
"bizid" => "YDZX",
"uid" => "765073697",
"platform" => "1",
"appid" => "hipu"
],
'timeout' => 0.1 //自定义超时秒数,覆盖默认值
],
1 => [
'url' => 'http://sso.dengwei4378.com/api/master/getInfoByMasterName',
'form_params' => [ //表单格式
"masterName" => 'dengwei4378',
"system" => 'rbac'
],
'timeout' => 0.2 //自定义超时秒数,覆盖默认值
],
];
$request = new Request();
$ret = $request->concurrencyPost($params);
var_dump($ret);
exit;
}
}
<?php
use App\Base\Base;
use Helpers\Aes;
use Api\PhpUtils\Http\Request;
use Api\PhpServices\Session\SessionManager;
use App\Exception\BaseException;
class SessionController extends Base
{
public function StartAction()
{
// $key = 'asdfasdfasdfasdf';
// $iv = 'fdsafdsafdsafdsa';
// $salt = "12341/5";
// var_dump(base64_encode($salt));
// var_dump(strtolower(str_replace(array('+','/','='), array(''), base64_encode($salt))));
// var_dump($data = openssl_encrypt($salt, "AES-128-CBC", $key, 0, $iv));
// var_dump(openssl_decrypt($data, "AES-128-CBC", $key, 0, $iv));
// exit;
// $result = (new Request())->get('http://10.126.171.30:18080/topom', [], 1);
// // $proxy = $result['stats']['proxy'];
// $server = $result['stats']['group']['models'];
// $arr = [];
// foreach ($server as $item) {
// $arr[] = $item['servers'][1]['server'];
// }
// print_r($arr);
// exit;
// print_r(\Yaconf::get('interface.test.service'));exit;
// echo $s = '{'.str_replace(array('+','/','='), array('-','_',''), base64_encode('12345')).'}';
// exit;
// $s = json_decode(json_encode(['a' =>'{MTIzNDU}e3eec597a5a3f9420b445c89d38a6fbc7c']),true);
// print_r($s);exit;
// phpinfo();exit;
// $key = 'interface.test.service.session.get';
// echo \Yaconf::get($key);
// exit;
$ret = SessionManager::start();
// print_r($_SERVER);
// print_r($_COOKIE);
var_dump($ret);
print_r($_SESSION);
// $ret1 = SessionManager::destroy();
// // print_r($_SERVER);
// // print_r($_COOKIE);
// var_dump($ret1);
// print_r($_SESSION);
// var_dump($ret);
}
public function CreateAction()
{
$ret = SessionManager::set('metro', '12345', true, ['a' => 'aaa', 'b' => 'bbb', 'c' => 'ccc', 'd' => 'ddd'], 1);
var_dump($ret);
print_r($_SESSION);
exit;
}
public function DestroyAction()
{
$ret = SessionManager::destroy();
// print_r($_SERVER);
// print_r($_COOKIE);
var_dump($ret);
print_r($_SESSION);
}
public function GetAction()
{
print_r($request = $this->getRequest()->getRequest());
$sessionid = $request['sid'] ?? 'aedcc37ea232aade90037716ddab1debe6';
$url = $this->getBaseUri() . '/get-session';
$query = ['sessionid' => $sessionid];
// $query = ['sessionid' => 'jssionidtest'];
$result = (new Request())->get($url, $query, 3000);
print_r($result);
exit;
if (isset($result['code']) && $result['code'] == 0 ) {
return true;
}
return false;
}
public function SetAction()
{
$url = $this->getBaseUri() . '/set-session';
$sessionData = ['id' => 123, 'name' => 'test'];
$params = ['sessionid' => 'jssionidtest11', 'data' => ($sessionData), 'expire' => 600, 'key' => 'c071f6e5923a648a5ef88f32b6f738e1'];
$result = (new Request())->post($url, $params, 1000, 'json');
print_r($result);
}
public function DelAction()
{
$url = $this->getBaseUri() . '/delete-session';
$query = ['sessionid' => ['jssionidtest1', 'jssionidtest'], 'key' =>'c071f6e5923a648a5ef88f32b6f738e1'];
$result = (new Request())->get($url, $query, 1000);
print_r($result);
}
public function MgetAction()
{
$url = $this->getBaseUri() . '/get-many-session';
$query = ['sessionid' =>['YPZQISU1Tjxg3wJLFWJmVA', 'E4vo3R5EfaPS-pnyDzia3Q']];
$result = (new Request())->get($url, $query, 2000);
print_r($result);
exit;
$url = $this->getBaseUri() . '/get-many-session';
$query = ['sessionid' =>['jssionidtest2', 'jssionidtest1']];
$result = (new Request())->get($url, $query, 2000);
print_r($result);
exit;
// $validSessionIds[] = 'a';
// $validSessionIds[] = 'b';
// $validSessionIds[] = 'c';
// echo $validSessionIds[rand(0, count($validSessionIds) - 1)];
// exit;
// // todo 请求接口读redis
// echo $url = $this->getBaseUri() . '/get-session1';
// $query = ['sessionid' => 'jssionidtest'];
// $result = (new Request())->get($url, $query, 1000);
// if (isset($result['code']) && $result['code'] == 0 && isset($result['result'])) {
// $data = $result['result'];
// print_r($data);
// }else {
// print_r($result);
// }
// exit;
// $r = \Api\PhpUtils\Common\IP::find('114.114.114.114');
// print_r($r);
// exit;
// $_SESSION['abc'] = 'ttt';
// echo $_SESSION['abc'];
// echo $_SESSION['abc'];
// echo $_SESSION['abc'];
// echo $_SESSION['abc'];
// exit;
// $abc = '123'. "\x7F" . 456;
// var_dump($abc);exit;//string(7) "123456" 不可见字任作为分隔符
// $a = base64_encode('6543211111dasfsdfasdf1111asdfasdfs1111');
// var_dump($a);
// var_dump(sha1($a));
// var_dump(substr(sha1($a), -2));
// $a = $a . substr(sha1($a), -2);
// var_dump($a);
// var_dump(substr($a, 0, -2));
// $a = substr($a, 0, -2);
// var_dump($a);
// var_dump(sha1($a));
// var_dump(substr(sha1($a), -2));
// exit;
// var_dump(strlen($a));
// var_dump($a);exit;
// var_dump($this->response);
// var_dump(Yaf\Dispatcher::getInstance()->getResponse());
// exit;
// $data = ['appid'=> 'appid', 'verison'=>'023200', 'reqid'=>'11adddddddfasdfasdfasdfasdfdsafwerqwersfasfasdvasdfsdfffs1', 'platform'=>'1', 'ts' => ceil(microtime(true) * 1000)];
// echo $sign = Aes::createSign($data);
// exit;
// $data = ['appid'=> 'appid', 'verison'=>'023200', 'reqid'=>'111', 'platform'=>'1'];
// $data['sign'] = 'l4lBCE3B_v-ODFeuoxFksl0IUY9ehBnjN_FtU3ESdrn_bMPDsEIxA8IUw0pDJ_kX06P6OOw23in46acBucgceSBE2Vx3Ew52w3FfmRn8IhE';
// $sign = Aes::checkSign($data);
// var_dump($sign);
// exit;
// $obj = new App\Models\User();
// print_r($obj->getUserData());//Array ( [name] => zhangsan [age] => 18 )
// exit;
// $http = $this->getRequest()->getRequest();
// var_dump($http);
// var_dump(file_get_contents("php://input"));
// var_dump($this->requestAll());yaf
// exit;
$res = [
"userid" => 'user',
"code" => 0
];
// print_r($this->failed(-1,'reason'));
$this->success($res);
}
/**
* get uri
* @return string
*/
public function getBaseUri()
{
$env = \Yaf\Application::app()->environ() ?? "dev1";
if ($env == 'product') {
$this->baseUri = 'http://a4.go2yd.com/Website/session';
}elseif ($env == 'dev') {
$this->baseUri = 'http://127.0.0.1/Website/session';
}else {
$this->baseUri = 'http://a4-1.go2yd.com/Website/session';
}
return $this->baseUri;
}
}
\ No newline at end of file
<?php
use App\Base\Base;
class TestController extends Base
{
public function indexAction()
{
$this->success();
}
}
This diff is collapsed.
## modules
#### 第一层文件夹 首字母要大写 ,请参考Test/controllers目录,
#### 已有的Test目录,请在开发时删除
\ No newline at end of file
<?php
namespace App\Plugins;
use App\Exception\ExceptionErrorCatch;
use Helpers\DebugLog;
class Hook extends \Yaf\Plugin_Abstract {
public function routerStartup(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
// 重定义异常处理
ExceptionErrorCatch::register();
}
public function routerShutdown(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
/*---Debug Begin---*/
if((defined('_IS_DEBUG') && _IS_DEBUG) && (isset($_REQUEST['__debug']) && strpos($_REQUEST['__debug'], _DEBUG_PASS) !== false))
{
// $_REQUEST['__debug'] = _DEBUG_PASS + 1 (2 数字表示级别 )
$debug_level = intval(substr($_REQUEST['__debug'], -1));
if ($debug_level > 0) {
define('DEBUG_LEVEL', $debug_level );
} else {
define('DEBUG_LEVEL', 1);
}
//Debug模式将错误打开
ini_set('display_errors', true);
//设置错误级别
error_reporting(_ERROR_LEVEL);
//开启ob函数
ob_start();
//Debug开关打开
DebugLog::init();
//注册shutdown函数用来Debug显示
register_shutdown_function(array('Helpers\DebugLog', 'show'));
} else {
define('DEBUG_LEVEL', 0);
}
// 调试探针,初始化完成,页面开始执行
DebugLog::time('init.php, start page');
}
public function dispatchLoopStartup(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
}
public function preDispatch(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
//处理$_POST, $_REQUEST请求,兼容application/json形式
if(!$_POST && $request->isPost()
&& $request->getServer('CONTENT_TYPE') == 'application/json') {
$jsonPost = file_get_contents("php://input");
if($jsonPost) {
$_POST = json_decode($jsonPost, true);
$ini = ini_get('request_order');
if($ini) {
$arrIni = str_split($ini, 1);
foreach($arrIni as $type) {
if(strtoupper($type) === 'G') {
$_REQUEST = array_merge($_REQUEST, $_GET);
}elseif(strtoupper($type) === 'P') {
$_REQUEST = array_merge($_REQUEST, $_POST);
}
}
}
}
}
}
public function postDispatch(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
}
public function dispatchLoopShutdown(\Yaf\Request_Abstract $request, \Yaf\Response_Abstract $response) {
}
}
<?php
namespace App\Services\demo;
use App\Models\demo\mongo\User;
class MongoService
{
public function addUser()
{
$user = User::getInstance();
$data = [
'_id' => 4,
'name' => 'dw04',
'mobile' => '17701340004'
];
return $user->add($data);
}
public function addManyUser()
{
$user = User::getInstance();
$data = [
[
'_id' => 5,
'name' => 'dw05',
'mobile' => '17701340005'
],
[
'_id' => 6,
'name' => 'dw06',
'mobile' => '17701340006'
]
];
return $user->addMany($data);
}
public function deleteUser()
{
$user = User::getInstance();
$params = [
'name' => 'dw01'
];
return $user->delete($params);
}
public function updateUser()
{
$user = User::getInstance();
$params = [
'name' => 'dw02'
];
$data = [
'mobile' => '17701340002'
];
return $user->update($params, $data);
}
public function getUser()
{
$user = User::getInstance();
$params = [
'name' => 'dw02'
];
return $user->get($params);
}
public function getManyUser()
{
$user = User::getInstance();
$params = [
'name' => 'dw02'
];
return $user->getMany($params);
}
}
<?php
namespace App\Services\demo;
use App\Models\demo\mysql\User;
class MysqlService
{
public function addUser()
{
$user = User::getWriteInstance();
$data = [
'name' => 'dw07',
'mobile' => '17701340007'
];
return $user->add($data);
}
public function addManyUser()
{
$user = User::getWriteInstance();
$data = [
[
'name' => 'dw08',
'mobile' => '17701340008'
],
[
'name' => 'dw09',
'mobile' => '17701340009'
]
];
return $user->addMany($data);
}
public function deleteUser()
{
$user = User::getWriteInstance();
$params = [
'name' => 'dw08'
];
return $user->delete($params);
}
public function updateUser()
{
$user = User::getWriteInstance();
$params = [
'name' => 'dw02'
];
$data = [
'mobile' => '15030690002'
];
return $user->update($params, $data);
}
public function getUser()
{
$user = User::getInstance();
$params = [
'name' => 'dw02'
];
$column = [
'name',
'mobile'
];
return $user->get($params, $column);
}
public function getManyUser()
{
$user = User::getInstance();
$params = [
'id[>]' => 3
];
$column = [
'name',
'mobile'
];
return $user->getMany($params, $column);
}
public function countUser()
{
$user = User::getInstance();
$params = [
'master_name' => 'dw04'
];
$column = 'id';
return $user->count($params, $column);
}
public function maxUser()
{
$user = User::getInstance();
$params = [
'id[>]' => 1
];
$column = 'id';
return $user->max($params, $column);
}
public function minUser()
{
$user = User::getInstance();
$params = [
'id[>]' => 1
];
$column = 'id';
return $user->min($params, $column);
}
public function avgUser()
{
$user = User::getInstance();
$params = [
'id[>]' => 1
];
$column = 'id';
return $user->avg($params, $column);
}
public function sumUser()
{
$user = User::getInstance();
$params = [
'id[>]' => 1
];
$column = 'id';
return $user->sum($params, $column);
}
}
<?php
namespace App\Services\order;
class OrderService
{
public static function get_idgen_id($number, $count=1){
$res = Idgen::get(appConfig('idgen.partner'),appConfig('idgen.key'), [], [[
"type" => "merchant_shop_id",
'number'=>$number,
"count"=> $count]]);
$id = $res['id_datetime']['merchant_shop_id'] ?? [];
return $id;
}
/**
* @param $orderId
* @param $userId
* 调用内部服务获取用户订单、子单、分润信息
*/
public static function getOrderData($orderId, $userId) {
return self::getDemoData($orderId, $userId);
}
public static function getDemoData($orderId, $userId) {
$order = [
'order_id'=>$orderId,
'user_id'=>$userId,
'life_account_id'=>2312, //'生活号id',
'shop_id'=>2312, //'店铺shop_id',
'order_type'=>1, //'1虚拟商品,2实体商品',
'payment'=>1, //'1虚拟商品,2实体商品',
'order_status'=>100, //'100 待付款',
];
$order_items = [
[
'order_item_id'=>$orderId . rand(100, 999),
'order_id'=>$orderId,
'user_id'=>$userId,
'goods_spu_id'=>$orderId . rand(100, 999),
'goods_sku_id'=>$orderId . rand(100, 999),
'marketing_type'=>1,
],
[
'order_item_id'=>$orderId . rand(100, 999),
'order_id'=>$orderId,
'user_id'=>$userId,
'goods_spu_id'=>$orderId . rand(100, 999),
'goods_sku_id'=>$orderId . rand(100, 999),
'marketing_type'=>1,
]
];
foreach ($order_items as $r) {
$order_distribution[] = [
'commission_mode'=>1,
'distributor_user_id'=>122234,
'distributor_commission_value'=>60,
'parent_user_id'=>122234 . rand(111, 999),
'parent_commission_value'=>60,
];
}
return [
'order'=> $order,
'order_items'=> $order_items,
'order_distribution'=> $order_distribution,
];
}
}
\ No newline at end of file
<?php
namespace App\Services\pay;
use Api\PhpServices\Idgen\Idgen;
use App\Exception\custom\PayException;
use App\Models\order\mysql\PayOrder;
use App\Models\order\mysql\PayOrderClearing;
class PayService
{
public function do_pay($order_id, $user_id) {
// 判断是否存在有效订单
$this->exist_valid($order_id, $user_id);
// 获取订单信息 + 子单信息 + 分润信息
$data = $this->get_order_data($order_id, $user_id);
// 创建订单信息
$pay_order = $this->make_pay_order($data);
// 发送ping++ 创建支付订单
$this->send_pingxx($pay_order);
}
/**
* @param $order_id
* @param $user_id
* @throws PayException
* 判断是否有效订单,如果存在则调用三方判断订单状态
*/
private function exist_valid($order_id, $user_id) {
$cur_date = date('Y-m-d H:i:s');
$order = PayOrder::ge(["order_id" => $order_id, 'expire_time[>]'=>$cur_date]);
if(!empty($order)) {
if($order['user_id'] != $user_id) {
throw new PayException(['cus' => 1]);
}
if(empty($order['third_order_id'])) {
throw new PayException(['cus' => 2]);
}
$this->get_order_from_pingxx($order['third_order_id']);
}
}
private function get_order_data($order_id, $user_id) {
}
public function makePayOrder($data) {
}
public function getInfo($orderId) {
$order = PayOrder::getRecord(["order_id" => $orderId]);
`expire_time` timestamp NULL DEFAULT NULL COMMENT '支付订单过期时间',
pay_order_status
}
public function iPingCreate() {
}
/**
* 创建店铺,同时更新生活号表的店铺数
* @param $life_account_id
* @param $merchant_id
* @param string $name
* @param bool $audit 是否需要审核
* @return \Api\PhpUtils\Mysql\MysqlBase
* @throws LifeAccountException
*/
public function create($life_account_id, $merchant_id, $name='', $shop_status=Shop::SHOP_STATUS_ON){
$life = LifeAccount::getMaster(['life_account_name'],['life_account_id' => $life_account_id]);
if(empty($life)){
throw new LifeAccountException(['cus'=>2]);
}
// 店铺id,通过idgen生成
$shop_id = OrderService::get_idgen_id(substr($life_account_id, -2));
$shop_id = $shop_id[0] ?? '';
if(empty($shop_id)){
throw new ShopException(['cus'=>1]);
}
// 店铺名,默认同生活号名
if(empty($name)){
$name = $life['life_account_name'];
}
$shop_res = Shop::insertRecord([
'shop_id' => $shop_id,
'shop_name' => $name,
'merchant_id' => $merchant_id,
'life_account_id' => $life_account_id,
'shop_status' => $shop_status
]);
if($shop_res===false){
throw new ShopException(['cus'=>0]);
}
// 更新生活号店铺数
$shop_res2 = LifeAccount::update([
"shop_totel_count[+]" => 1,
"shop_count[+]" => 1,
],[
"life_account_id" => $life_account_id
]);
if(!$shop_res2){
throw new ShopException(['cus'=>2]);
}
return $shop_id;
}
/**
* 更新商户id
*/
public static function changeMid($o_mid, $n_mid){
$res = Shop::update([
'merchant_id' => $n_mid
],[
'merchant_id' => $o_mid
]);
if($res===false){
throw new ShopException(['cus'=>3]);
}
return true;
}
}
\ No newline at end of file
## 业务处理放在这里
\ No newline at end of file
{
"name" : "bp/pay",
"description": "",
"type": "project",
"license": "MIT",
"require": {
"php": "7.4.*",
"ext-json": "*",
"api/php_utils":"dev-master",
"api/php_services":"dev-master",
"ext-openssl": "*"
},
"minimum-stability": "dev",
"autoload" : {
"psr-4" : {
"App\\Plugins\\" : "application/plugins",
"App\\Services\\" : "application/services",
"App\\Models\\" : "application/models",
"App\\Base\\" : "application/modules/Base",
"App\\Exception\\" : "application/exception",
"Daemon\\" : "daemon"
}
},
"scripts": {
"post-update-cmd": [
"php -f rmgit.php"
]
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"repositories": {
"api/php_utils":{
"type":"vcs",
"url":"https://gitlab.yidian-inc.com/bp/php_utils.git"
},
"api/php_services":{
"type":"vcs",
"url":"https://gitlab.yidian-inc.com/bp/php_services.git"
}
}
}
\ No newline at end of file
[common]
application.directory = APP_PATH
application.bootstrap = APP_PATH "/Bootstrap.php"
application.library = APP_PATH"/library"
application.library.namespace = ""
application.modules="Index,Test,Pay,Refund"
appid = "pay"
;AES密钥
aes.key = "79b20206d70e09b2"
aes.iv = "645410b05b5d1670"
aes.timeout = 5
;校验时间的开关
aes.switch = true
idgen.partner = "bp"
idgen.key = "5cfdb867e96374c7883b31d6928cc4cb"
[exception]
debug = true
exception.user.code = -1
exception.user.msg = "error"
exception.sys.code = -1
exception.sys.msg = "system error"
[prod : common : exception]
[pre : common : exception]
[test : common : exception]
[dev : common : exception]
[common]
application.directory = APPLICATION_PATH"/application"
application.library = APPLICATION_PATH"/application/library"
application.bootstrap = APPLICATION_PATH"/application/BootstrapCli.php"
application.dispatcher.catchException = true
application.dispatcher.throwException = true
daemon.script_dir = "\\Daemon\\"
appid = "pay"
[product : common]
[pre : common ]
[test: common ]
[dev : common ]
\ No newline at end of file
<?php
namespace Daemon;
use Api\PhpServices\Daemon\DaemonServiceInterface;
class Test implements DaemonServiceInterface
{
public function run()
{
// throw new \Exception("test exception");
sleep(10);
}
}
\ No newline at end of file
ipdata等文件放在这里
\ No newline at end of file
#!/usr/bin/env bash
# Start commands for each container, one cmd a line
START_CMDS="cd /home/services && ${start_cmd}
"
# QA_PRE_START_CMD='
# export collect_coverage=true
# '
# Container names for each container, one name a line, same order with $start_cmds
CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Port maps for each container, one map a line, same order with $start_cmds
DOCKER_PORT_MAPS="
${TARGET_PORT}:9000
"
# This is for changing container name, remove old containers when deploy new one
OLD_CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Volumn maps for each container, one map a line, same order with $start_cmds
DOCKER_VOLUMN_MAPS="
/home/worker/_logs/api-${env}-${domain_prefix}:/home/services/api.go2yd.com/logs
"
# Other docker run options
DOCKER_RUN_OPTIONS="--cap-add SYS_PTRACE --restart=always --privileged"
# Image name
IMAGE_NAME="docker2.yidian.com:5000/publish/${COMMIT_JOB}-${COMMIT_NUMBER}-image"
# This is for stopping container, kill sepicify process inside the container before 'docker stop' and 'docker rm'
DOCKER_PRESTOP_CMD='mv /var/lib/logrotate.status /home/services/api.go2yd.com/logs/logrotate.status'
# Service port for apitest
SERVICE_PORT=${TARGET_PORT}
# Service port inside container
ORIGIN_SERVICE_PORT="9000"
#!/usr/bin/env bash
# Start commands for each container, one cmd a line
START_CMDS="
cd /home/services && ${start_cmd}
"
QA_PRE_START_CMD="
"
# Container names for each container, one name a line, same order with $start_cmds
CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Port maps for each container, one map a line, same order with $start_cmds
DOCKER_PORT_MAPS="
${TARGET_PORT}:9000
"
# This is for changing container name, remove old containers when deploy new one
OLD_CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Volumn maps for each container, one map a line, same order with $start_cmds
DOCKER_VOLUMN_MAPS="
/home/worker/_logs/api-${env}-${domain_prefix}:/home/services/api.go2yd.com/logs
"
# Other docker run options
DOCKER_RUN_OPTIONS="--cap-add SYS_PTRACE --restart=always --privileged"
# Image name
IMAGE_NAME="docker2.yidian.com:5000/publish/${COMMIT_JOB}-${COMMIT_NUMBER}-image"
# This is for stopping container, kill sepicify process inside the container before 'docker stop' and 'docker rm'
DOCKER_PRESTOP_CMD='mv /var/lib/logrotate.status /home/services/api.go2yd.com/logs/logrotate.status'
# Service port for apitest
SERVICE_PORT=${TARGET_PORT}
# Service port inside container
ORIGIN_SERVICE_PORT="9000"
#!/usr/bin/env bash
# Start commands for each container, one cmd a line
START_CMDS="
cd /home/services && ${start_cmd}
"
QA_PRE_START_CMD="
"
# Container names for each container, one name a line, same order with $start_cmds
CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Port maps for each container, one map a line, same order with $start_cmds
DOCKER_PORT_MAPS="
${TARGET_PORT}:9000
"
# This is for changing container name, remove old containers when deploy new one
OLD_CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Volumn maps for each container, one map a line, same order with $start_cmds
DOCKER_VOLUMN_MAPS="
/home/worker/_logs/api-${env}-${domain_prefix}:/home/services/api.go2yd.com/logs
"
# Other docker run options
DOCKER_RUN_OPTIONS="--cap-add SYS_PTRACE --restart=always --privileged"
# Image name
IMAGE_NAME="docker2.yidian.com:5000/publish/${release_job}-${release_number}-image"
# This is for stopping container, kill sepicify process inside the container before 'docker stop' and 'docker rm'
DOCKER_PRESTOP_CMD='mv /var/lib/logrotate.status /home/services/api.go2yd.com/logs/logrotate.status'
# Service port for apitest
SERVICE_PORT=${TARGET_PORT}
# Service port inside container
ORIGIN_SERVICE_PORT="9000"
#!/usr/bin/env bash
# Start commands for each container, one cmd a line
START_CMDS="cd /home/services && ${start_cmd}
"
# QA_PRE_START_CMD='
# export collect_coverage=true
# '
# Container names for each container, one name a line, same order with $start_cmds
CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Port maps for each container, one map a line, same order with $start_cmds
DOCKER_PORT_MAPS="
${TARGET_PORT}:9000
"
# This is for changing container name, remove old containers when deploy new one
OLD_CONTAINER_NAMES="
api-${env}-${domain_prefix}
"
# Volumn maps for each container, one map a line, same order with $start_cmds
DOCKER_VOLUMN_MAPS="
/home/worker/_logs/api-${env}-${domain_prefix}:/home/services/api.go2yd.com/logs
"
# Other docker run options
DOCKER_RUN_OPTIONS="--cap-add SYS_PTRACE --restart=always --privileged"
# Image name
IMAGE_NAME="docker2.yidian.com:5000/publish/${COMMIT_JOB}-${COMMIT_NUMBER}-image"
# This is for stopping container, kill sepicify process inside the container before 'docker stop' and 'docker rm'
DOCKER_PRESTOP_CMD='mv /var/lib/logrotate.status /home/services/api.go2yd.com/logs/logrotate.status'
# Service port for apitest
SERVICE_PORT=${TARGET_PORT}
# Service port inside container
ORIGIN_SERVICE_PORT="9000"
#!/usr/bin/env bash
DIST_FILE_NAME="*.tar.gz"
PROJECT_DIR="api.go2yd.com"
START_SCRIPT="./start_env/start_api.sh"
SYNC_DATA_OPERATIONS="
tar zxf *.tar.gz -C start_env/api.go2yd.com/htdocs/Website
"
DEST_FILE_NAME=""
DEST_FILE_PATH=""
BASE_IMAGE="docker2.yidian.com:5000/centos7/php72_without_nginx:20210621"
MAINTAINER="cuiweifeng \"cuiweifeng@yidian-inc.com\""
HOME_DIR="/home/services"
LOG_DIRS="
${HOME_DIR}/${PROJECT_DIR}/logs
"
DATA_DIRS="
"
#!/usr/bin/env bash
DIST_FILE_NAME="*.tar.gz"
PROJECT_DIR="api.go2yd.com"
START_SCRIPT="./start_env/start_api.sh"
SYNC_DATA_OPERATIONS="
tar zxf *.tar.gz -C start_env/api.go2yd.com/htdocs/Website
"
DEST_FILE_NAME=""
DEST_FILE_PATH=""
BASE_IMAGE="docker2.yidian.com:5000/centos7/php72_without_nginx:20210621"
MAINTAINER="cuiweifeng \"cuiweifeng@yidian-inc.com\""
HOME_DIR="/home/services"
LOG_DIRS="
${HOME_DIR}/${PROJECT_DIR}/logs
"
DATA_DIRS="
"
#!/usr/bin/env bash
DIST_FILE_NAME="*.tar.gz"
PROJECT_DIR="api.go2yd.com"
START_SCRIPT="./start_env/start_api.sh"
SYNC_DATA_OPERATIONS="
tar zxf *.tar.gz -C start_env/api.go2yd.com/htdocs/Website
"
DEST_FILE_NAME=""
DEST_FILE_PATH=""
BASE_IMAGE="docker2.yidian.com:5000/centos7/php72_without_nginx:20210621"
MAINTAINER="cuiweifeng \"cuiweifeng@yidian-inc.com\""
HOME_DIR="/home/services"
LOG_DIRS="
${HOME_DIR}/${PROJECT_DIR}/logs
"
DATA_DIRS="
"
#!/usr/bin/env bash
DIST_FILE_NAME="*.tar.gz"
PROJECT_DIR="api.go2yd.com"
START_SCRIPT="./start_env/start_api.sh"
SYNC_DATA_OPERATIONS="
tar zxf *.tar.gz -C start_env/api.go2yd.com/htdocs/Website
"
DEST_FILE_NAME=""
DEST_FILE_PATH=""
BASE_IMAGE="docker2.yidian.com:5000/centos7/php72_without_nginx:20210621"
MAINTAINER="cuiweifeng \"cuiweifeng@yidian-inc.com\""
HOME_DIR="/home/services"
LOG_DIRS="
${HOME_DIR}/${PROJECT_DIR}/logs
"
DATA_DIRS="
"
This diff is collapsed.
[api.go2yd.com]
prefix = /home/services/api.go2yd.com
user = nobody
group = nobody
listen = 0.0.0.0:9000
;listen = /var/run/php-fpm/api.go2yd.com.sock
listen.backlog = 2048
listen.owner = nobody
listen.group = nobody
listen.mode = 0600
pm = static
pm.max_children = 256
pm.max_requests = 100
pm.status_path = /status-fpm
access.log = /home/services/api.go2yd.com/logs/access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %{mili}d %{kilo}M %C%%"
slowlog = /home/services/api.go2yd.com/logs/fpm-slow.log
request_slowlog_timeout = 1s
request_terminate_timeout = 6s
catch_workers_output = yes
env[PATH] = /usr/local/bin:/usr/bin:/bin
<?php
$config = array(
'debug' => false,
'mode' => 'development',
'extension' => 'tideways_xhprof',
'save.handler' => 'mongodb',
'db.host' => 'mongodb://10.126.150.23:27017',
'db.db' => 'xhprof',
'db.options' => array(),
'date.format' => 'Y-m-d H:i:s',
'detail.count' => 6,
'page.limit' => 25,
// Profile 1 in 100 requests.
// You can return true to profile every request.
'profiler.enable' => function () {
// 暂时关闭xhgui性能监控
// if (strpos($_SERVER['SCRIPT_NAME'], 'Action.php') !== false)
// {
// return true;
// }
return false;
},
'profiler.simple_url' => function ($url) {
return preg_replace('/\=\d+/', '', $url);
},
//'/home/admin/www/xhgui/webroot','F:/phpPro'
'profiler.filter_path' => array()
);
if (!extension_loaded('tideways_xhprof'))
{
error_log('xhgui - extension tideways_xhprof must be loaded');
return;
}
if ($config['debug'])
{
ini_set('display_errors', 1); // 该选项设置是否将错误信息作为输出的一部分显示到屏幕,或者对用户隐藏而不显示。
}
// 指定监控的目录
if (is_array($config['profiler.filter_path']) && in_array($_SERVER['DOCUMENT_ROOT'], $config['profiler.filter_path']))
{
return;
}
if ((!extension_loaded('mongo') && !extension_loaded('mongodb')) && $config['save.handler'] === 'mongodb')
{
error_log('xhgui - extension mongo not loaded');
return;
}
if (!shouldRun())
{
return;
}
if (!isset($_SERVER['REQUEST_TIME_FLOAT']))
{
$_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
}
if ($config['extension'] == 'tideways_xhprof' && extension_loaded('tideways_xhprof'))
{
tideways_xhprof_enable(TIDEWAYS_XHPROF_FLAGS_MEMORY | TIDEWAYS_XHPROF_FLAGS_MEMORY_MU | TIDEWAYS_XHPROF_FLAGS_MEMORY_PMU | TIDEWAYS_XHPROF_FLAGS_CPU);
}
else
{
error_log("Please check the extension name in config.php, you can use the 'php -m' command.");
return;
}
//注册一个会在php中止时执行的函数
register_shutdown_function(
function () {
$data['profile'] = tideways_xhprof_disable();
// ignore_user_abort(true) allows your PHP script to continue executing, even if the user has terminated their request.
// Further Reading: http://blog.preinheimer.com/index.php?/archives/248-When-does-a-user-abort.html
// flush() asks PHP to send any data remaining in the output buffers. This is normally done when the script completes, but
// since we're delaying that a bit by dealing with the xhprof stuff, we'll do it now to avoid making the user wait.
ignore_user_abort(true);
flush();
$uri = array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : null;
if (empty($uri) && isset($_SERVER['argv']))
{
$cmd = basename($_SERVER['argv'][0]);
$uri = $cmd . ' ' . implode(' ', array_slice($_SERVER['argv'], 1));
}
$time = array_key_exists('REQUEST_TIME', $_SERVER) ? $_SERVER['REQUEST_TIME'] : time();
$requestTimeFloat = explode('.', $_SERVER['REQUEST_TIME_FLOAT']);
if (!isset($requestTimeFloat[1]))
{
$requestTimeFloat[1] = 0;
}
$requestTs = new MongoDB\BSON\UTCDateTime($time * 1000);
$requestTsMicro = new MongoDB\BSON\UTCDateTime($_SERVER['REQUEST_TIME_FLOAT'] * 1000);
$data['meta'] = array(
'url' => $uri,
'SERVER' => $_SERVER,
'get' => $_GET,
'env' => $_ENV,
'simple_url' => simpleUrl($uri),
'request_ts' => $requestTs,
'request_ts_micro' => $requestTsMicro,
'request_date' => date('Y-m-d', $time),
);
// 保存数据到MongoDB
save2mongo($data);
}
);
function simpleUrl($url)
{
global $config;
$callable = $config['profiler.simple_url'];
if (is_callable($callable))
{
return call_user_func($callable, $url);
}
return preg_replace('/\=\d+/', '', $url);
}
function shouldRun()
{
global $config;
$callback = $config['profiler.enable'];
if (!is_callable($callback))
{
return false;
}
return (bool)$callback();
}
function save2mongo($data)
{
global $config;
$manager = new MongoDB\Driver\Manager($config['db.host']);
$bulk = new MongoDB\Driver\BulkWrite();
try
{
$bulk->insert($data);
$writeConcern = new MongoDB\Driver\WriteConcern(1, 100);
$manager->executeBulkWrite($config['db.db'] . '.results', $bulk, $writeConcern);
} catch (Exception $e)
{
error_log('xhgui - ' . $e->getMessage());
}
}
#!/usr/bin/env bash
working_dir=`dirname $0`
echo "working_dir :"$working_dir
CGI_CLIENT="${working_dir}/cgi-fcgi"
function log()
{
echo "[`date +%Y-%m-%d %H:%M:%S`] $@"
}
export LD_LIBRARY_PATH=${working_dir}
if [ ! -x "${CGI_CLIENT}" ]
then
log "cgi client not found or not executable"
exit 1
fi
function fcgi_get()
{
document_root=$1
script_file=$2
host=$3
port=$4
server_name=$5
REQUEST_URI=${script} \
SERVER_ADDR=$3 \
REQUEST_METHOD=GET \
SERVER_NAME=${server_name} \
DOCUMENT_ROOT=${document_root} \
DOCUMENT_URI=${script} \
SCRIPT_NAME=${script} \
SCRIPT_FILENAME=${document_root}${script} \
QUERY_STRING= \
REMOTE_ADDR=127.0.0.1 \
GATEWAY_INTERFACE=CGI/1.1 \
${CGI_CLIENT} -bind -connect ${host}:${port}
}
function api_get()
{
script=$1
port=$2
domain_prefix=$3
fcgi_get "/home/services/api.go2yd.com/htdocs/Website/public" ${script} 127.0.0.1 ${port} {$domain_prefix}".go2yd.com"
}
result=`api_get "/test.php" $1 $2 | awk -F"\r" '{print $NF}'`
check=`echo ${result} | grep "success"`
if [ "" = "${check}" ]
then
echo ${result}
exit 1
else
echo "success"
fi
#!/usr/bin/env bash
working_dir=`dirname $0`
CGI_CLIENT="${working_dir}/cgi-fcgi"
export LD_LIBRARY_PATH=${working_dir}
function fcgi_get()
{
document_root=$1
script_file=$2
host=$3
port=$4
server_name=$5
REQUEST_METHOD=GET \
SERVER_NAME=${server_name} \
DOCUMENT_ROOT=${document_root} \
DOCUMENT_URI=${script} \
SCRIPT_NAME=${script} \
SCRIPT_FILENAME=${document_root}${script} \
QUERY_STRING= \
GATEWAY_INTERFACE=CGI/1.1 \
REMOTE_ADDR = 127.0.0.1 \
REQUEST_URI=${script}
${CGI_CLIENT} -bind -connect ${host}:${port}
}
function api_get()
{
script=$1
fcgi_get "/home/services/api.go2yd.com/htdocs/Website" ${script} 127.0.0.1 9000 "qa-int.go2yd.com/Website"
}
while [ "`ps -ax | grep php-fpm -c`" = 0 ]; do
sleep 5;
done
sleep 10
for file in `find /home/services/api.go2yd.com/htdocs/Website/ | grep -oP '(?<=/home/services/api.go2yd.com/htdocs/Website).*\.php$'`; do
api_get $file
done
<?php
if ($_GET['clear'] == "true")
{
apcu_delete("coverage");
print("done!");
exit();
} else {
print("need param 'clear' be 'true'");
}
<?php
$coverage = apcu_fetch("coverage");
if ($coverage == false)
{
$coverage = array();
}
$timestamp = time();
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument('1.0','UTF-8');
$xml->setIndent(4);
$xml->startElement('coverage');
$xml->writeAttribute('generated', $timestamp);
$xml->startElement('project');
$xml->writeAttribute('timestamp', $timestamp);
$sum_ncloc = 0;
$sum_methods = 0;
$sum_coveredmethods = 0;
$sum_statements = 0;
$sum_coveredstatements = 0;
$sum_elements = 0;
$sum_coveredelements = 0;
function generate_line_element($line_coverage, $line_number, $xml)
{
# $xml->startElement('line');
# $xml->writeAttribute('num', $line_number);
# $xml->writeAttribute('type', 'stmt');
# $xml->writeAttribute('value', $line_coverage);
# $xml->endElement();
$GLOBALS['loc']++;
if ($line_coverage > -2) {
$GLOBALS['ncloc']++;
}
$GLOBALS['statements']++;
if ($line_coverage >= 1) {
$GLOBALS['coveredstatements']++;
}
}
function gerenate_file_element($file_coverage, $filename, $xml)
{
$xml->startElement('file');
$xml->writeAttribute('name', $filename);
# $content = file_get_contents($filename);
# try {
# $parser = new PHPFuncParser($content);
# $function_list = $parser -> process();
# $GLOBALS['function_list'] = $function_list;
# } catch (RuntimeException $e) {
# var_dump($e->getMessage());
# exit(1);
# }
$GLOBALS['loc'] = 0;
$GLOBALS['ncloc'] = 0;
$GLOBALS['methods'] = 0;
$GLOBALS['coveredmethods'] = 0;
$GLOBALS['statements'] = 0;
$GLOBALS['coveredstatements'] = 0;
$GLOBALS['elements'] = 0;
$GLOBALS['coveredelements'] = 0;
array_walk($file_coverage, 'generate_line_element', $xml);
$GLOBALS['elements'] = $GLOBALS['methods'] + $GLOBALS['statements'];
$GLOBALS['coveredelements'] = $GLOBALS['coveredmethods'] + $GLOBALS['coveredstatements'];
$xml->startElement('metrics');
$xml->writeAttribute('loc', $GLOBALS['loc']);
$xml->writeAttribute('ncloc', $GLOBALS['ncloc']);
$xml->writeAttribute('methods', $GLOBALS['methods']);
$xml->writeAttribute('coveredmethods', $GLOBALS['coveredmethods']);
$xml->writeAttribute('statements', $GLOBALS['statements']);
$xml->writeAttribute('coveredstatements', $GLOBALS['coveredstatements']);
$xml->writeAttribute('elements', $GLOBALS['elements']);
$xml->writeAttribute('coveredelements', $GLOBALS['coveredelements']);
$GLOBALS['sum_loc'] += $GLOBALS['loc'];
$GLOBALS['sum_ncloc'] += $GLOBALS['ncloc'];
$GLOBALS['sum_methods'] += $GLOBALS['methods'];
$GLOBALS['sum_coveredmethods'] += $GLOBALS['coveredmethods'];
$GLOBALS['sum_statements'] += $GLOBALS['statements'];
$GLOBALS['sum_coveredstatements'] += $GLOBALS['coveredstatements'];
$GLOBALS['sum_elements'] += $GLOBALS['elements'];
$GLOBALS['sum_coveredelements'] += $GLOBALS['coveredelements'];
$xml->endElement();
$xml->endElement();
}
array_walk($coverage, 'gerenate_file_element', $xml);
$xml->startElement('metrics');
$xml->writeAttribute('loc', $GLOBALS['sum_loc']);
$xml->writeAttribute('ncloc', $GLOBALS['sum_ncloc']);
$xml->writeAttribute('methods', $GLOBALS['sum_methods']);
$xml->writeAttribute('coveredmethods', $GLOBALS['sum_coveredmethods']);
$xml->writeAttribute('statements', $GLOBALS['sum_statements']);
$xml->writeAttribute('coveredstatements', $GLOBALS['sum_coveredstatements']);
$xml->writeAttribute('elements', $GLOBALS['sum_elements']);
$xml->writeAttribute('coveredelements', $GLOBALS['sum_coveredelements']);
$xml->endElement();
$xml->endElement();
$xml->endElement();
$xml->endDocument();
#$xml->flush();
header("Content-type: text/xml");
print_r($coverage);
<?php
$coverage = apcu_fetch("coverage");
if ($coverage == false)
{
$coverage = array();
}
$timestamp = time();
$xml = new XMLWriter();
$xml->openMemory();
$xml->startDocument('1.0','UTF-8');
$xml->setIndent(4);
$xml->startElement('coverage');
$xml->writeAttribute('generated', $timestamp);
$xml->startElement('project');
$xml->writeAttribute('timestamp', $timestamp);
$sum_ncloc = 0;
$sum_methods = 0;
$sum_coveredmethods = 0;
$sum_statements = 0;
$sum_coveredstatements = 0;
$sum_elements = 0;
$sum_coveredelements = 0;
function generate_line_element($line_coverage, $line_number, $xml)
{
# $xml->startElement('line');
# $xml->writeAttribute('num', $line_number);
# $xml->writeAttribute('type', 'stmt');
# $xml->writeAttribute('value', $line_coverage);
# $xml->endElement();
$GLOBALS['loc']++;
if ($line_coverage > -2) {
$GLOBALS['ncloc']++;
}
$GLOBALS['statements']++;
if ($line_coverage >= 1) {
$GLOBALS['coveredstatements']++;
}
}
function gerenate_file_element($file_coverage, $filename, $xml)
{
$xml->startElement('file');
$xml->writeAttribute('name', $filename);
# $content = file_get_contents($filename);
# try {
# $parser = new PHPFuncParser($content);
# $function_list = $parser -> process();
# $GLOBALS['function_list'] = $function_list;
# } catch (RuntimeException $e) {
# var_dump($e->getMessage());
# exit(1);
# }
$GLOBALS['loc'] = 0;
$GLOBALS['ncloc'] = 0;
$GLOBALS['methods'] = 0;
$GLOBALS['coveredmethods'] = 0;
$GLOBALS['statements'] = 0;
$GLOBALS['coveredstatements'] = 0;
$GLOBALS['elements'] = 0;
$GLOBALS['coveredelements'] = 0;
array_walk($file_coverage, 'generate_line_element', $xml);
$GLOBALS['elements'] = $GLOBALS['methods'] + $GLOBALS['statements'];
$GLOBALS['coveredelements'] = $GLOBALS['coveredmethods'] + $GLOBALS['coveredstatements'];
$xml->startElement('metrics');
$xml->writeAttribute('loc', $GLOBALS['loc']);
$xml->writeAttribute('ncloc', $GLOBALS['ncloc']);
$xml->writeAttribute('methods', $GLOBALS['methods']);
$xml->writeAttribute('coveredmethods', $GLOBALS['coveredmethods']);
$xml->writeAttribute('statements', $GLOBALS['statements']);
$xml->writeAttribute('coveredstatements', $GLOBALS['coveredstatements']);
$xml->writeAttribute('elements', $GLOBALS['elements']);
$xml->writeAttribute('coveredelements', $GLOBALS['coveredelements']);
$GLOBALS['sum_loc'] += $GLOBALS['loc'];
$GLOBALS['sum_ncloc'] += $GLOBALS['ncloc'];
$GLOBALS['sum_methods'] += $GLOBALS['methods'];
$GLOBALS['sum_coveredmethods'] += $GLOBALS['coveredmethods'];
$GLOBALS['sum_statements'] += $GLOBALS['statements'];
$GLOBALS['sum_coveredstatements'] += $GLOBALS['coveredstatements'];
$GLOBALS['sum_elements'] += $GLOBALS['elements'];
$GLOBALS['sum_coveredelements'] += $GLOBALS['coveredelements'];
$xml->endElement();
$xml->endElement();
}
array_walk($coverage, 'gerenate_file_element', $xml);
$xml->startElement('metrics');
$xml->writeAttribute('loc', $GLOBALS['sum_loc']);
$xml->writeAttribute('ncloc', $GLOBALS['sum_ncloc']);
$xml->writeAttribute('methods', $GLOBALS['sum_methods']);
$xml->writeAttribute('coveredmethods', $GLOBALS['sum_coveredmethods']);
$xml->writeAttribute('statements', $GLOBALS['sum_statements']);
$xml->writeAttribute('coveredstatements', $GLOBALS['sum_coveredstatements']);
$xml->writeAttribute('elements', $GLOBALS['sum_elements']);
$xml->writeAttribute('coveredelements', $GLOBALS['sum_coveredelements']);
$xml->endElement();
$xml->endElement();
$xml->endElement();
$xml->endDocument();
#$xml->flush();
header("Content-type: text/xml");
print($xml->outputMemory());
<?php
$coverage = apcu_fetch("coverage");
echo json_encode($coverage);
<?php
var_dump(apcu_cache_info(true));
var_dump(apcu_sma_info());
var_dump(memory_get_usage());
<?php
xdebug_start_code_coverage(1|2);
$GLOBALS["stored_coverage"] = array();
function my_print($msg)
{
#print($msg);
}
function my_print_r($var)
{
#print_r($var);
}
function merge_line_coverage($new_line_coverage, $key)
{
$old_line_coverage = &$GLOBALS["stored_file_coverage"];
if (array_key_exists($key, $old_line_coverage))
{
if ($old_line_coverage[$key] < $new_line_coverage)
{
$old_line_coverage[$key] = $new_line_coverage;
}
} else {
$old_line_coverage[$key] = $new_line_coverage;
}
}
function merge_file_coverage($new_file_coverage, $key)
{
$stored_coverage = &$GLOBALS["stored_coverage"];
if (array_key_exists($key, $stored_coverage))
{
$GLOBALS["stored_file_coverage"] = &$stored_coverage[$key];
array_walk($new_file_coverage, 'merge_line_coverage');
} else {
$stored_coverage[$key] = $new_file_coverage;
}
}
function shutdown ()
{
$previews_coverage = array();
apcu_add("coverage", $previews_coverage);
$previews_coverage = apcu_fetch("coverage");
# $previews_coverage = apcu_fetch("coverage");
# if ($previews_coverage == false)
# {
# my_print("\$previews_coverage = false\n");
# $previews_coverage = array();
# }
my_print("\n\npreviews_coverage:\n");
my_print_r($previews_coverage);
my_print("\n");
$GLOBALS["stored_coverage"] = $previews_coverage;
$coverage = xdebug_get_code_coverage();
my_print("\n\ncoverage:\n");
my_print_r($coverage);
my_print("\n");
array_walk($coverage, 'merge_file_coverage');
my_print("\n\nmerged_coverage:\n");
my_print_r($GLOBALS["stored_coverage"]);
my_print("\n");
# apcu_delete("coverage");
apcu_store("coverage", $GLOBALS["stored_coverage"]);
xdebug_stop_code_coverage();
}
register_shutdown_function('shutdown');
#!/usr/bin/env bash
dir=`dirname $0`
cp -r ${dir}/coverage /home/services/api.go2yd.com/
cp -r ${dir}/collect_coverage /home/services/api.go2yd.com/htdocs/Website/
echo "zend_extension=/usr/lib64/php/modules/xdebug.so" >> /etc/php.ini
echo "auto_prepend_file=/home/services/api.go2yd.com/coverage/StartRecordCoverage.php" >> /etc/php.ini
sed -i 's/php_admin_value\[memory_limit\].*$/php_admin_value[memory_limit] = 1024M/g' /etc/php-fpm.d/api.go2yd.com.conf
nohup sh ${dir}/call_all.sh &
#日志分割
59 23 * * * /usr/sbin/logrotate -f /etc/logrotate.conf
#ipip 更新数据字典
0 3 * * * /bin/bash /home/services/ipip/ipip.sh > /home/services/api.go2yd.com/logs/ipip.log
###################### Filebeat Configuration #########################
filebeat.inputs:
- type: log
paths:
- /home/services/api.go2yd.com/logs/fpm-error.log
fields:
log_type: 'fpm-error_log'
service_name: 'api.go2yd.com'
fields_under_root: false
- type: log
paths:
- /home/services/api.go2yd.com/logs/fpm-slow.log
multiline.pattern: '^$'
multiline.negate: true
multiline.match: after
fields:
log_type: 'fpm-slowlog'
service_name: 'api.go2yd.com'
fields_under_root: false
- type: log
paths:
- /home/services/api.go2yd.com/logs/php-error.log
multiline.pattern: '^\[\d{2}-'
multiline.negate: true
multiline.match: after
fields:
log_type: 'php-error_log'
service_name: 'api.go2yd.com'
fields_under_root: false
#- type: log
#
# paths:
# - /home/services/api.go2yd.com/logs/access.log
#
# fields:
# log_type: 'fpm-access_log'
# service_name: 'a1.go2yd.com'
# fields_under_root: false
#output.logstash:
#hosts: ["log.transfer.v.yidian-inc.com:5044"]
#hosts: ["10.126.154.124:5044"]
#hosts: ["172.29.60.5:5044"]
output.kafka:
enable: true
hosts: ["10.103.17.40:8091", "10.103.17.41:8091", "10.103.17.42:8091", "10.103.17.43:8091", "10.103.32.28:8091", "10.103.32.29:8091", "10.120.187.37:8091", "10.120.187.38:8091", "10.120.187.39:8091"]
topic: "%{[fields.log_type]}"
codec.format:
string: "%{[fields.service_name]}|${HOSTNAME} %{[message]}"
logging.level: warning
logging.to_files: true
logging.files:
path: /home/services/api.go2yd.com/logs
name: filebeat.log
rotateeverybytes: 52428800
keepfiles: 7
This diff is collapsed.
#!/bin/bash
cd /home/services/api.go2yd.com/htdocs/Website/data && wget http://10.103.17.28/ipip/ipdata_ipv6v4_2in1.ipdb.zip && unzip -o ipdata_ipv6v4_2in1.ipdb.zip && rm -f ipdata_ipv6v4_2in1.ipdb.zip && cd -
/home/services/api.go2yd.com/logs/*.log {
su root root
daily
dateext
rotate 7
missingok
notifempty
create 755 nobody nobody
postrotate
/bin/kill -SIGUSR1 `cat /var/run/php-fpm/php-fpm.pid 2>/dev/null` 2>/dev/null || true
endscript
}
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;
; All relative paths in this configuration file are relative to PHP's install
; prefix.
; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
include=/etc/php-fpm.d/*.conf
;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;
[global]
; Pid file
; Default Value: none
pid = /var/run/php-fpm/php-fpm.pid
; Error log file
; Default Value: /var/log/php-fpm.log
; error_log = syslog
; syslog.facility = local7
; syslog.ident = php-fpm
error_log = /home/services/api.go2yd.com/logs/fpm-error.log
; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
log_level = warning
; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0
; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated. This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval = 0
; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
process_control_timeout = 7
; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
daemonize = yes
;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;
; See /etc/php-fpm.d/*.conf
This diff is collapsed.
## protobuf
#### protobuf3 的定义文件在yaconf中统一管理
\ No newline at end of file
This diff is collapsed.
<?php
ini_set("display_errors", "On");
/* 定义这个常量是为了在application.ini中引用*/
define('ROOT_PATH', realpath(__DIR__.'/../'));
define('APP_PATH', realpath(__DIR__.'/../application'));
define('APP_START', microtime(true));
// 调试参数 __debug 的值
define('_DEBUG_PASS', 'debugpass'); // 为了避免调试信息泄漏,请定义自己的密钥
// 是否开启调试状态
define('_IS_DEBUG', true);
// 异常信息等级
define('_ERROR_LEVEL', E_ALL);
$application = new Yaf\Application( ROOT_PATH . "/conf/application.ini");
$application->bootstrap()->run();
<?php
echo "success";
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment