常用助手函式

三餐四季發表於2023-03-14
[TOC]

CURL 後端訪問介面

* $method引數可以指定請求方式 get 或post
* $url引數可以指定要請求的地址
* $param為設定的get或者post的引數
* $timeout設定為1為非同步請求,設定數值稍大則可以視為同步請求
function curl_common($method='get', $url = '', $param = [], $header = [], $timeout =1)
{
    $curl = curl_init(); //初始化curl
    curl_setopt($curl, CURLOPT_URL, $url); //抓取指定網頁
    curl_setopt($curl, CURLOPT_HEADER, 0); //設定header
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //要求結果為字串且輸出到螢幕上
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);       //設定頭部
    curl_setopt($curl, CURLOPT_HEADER, 0);                 //返回頭部資訊

    if('get' ==$method){
       $url .= '?'.http_build_query($param);
    }else{
        curl_setopt($curl, CURLOPT_POST, 1); //post提交方式
        curl_setopt($curl, CURLOPT_POSTFIELDS, $param); //post提交資料
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //繞過ssl協議
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    }

    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); //設定超時時間
    $data = curl_exec($curl); //執行curl
    curl_close($curl);

    return $data;

}

人性化顯示某時間距離當前已經過去多久

//$sTime int  時間戳
function formatTime($sTime, $formt = 'Y-m-d')
{
    if (!$sTime) {
        return '';
    }

    //sTime=源時間,cTime=當前時間,dTime=時間差
    $cTime = $_SERVER['REQUEST_TIME'];
    $dTime = $cTime - $sTime;
    $dDay = intval(date('z', $cTime)) - intval(date('z', $sTime));
    $dYear = intval(date('Y', $cTime)) - intval(date('Y', $sTime));

    //n秒前,n分鐘前,n小時前,日期
    if ($dTime < 60) {
        if ($dTime < 10) {
            return '剛剛';
        } else {
            return intval(floor($dTime / 10) * 10).'秒前';
        }
    } elseif ($dTime < 3600) {
        return intval($dTime / 60).'分鐘前';
    } elseif ($dYear == 0 && $dTime >= 3600 && $dDay == 0) {
        return intval($dTime / 3600).'小時前';
    } elseif ($dYear == 0 && $dDay > 0 && $dDay <= 7) {
        return intval($dDay).'天前';
    } elseif ($dYear == 0 && $dDay > 7 && $dDay <= 30) {
        return intval($dDay / 7).'周前';
    } elseif ($dYear == 0 && $dDay > 30) {
        return intval($dDay / 30).'個月前';
    } elseif ($dYear == 0) {
        return date('m月d日', $sTime);
    } else {
        return date($formt, $sTime);
    }
}

獲取客戶端裝置型別(Windows、Mac、ihpone、Android、Linux等)

function getClientOsInfo()
{
    @$agent = $_SERVER['HTTP_USER_AGENT'];
    $os = false;
    if (preg_match('/win/i', $agent) && strpos($agent, '95')) {
        $os = 'Windows 95';
    } elseif (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90')) {
        $os = 'Windows ME';
    } elseif (preg_match('/win/i', $agent) && preg_match('/98/i', $agent)) {
        $os = 'Windows 98';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent)) {
        $os = 'Windows Vista';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent)) {
        $os = 'Windows 7';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent)) {
        $os = 'Windows 8';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent)) {
        $os = 'Windows 10';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent)) {
        $os = 'Windows XP';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent)) {
        $os = 'Windows 2000';
    } elseif (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent)) {
        $os = 'Windows NT';
    } elseif (preg_match('/win/i', $agent) && preg_match('/32/i', $agent)) {
        $os = 'Windows 32';
    } elseif (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'SunOS';
    } elseif (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent)) {
        $os = 'IBM OS/2';
    } elseif (preg_match('/Mac/i', $agent) && preg_match('/PC/i', $agent)) {
        $os = 'Mac';
    } elseif (preg_match('/PowerPC/i', $agent)) {
        $os = 'PowerPC';
    } elseif (preg_match('/AIX/i', $agent)) {
        $os = 'AIX';
    } elseif (preg_match('/HPUX/i', $agent)) {
        $os = 'HPUX';
    } elseif (preg_match('/NetBSD/i', $agent)) {
        $os = 'NetBSD';
    } elseif (preg_match('/BSD/i', $agent)) {
        $os = 'BSD';
    } elseif (preg_match('/OSF1/i', $agent)) {
        $os = 'OSF1';
    } elseif (preg_match('/IRIX/i', $agent)) {
        $os = 'IRIX';
    } elseif (preg_match('/FreeBSD/i', $agent)) {
        $os = 'FreeBSD';
    } elseif (preg_match('/teleport/i', $agent)) {
        $os = 'teleport';
    } elseif (preg_match('/flashget/i', $agent)) {
        $os = 'flashget';
    } elseif (preg_match('/webzip/i', $agent)) {
        $os = 'webzip';
    } elseif (preg_match('/offline/i', $agent)) {
        $os = 'offline';
    } elseif (preg_match('/ipod/i', $agent)) {
        $os = 'ipod';
    } elseif (preg_match('/ipad/i', $agent)) {
        $os = 'ipad';
    } elseif (preg_match('/iphone/i', $agent)) {
        $os = 'iphone';
    } elseif (preg_match('/android/i', $agent)) {
        $os = 'Android';
    } elseif (preg_match('/linux/i', $agent)) {
        $os = 'Linux';
    } elseif (preg_match('/unix/i', $agent)) {
        $os = 'Unix';
    } else {
        $os = '未知作業系統';
    }
    return $os;
}

檔案批次重新命名程式

function resetname()
{
    $dir1 = './aaa/';//讀取資料夾名稱
    $dir2 = './aaa1/';//移動到資料夾名稱
    $filearr = scandir($dir1);//讀取資料夾
    unset($filearr[0]);//去除多餘的元素
    unset($filearr[1]);
    $filearr = array_values($filearr);//使陣列從0開始,以1遞增
    $filecount = count($filearr);//檔案數量
    $onenum = 1;//起始編號
    $maxnum = $onenum + $filecount;//最大迴圈次數
    $title = '';//'隋唐演義';//檔案標題
    $houzhui = '.jpg';//檔案字尾
    for ($i = $onenum; $i <= $maxnum; $i++) {
        for ($j=0; $j < $filecount ; $j++) {
            $filename = $title.$i.$houzhui;
            rename($dir1.$filearr[$j],$dir2.iconv("utf-8","gb2312",$filename));//設定字符集
            $i++;
        }
    }
       return 'ok';
}

統一構造的失敗或成功的JSON響應

function success($data, $msg = null)
{
    return json_encode(
        [
        'status' => 1,
        'msg' => $msg ?? '請求成功',
        'data' => $data,
        ]
    );
}

function fail($msg = '請求失敗')
{
    return json_encode(
        [
        'status' => 0,
        'msg' => $msg,
        ]
    );
}

自定義陣列過濾

  • 可以自定義一個回撥方法,返回 true或false 來決定是否過濾
array_filter($data,'filtrArr');
function filtrArr($arr)
{
    if($arr === '' || $arr === null){
            return false;
        }
        return true;
}

檔案上傳到本地

use Illuminate\Support\Facades\Storage;
function upload($request)
{
    $images = $request->file();

    $image = '';
    foreach ($images as $key => $value) {
        $image = $value;
    }

    $channel = 'public';
    $path = Storage::putFile($channel, $image);
    if ($path) {
        $url = env('APP_URL').Storage::url($path);
        return $url; //檔案路徑
    } else {
        return fail('上傳失敗');
    }
}

資產的操作(金幣/積分等平臺幣的處理)

  • 對於資產的操作一般比較敏感,所以最好有一個健全的易維護的統一的處理機制
  • 還需要考慮交易過程中的安全問題,所以交易是一個很複雜的過程,必須封裝,以免不小心出現錯誤
function sumPoint($uid, $num, $note)
{
    $exists = DB::table('users')->where('id', $uid)->exists();
    if (!$exists || $num<0) {
        return false;
    }
    try {
        DB::transaction(function () use ($uid, $num, $note) {
            $latest = bcsub($origin,$num,2);
            $origin =  DB::table('users')->where('id', $uid)->value('point');
            DB::table('users')->where('id', $uid)->update([
            'point'=> bcadd($origin, $num, 2)]);
            DB::table('financial_logs')->insert([
                'user_id' => $uid,
                'type' => 1,//1=收入 2=支出
                'num' => $num,
                'latest' => bcadd($origin, $num, 2),
                'note' => $note,
            ]);
        }, 5);
        return true;
    }catch(Exception $e) {
        return false;
    }
    return true;
}
function subPoint($uid, $num, $note)
{
    $exists = DB::table('users')->where('id', $uid)->exists();
    if (!$exists || $num>0) {
        return false;
    }
    $asset = 'point';
    $origin =  DB::table('users')->where('id', $uid)->value($asset);
    if ($origin < $num) {
        return false;
    }
    try {
        DB::transaction(function () use ($uid, $num, $note) {
            $latest = bcsub($origin,$num,2);
            $origin =  DB::table('users')->where('id', $uid)->value('point');
            DB::table('users')->where('id', $uid)->update([
            'point'=> $latest]);
            DB::table('financial_logs')->insert([
                'user_id' => $uid,
                'type' => 2,//1=收入 2=支出
                'num' => $num,
                'latest' => $latest,
                'note' => $note,
            ]);
        }, 5);
        return true;
    }catch(Exception $e) {
        return false;
    }
    return true;
}

獲取使用者的IP地址

function get_ip()
{
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $realip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }

    return $realip;
}

計算兩點地理座標之間的距離.

/**
 * 計算兩點地理座標之間的距離.
 *
 * @param Decimal $longitude1 起點經度
 * @param Decimal $latitude1  起點緯度
 * @param Decimal $longitude2 終點經度
 * @param Decimal $latitude2  終點緯度
 * @param int     $unit       單位 1:米 2:公里
 * @param int     $decimal    精度 保留小數位數
 *
 * @return Decimal
 */
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit = 1, $decimal = 2)
{
    $EARTH_RADIUS = 6370.996; // 地球半徑係數
    $PI = 3.1415926;

    $radLat1 = $latitude1 * $PI / 180.0;
    $radLat2 = $latitude2 * $PI / 180.0;

    $radLng1 = $longitude1 * $PI / 180.0;
    $radLng2 = $longitude2 * $PI / 180.0;

    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;

    $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
    $distance = $distance * $EARTH_RADIUS * 1000;

    if ($unit == 2) {
        $distance = $distance / 1000;
    }

    return round($distance, $decimal);
}

基於GEOHASH附近的人功能實現

  • GEOHASH 可以將一個地址對映成為一個字串,透過比較字串的相似度,確定兩個座標的大概距離
  • //1=5000km;2=1000km;3=100km 4=40km 5=5km 6=1km 7=100m 8=50m 9=5m 10=1m 11=10cm 12=5cm
  • 已知自身座標位置,可以去找附近範圍的人,也可以比較自己與附近人的範圍
function getgeohash($longitude, $latitude)
{
    return  GeoHash::encode($longitude, $latitude);
}

function compareGeohash($geohash1, $geohash2)
{
    $map  = [
        '0' => '>5000km 距離過遠',
        '1' => '<5000km 距離過遠',
        '2' => '<1000km 距離過遠',
        '3' => '<100km 不建議步行',
        '4' => '<40km 不建議步行',
        '5' => '<5km 20分鐘',
        '6' => '<1km 10分鐘',
        '7' => '<500m 5分鐘',
        '8' => '<50m 1分鐘',
        '9' => '<5m 1分鐘',
        '10' => '<1m 1分鐘',
    ];

    $len  = 10;
    for ($i=$len;$i>0;$i--) {
          $key1 =  substr($geohash1, 0, $i);
          $key2 =  substr($geohash2, 0, $i);
        if ($key1 == $key2) {
            return $map[$i];
        }
    }

    return '系統故障,無法測算';
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章