目录
数组根据某个字段进行排序
/**
* 数组根据某个字段进行排序
* @param Array $array 需要排序的数组
* @param String $keys 根据某个key排序
* @param String $sort 倒叙还是顺序
* @return Array
**/
function arraySort($array, $keys, $sort = 'asc')
{
$newArr = $valArr = array();
foreach ($array as $key => $value) {
$valArr[$key] = $value[$keys];
}
($sort == 'asc') ? asort($valArr) : arsort($valArr); //先利用keys对数组排序,目的是把目标数组的key排好序
reset($valArr); //指针指向数组第一个值
foreach ($valArr as $key => $value) {
$newArr[$key] = $array[$key];
}
return $newArr;
}
数组根据某字段进行分组
/**
* 数组根据某字段进行分组
* @param Array $dataArr 需要分组的数据
* @param String $keyStr 分组依据
* @return Array
*/
function dataGroup(array $dataArr, string $keyStr): array
{
$newArr = [];
foreach ($dataArr as $k => $val) { //数据根据日期分组
$newArr[$val[$keyStr]][] = $val;
}
return $newArr;
}
秒转时分秒
$s = 30;
$s = gmdate("H:i:s",$s);
/**
* 处理时间
*
* @param string $s 转化好的时间 00:00:30
* @return string $ftime 处理好的时间 XX时XX分XX秒
*/
public function ftime($s)
{
$time = explode(':', $s);
$time['0'] == '00' ? $h = 0 : $h = $time['0'];
$time['1'] == '00' ? $m = 0 : $m = $time['1'];
$time['2'] == '00' ? $s = 0 : $s = $time['2'];
$ftime = (
empty($h) ? (
empty($m) ? $s .'秒' : (
empty($s) ? $m . '分' : $m . '分' . $s .'秒'
)
) :(
empty($m) && empty($s) ? $h .'小时' : (
empty($m) ? $h . '时' . $s . '秒' : (
empty($s) ? $h . '小时' . $m . '分' : $h . '小时' . $m . '分' .$s . '秒'
)
)
)
);
return $ftime;
}
向文件写入内容
function logs($data, $separator = false, $prefix = "", $pathname = '')
{
$filename = date('Ymd') . ".log";
$path = FCPATH . 'logs/';
if (!empty($pathname)) {
$path .= $pathname . '/';
}
if (!file_exists($path)) {
mkdirs($path);
}
if (!empty($prefix)) {
$filename = $prefix . "_" . $filename;
}
$file = $path . $filename;
if (!file_exists($file)) {
touch($file);
chmod($file, 0777);
} elseif (0777 !== (fileperms($file) & 0777)) {
chmod($file, 0777);
}
if (is_array($data)) {
$data = var_export($data, true);
}
$str = "";
if ($separator) {
$str .= "\n---------------------------------------------------------------------------------\n";
}
$str .= date('Y-m-d H:i:s') . " " . $data . "\n";
file_put_contents($file, $str, FILE_APPEND);
}
/*
* 判断是否存在文件夹,不存在则创建
* $path 文件夹路径
*/
function mkdirs($path, $mode = 0777)
{
if (is_dir($path) || @mkdir($path, $mode)) {
return true;
}
if (!mkdirs(dirname($path), $mode)) {
return false;
}
return @mkdir($path, $mode);
}
function fwrite_file($content)
{
$file = "data.txt";
// $content = "内容标题\r\n内容第一行\r\n内容第二行";
//打开文件$file时,使用追加模式,此时文件指针会在文件开始出
if (!$fp = fopen($file, 'a')) {
return ['code' => 0, 'msg' => "打开文件" . $file . "失败!"];
exit;
}
if (fwrite($fp, $content) === FALSE) {
return ['code' => 0, 'msg' => "写入文件失败!"];
}
return ['code' => 1, 'msg' => "写入文件成功!"];
}
时间戳转天时分秒
// 时间戳转天时分秒
function secsToStr($secs)
{
$r = '';
if ($secs >= 86400) {
$days = floor($secs / 86400);
$secs = $secs % 86400;
$r = $days . ' day';
if ($days <> 1) {
$r .= 's';
}
if ($secs > 0) {
$r .= ', ';
}
}
if ($secs >= 3600) {
$hours = floor($secs / 3600);
$secs = $secs % 3600;
$r .= $hours . ' hour';
if ($hours <> 1) {
$r .= 's';
}
if ($secs > 0) {
$r .= ', ';
}
}
if ($secs >= 60) {
$minutes = floor($secs / 60);
$secs = $secs % 60;
$r .= $minutes . ' minute';
if ($minutes <> 1) {
$r .= 's';
}
if ($secs > 0) {
$r .= ', ';
}
}
$r .= $secs . ' second';
if ($secs <> 1) {
$r .= 's';
}
return $r;
}
无限级分类
/**
* @param $arr 数组
* @param $id id
* @param $level 层级
* @return array
*/
function demo($arr,$id,$level)
{
$list =array();
foreach ($arr as $k=>$v){
if ($v['pid'] == $id){
$v['level']=$level;
$v['son'] = demo($arr,$v['id'],$level+1);
$list[] = $v;
}
}
return $list;
}
/*
* 获取所有上级
* @param $id String 待查找的id
* @return String | NULL 失败返回null
*/
public function getSup($id,$n = 0)
{
$sql = "SELECT `pid` from `aaa` where `id` =" . $id;
$res = $this->db->getone($sql); //获取字段值,如15
if ($res) {
if($n){
$ids .= "," . $res;
}else{
$ids = $res;
}
$n++;
$ids .= $this->test($res,$n);
}
return $ids;
}
/*
* 获取所有下级
* @param $id String 待查找的id
* @return String | NULL 失败返回null
*/
public function getSub($id)
{
$isComma = strstr($id,',');
if($isComma){
$sql = "SELECT `id` from `aaa` where `pid` in (" . $id.")";
}else{
$sql = "SELECT `id` from `aaa` where `pid`=" . $id;
}
$res = $this->sql($sql); //获取二维数组,如Array ( [0] => Array ( [id] => 12 ) [1] => Array ( [id] => 13 ) )
if ($res) {
$id = '';
foreach ($res as $k=>$v) {
if($v['id']>0){
if($k == 0){
$id = $v['id'];
}else{
$id .= ','.$v['id'];
}
}
}
if($isComma){
$ids .= "," . $id;
}else{
$ids .= $id;
}
$ids .= $this->test2($id);
}
return $ids;
}
截取两个字符串之间的字符串
/**
* php截取指定两个字符之间字符串,默认字符集为utf-8
* @param string $begin 开始字符串
* @param string $end 结束字符串
* @param string $str 需要截取的字符串
* @return string
*/
function cut($begin,$end,$str){
$b = mb_strpos($str,$begin) + mb_strlen($begin);
$e = mb_strpos($str,$end) - $b;
return mb_substr($str,$b,$e);
}
/**
* php截取指定两个字符之间字符串
**/
function get_between($input, $start, $end) {
$substr = substr($input, strlen($start)+strpos($input, $start),(strlen($input) - strpos($input, $end))*(-1));
return $substr;
}
简洁打印
function pp(){
$params = func_get_args();
foreach($params as $k=>$v){
echo "<pre>";
print_r($v);
}
die;
}
获取26个英文字母
// 获取26个大写英文字母
function getTwentySixLetter()
{
$letter = array();
for($i=65;$i<91;$i++){
$letter[] = strtoupper(chr($i));
}
return $letter;
}
上传文件
/**
* 上传
*
* @Author KeerDi diwei@keerdi.com
* @DateTime 2021-04-14
* @param [type] $file
* @param string $filename
* @return void
*/
public function upload($file, $filename = '')
{
$filetemp = $file[$filename];
if (!(isset($filetemp['name']) && !empty($filetemp['name']))) throw new Exception('文件为空', 300);
if (empty($filename)) throw new Exception('文件名为空', 300);
$file_subdirectory = '/' . date('Ym') . '/';
$fileconfig['upload_path'] = '/uploads/img' . $file_subdirectory;
$fileconfig['allowed_types'] = 'gif|jpg||jpeg|png'; // 允许上传的文件类型
$this->load->library('upload', $fileconfig);
if (!is_dir($fileconfig['upload_path']) && !mkdir($fileconfig['upload_path'], 0777)) throw new Exception($fileconfig['upload_path'] . '不是目录,请重新尝试!');
if (!is_writable($fileconfig['upload_path']) && !chmod($fileconfig['upload_path'], 0777)) throw new Exception($fileconfig['upload_path'] . '加权限失败,请重新尝试!');
unset($_FILES[$filename]);
$_FILES[$filename]['name'] = $filetemp['name'];
$_FILES[$filename]['type'] = $filetemp['type'];
$_FILES[$filename]['tmp_name'] = $filetemp['tmp_name'];
$_FILES[$filename]['error'] = $filetemp['error'];
$_FILES[$filename]['size'] = $filetemp['size'];
if (!$this->upload->do_upload_ex($filename)) throw new Exception($this->upload->display_errors());
$upload_filedata = $this->upload->data();
$file_dir = $file_subdirectory . $upload_filedata['file_name'];
return $file_dir;
}
/*文件上传*/
public function upload()
{
$imgpath = '/uploads/img/' . date("Ymd") . '/';
$path = getcwd().$imgpath;
$pathret = mkdirs($path);
$config['upload_path'] = $path;
$config['allowed_types'] = '*';
$config['file_name'] = date('Ymd') . uniqid();
$this->load->helper('form', 'url');
$this->load->library('upload', $config);
$this->upload->initialize($config);
$filearr = $_FILES;
foreach ($filearr as $k => $v) {
if ($v['error'] == 0) {
if ($this->upload->do_upload($k)) {
$file = $this->upload->data();
$data = 'http://' . $_SERVER['SERVER_NAME'] . $imgpath. $file['file_name'];
} else {
$msg = $this->upload->display_errors();
Response(500, $msg);
return false;
}
}
}
Response(200, '上传成功', $data);
}
数组按值长度,大小排序
function lensort($a, $b)
{
$la = strlen($a);
$lb = strlen($b);
if ($la == $lb) {
return strcmp($a, $b);
}
return $la - $lb;
}
获取当前文件域名访问路径
function refer(){
return $_SERVER["REQUEST_SCHEME"]."://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
获取指定日期段内每一天的日期
/**
* 获取指定日期段内每一天的日期
* @param Date $startdate 开始日期
* @param Date $enddate 结束日期
* @return Array
*/
function getDateFromRange($start_date, $end_date){
$stimestamp = strtotime($start_date);
$etimestamp = strtotime($end_date);
// 计算日期段内有多少天
$days = ($etimestamp-$stimestamp)/86400+1;
// 保存每天日期
$date = array();
for($i=0; $i<$days; $i++){
$date[] = date('Y-m-d', $stimestamp+(86400*$i));
}
return $date;
}
获取指定日期段内每个月的日期
/**
* 获取指定日期段内每个月的日期
* @param Date $startdate 开始日期
* @param Date $enddate 结束日期
* @return Array
*/
function getMonthsInRange($startDate, $endDate)
{
$start = new DateTime($startDate);
$end = new DateTime($endDate);
$months = array();
while ($start <= $end) {
$months[] = $start->format('Y-m');
$start->modify('first day of next month');
}
return $months;
}
获取一天内间隔5分钟的时间
// 获取一天内间隔5分钟的时间
function GetInterval5Minutes(){
$min = 0;
while($min < 60){
if($min < 10) $min = '0'.$min;
$minutes[] = $min;
$min += 5;
}
$hour = 0;
while($hour < 24){
if($hour < 10) $hour = '0'.$hour;
$hours[] = $hour;
$hour += 1;
}
$time = [];
foreach($hours as $h){
foreach($minutes as $m){
$time[] = $h.':'.$m.':00';
}
}
return $time;
}
比较数组去除相同值
function CallCompare($arr1, $arr2)
{
foreach ($arr2 as $v2) {
$arr1 = removeValue($arr1, $v2);
}
return $arr1;
}
function removeValue($arr, $value)
{
foreach ($arr as $k => $v) {
if ($v == $value) {
unset($arr[$k]);
return $arr;
}
}
return $arr;
}
//示例
$arr1 = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3];
$arr2 = [1, 1, 3];
$arr = CallCompare($arr1, $arr2);
print_r($arr);
// 输出
Array
(
[2] => 1
[3] => 1
[4] => 2
[5] => 2
[6] => 2
[7] => 2
[9] => 3
[10] => 3
[11] => 3
)
工作项目
-
库位排序
需求:为了工作人员方便取货,对仓库中的库位进行排序
说明:
仓库如下图所示,分别从大到小按【区,排位,货架,层,列 】进行排序
/** * 库位排序 */ public function stockSort() { // 排位排序 $line_sort = $this->db->select('a.*,GROUP_CONCAT(a.line_code) as line_codes,b.zone_name') ->order_by('b.sort') ->group_by('a.zone_id,a.sort') ->join('epcoa_pos_zone b', 'b.id = a.zone_id', 'left') ->get('epcoa_pos_line_sort a') ->result_array(); $line_arr = array(); $line_arr2 = array(); foreach ($line_sort as $v) { $line_arr[$v['zone_name']][$v['line_codes']]['line_sort'] = $v['sort']; $line_arr[$v['zone_name']][$v['line_codes']]['line_direction'] = $v['direction']; $line_arr2[$v['line_codes']] = $v['sort']; } // 列表 $list = $this->db->select('a.stock_position_code,b.zone_name') ->order_by('b.sort') ->join('epcoa_pos_zone b', 'b.id = a.zone_id', 'left') ->get('epcoa_pos_position a') ->result_array(); $list_arr = array(); foreach ($list as $v) { $stock_code = explode('-', $v['stock_position_code']); $flag = false; foreach ($line_arr as $zone_key => $zone_value) { foreach ($zone_value as $line_key => $line_value) { if (strpos($line_key, $stock_code[0]) !== false) { $list_arr[$zone_key][$line_key][$stock_code[0]][$stock_code[1]][$stock_code[2]][] = $v['stock_position_code']; $flag = true; break; } } } if ($flag) continue; $list_arr[$v['zone_name']][$stock_code[0]][$stock_code[0]][$stock_code[1]][$stock_code[2]][] = $v['stock_position_code']; } // 货架和列按配置排序;排位和层升序 foreach ($list_arr as $k1 => $v1) { //区 foreach ($v1 as $k2 => $v2) { //排位 ksort($list_arr[$k1][$k2]); foreach ($v2 as $k3 => $v3) { //货架 $line_direction = isset($line_arr[$k1][$k2]) ? $line_arr[$k1][$k2]['line_direction'] : 0; if ($line_direction) { krsort($list_arr[$k1][$k2][$k3]); } else { ksort($list_arr[$k1][$k2][$k3]); } foreach ($v3 as $k4 => $v4) { // 层 krsort($list_arr[$k1][$k2][$k3][$k4]); foreach ($v4 as $k5 => $v5) { // 列 if ($line_direction) { rsort($list_arr[$k1][$k2][$k3][$k4][$k5]); } else { sort($list_arr[$k1][$k2][$k3][$k4][$k5]); } } } } } } // 排位按配置排序 $list_arr2 = array(); foreach ($list_arr as $k1 => $v1) { foreach ($v1 as $k2 => $v2) { $list_arr2[$k2] = $v2; } } $list_arr = array_replace($line_arr2, $list_arr2); // 相同排序的货架放在一起 $list_arr3 = array(); foreach ($list_arr as $k => $v) { if(strpos($k,',')){ $line_code = explode(',',$k); $list1 = $list_arr[$k][$line_code[0]]; $list2 = $list_arr[$k][$line_code[1]]; foreach($list1 as $k2=>$v2){ $list_arr3[$k][$line_code[0].'-'.$k2] = $v2; if(isset($list2[$k2])){ $list_arr3[$k][$line_code[1].'-'.$k2] = $list2[$k2]; } } foreach($list2 as $k2=>$v2){ $list_arr3[$k][$line_code[1].'-'.$k2] = $v2; if(isset($list1[$k2])){ $list_arr3[$k][$line_code[0].'-'.$k2] = $list1[$k2]; } } }else{ $list_arr3[$k] = $v; } } $list_arr = $this->arr_foreach($list_arr3); $upDate= array(); foreach($list_arr as $k=>$v){ $upDate[$k]['stock_position_code'] = $v; $upDate[$k]['sort'] = $k; } $this->db->update_batch('epcoa_pos_position',$upDate,'stock_position_code'); } // 多维数组转一维数组 function arr_foreach($arr) { static $tmp = array(); if (!is_array($arr)) { return false; } foreach ($arr as $val) { if (is_array($val)) { $this->arr_foreach($val); } else { $tmp[] = $val; } } return $tmp; }
-
打合首算法查重
需求:统计指定一天时间内,相同的两个人在不同房间游戏超过5次的个数,防止作弊
问题:数据库两张表的数据已过亿,查询出来的数据约有十几万,有内存溢出,超时执行的问题
方法:数据库查询使用了非缓冲查询,数组循环结束使用unset,减少内存溢出问题// 打合首算法查重 function same_room() { ini_set('memory_limit', -1);// 不限内存 ini_set('max_execution_time', 0);//不限时间 set_time_limit(0); $date = isset($_REQUEST['date']) && !empty($_REQUEST['date']) ? $_REQUEST['date'] : date('Y-m-d', strtotime("-1 day")); $ts_begin = strtotime($date . " 00:00:00"); $ts_end = strtotime($date . " 23:59:59"); $sql = "SELECT a.log_id,a.create_uid,a.room_id,b.uid FROM gold_room_log a JOIN gold_room_user_log b ON a.log_id = b.log_id left join `user` u ON b.uid = u.uid WHERE 1 = 1 AND a.create_time >= {$ts_begin} AND a.create_time <= {$ts_end} AND channel !='nn_robot' "; // $list = $this->game->query($sql)->result_array(); // pdo_mysql非缓冲查询 mysqL_unbuffered_query 减少内存 $pdo = new PDO("mysql:host=127.0.0.1;dbname=db", 'root', 'password'); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $uresult = $pdo->query($sql); // 按房间分组 $data = []; if ($uresult) { while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) { if (empty($row['uid'])) { continue; } if (!in_array($row['create_uid'], $data[$row['log_id']])) { $data[$row['log_id']][] = $row['create_uid']; } if (!in_array($row['uid'], $data[$row['log_id']])) { $data[$row['log_id']][] = $row['uid']; } } } if (empty($data)) { Response(500, '无数据'); } // 同房间两两组合 $item = []; foreach ($data as $k => $v) { if (empty($v)) { continue; } $arr = getCombine($v, 2); foreach ($arr as $k1 => $v1) { $item[$k][] = $v1; } } unset($data);// 减少内存 // 不同房间两两比较 $data = []; $item = array_values($item); $len = count($item); for ($i = 0; $i < $len; $i++) { $item[$i] = array_values($item[$i]); for ($n = 0; $n < count($item[$i]); $n++) { if (count($item[$i][$n]) < 2) { continue; } $n1 = $item[$i][$n][0]; $n2 = $item[$i][$n][1]; if ($n1 < $n2) { $k = $n1 . '-' . $n2; } else { $k = $n2 . '-' . $n1; } if (!isset($data[$k])) { $data[$k] = 1; } else { $data[$k]++; } } unset($item[$i]); } foreach ($data as $k => $v) { if ($v < 5) { unset($data[$k]); } } ksort($data); Response(200, 'ok', count($data)); } // 全排列算法 function getCombine($nArr, $k) { $ret = []; if ($k == 0) //递归终止 { return []; } if ($k == 1) { //递归终止 foreach ($nArr as $item) { $ret[] = [$item]; } return $ret; } foreach ($nArr as $key => $v) { if (sizeof($nArr) < $k) //注意剪枝操作 { break; } unset($nArr[$key]); $res = getCombine($nArr, $k - 1); //递归 foreach ($res as $vv) { //处理返回结果 array_unshift($vv, $v); $ret[] = $vv; } } return $ret; }
示例
// 原数组 $data = [ ['log_id' => 1, 'create_uid' => 100, 'room_id' => 1000, 'uid' => 102], ['log_id' => 1, 'create_uid' => 100, 'room_id' => 1000, 'uid' => 103], ['log_id' => 1, 'create_uid' => 100, 'room_id' => 1000, 'uid' => 101], ['log_id' => 2, 'create_uid' => 101, 'room_id' => 1001, 'uid' => 102], ['log_id' => 2, 'create_uid' => 101, 'room_id' => 1001, 'uid' => 103], ['log_id' => 2, 'create_uid' => 101, 'room_id' => 1001, 'uid' => 104], ['log_id' => 3, 'create_uid' => 102, 'room_id' => 1002, 'uid' => 101], ['log_id' => 3, 'create_uid' => 102, 'room_id' => 1002, 'uid' => 103], ['log_id' => 3, 'create_uid' => 102, 'room_id' => 1002, 'uid' => 109], ['log_id' => 4, 'create_uid' => 103, 'room_id' => 1003, 'uid' => 101], ['log_id' => 4, 'create_uid' => 103, 'room_id' => 1003, 'uid' => 109], ['log_id' => 4, 'create_uid' => 103, 'room_id' => 1003, 'uid' => 112], ['log_id' => 5, 'create_uid' => 104, 'room_id' => 1004, 'uid' => 113], ['log_id' => 5, 'create_uid' => 104, 'room_id' => 1004, 'uid' => 114], ['log_id' => 5, 'create_uid' => 104, 'room_id' => 1004, 'uid' => 115], ['log_id' => 6, 'create_uid' => 105, 'room_id' => 1005, 'uid' => 113], ['log_id' => 6, 'create_uid' => 105, 'room_id' => 1005, 'uid' => 114], ['log_id' => 6, 'create_uid' => 105, 'room_id' => 1005, 'uid' => 116], ['log_id' => 7, 'create_uid' => 106, 'room_id' => 1006, 'uid' => 101], ['log_id' => 7, 'create_uid' => 106, 'room_id' => 1006, 'uid' => 102], ]; // 执行结果 data:{"100-101":1,"100-102":1,"100-103":1,"101-102":4,"101-103":4,"101-104":1,"101-106":1,"101-109":2,"101-112":1,"102-103":3,"102-104":1,"102-106":1,"102-109":1,"103-104":1,"103-109":2,"103-112":1,"104-113":1,"104-114":1,"104-115":1,"105-113":1,"105-114":1,"105-116":1,"109-112":1,"113-114":2,"113-115":1,"113-116":1,"114-115":1,"114-116":1}
get post请求
function curl_post($url, $params, $timeout = 5000) { $header = ['Content-Type: application/x-www-form-urlencoded']; if($url == "" || $timeout <= 0) { return false; } if(is_array($params)) { $params = http_build_query($params);//重点 } logs($url); logs($params); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0);//不抓取头部信息。只返回数据 curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout);//超时设置 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//1表示不返回bool值 curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $header);//重点 curl_setopt($ch, CURLOPT_POSTFIELDS, $params); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//规避SSL验证 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//跳过HOST验证 $result = curl_exec($ch); logs($result); if (curl_errno($ch)) { return curl_error($ch); } curl_close($ch); return $result; } function curl_get($url) { if($url == "") { return false; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 3); curl_setopt($ch, CURLOPT_HEADER, 0); $result = curl_exec($ch); logs($result); if (curl_errno($ch)) { return curl_error($ch); } curl_close($ch); return $result; }
socket
public function send($cmd, $params = null) { logs(refer(), true); $this->config->load("cmd"); $server = $this->config->item("Server"); $host = $params['ip'] ?: $server["ip"]; $port = $params['port'] ?: $server["port"]; $key = $params['key'] ?: $server["key"]; $cfg = $this->config->item($cmd); $prefix = $cfg["prefix"]; logs($host . ":" . $port . " " . $key . " " . $cmd . " " . $prefix); $params = array_merge($cfg["params"], $params); $params['account'] = "admin"; logs($params); $buf = $this->write($host, $port, $key, $prefix, $params); if (empty($buf)) { return false; } logs($buf); $ret = $this->parse($buf); return $ret; } private function parse($buf) { $pattern = '/\{(?:[^{}]|(?R))*\}/x'; preg_match_all($pattern, $buf, $matches); if (empty($matches)) { return false; } $matches = $matches[0]; if (is_array($matches)) { $matches = $matches[0]; } $result = json_decode($matches, true); logs($result); return $result; } /*SOCKET*/ private function write($ip, $port, $key, $prefix, $params) { $str = ''; ksort($params); foreach ($params as $k => $v) { $str .= $v; } $str .= $key; $params['sign'] = md5($str); $data = $prefix . json_encode($params); $bin = pack("na" . strlen($data), strlen($data), $data); logs($bin); $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // if (!is_resource($sock)) { // logs(socket_last_error() . ":" . socket_strerror(socket_last_error())); // return false; // } // logs("socket_create: " . $sock); $bool = socket_connect($sock, $ip, $port); if ($bool === false) { logs(socket_last_error() . ":" . socket_strerror(socket_last_error())); return false; } logs("socket_connnet: " . $bool); $result = socket_write($sock, $bin, strlen($bin)); if ($result === false) { logs(socket_last_error() . ":" . socket_strerror(socket_last_error())); return false; } logs("socket_write: " . $result); //TODO 阻塞进程 非127.0.0.1 $buf = false; // 循环读取大量数据 while($resp = socket_read($sock, 2048, PHP_BINARY_READ)) { // 使用系统的 recv() 函数 二进制安全地读取数据 $buf .= $resp; if (strpos($buf, "\n") !== false) { break; } } if ($buf === false) { logs(socket_last_error() . ":" . socket_strerror(socket_last_error())); return false; } logs("socket_read: " . $buf); socket_close($sock); return trim($buf); }