首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 常用工具函數大全 (第一輯·上):IP 獲取、日期運算、星期判斷、日期驗證、時間差計算、HTML 解析、瀏覽器與作業系統偵測

     編輯:PHP 綜合知識

前言

收集自各大 PHP 專案的實戰工具函數,涵蓋網路、日期、HTML、用戶代理偵測等高頻領域。本文為上集,包含 7 大類函數,附參數詳解、邏輯分析與現代化改良。

一、獲取客戶端 IP (多層代理相容)

function GetIP(): string {
    $ipKeys = [
        'HTTP_X_FORWARDED_FOR',  // 標準代理標頭 (可能多 IP)
        'HTTP_CLIENT_IP',        // 部分代理使用
        'REMOTE_ADDR',           // 直接連線或最後一層代理
    ];
    
    foreach ($ipKeys as $key) {
        $val = $_SERVER[$key] ?? '';
        if ($val) {
            $ips = array_map('trim', explode(',', $val));
            foreach ($ips as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
            return $ips[0]; // 全為私有 IP 時取第一個
        }
    }
    
    // 相容 getenv (CGI 模式)
    $envKeys = ['HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
    foreach ($envKeys as $key) {
        $val = getenv($key);
        if ($val) return $val;
    }
    
    return 'Unknown';
}

二、日期加減運算 (DateAdd)

function DateAdd(string $date, int $interval, string $unit = 'd'): string {
    // 支援單位: y(年), m(月), d(日), h(時), i(分), s(秒)
    $units = ['y'=>'year', 'm'=>'month', 'd'=>'day', 'h'=>'hour', 'i'=>'minute', 's'=>'second'];
    $unit = $units[$unit] ?? 'day';
    
    $dt = new DateTime($date);
    $intervalStr = ($interval >= 0 ? '+' : '') . abs($interval) . " {$unit}";
    $dt->modify($intervalStr);
    return $dt->format('Y-m-d'); // 或依需求回傳完整格式
}

// 範例
DateAdd('2024-01-15', 10, 'd');  // 2024-01-25
DateAdd('2024-01-15', 1, 'm');   // 2024-02-15 (自動處理月末)
DateAdd('2024-01-15', -3, 'd');  // 2024-01-12

// 簡化版 (僅支援日)
function DateAddSimple(string $date, int $days): string {
    return date('Y-m-d', strtotime($date . " {$days} days"));
}

三、計算星期幾 (GetWeekDay)

function GetWeekDay(string $date): int {
    // 回傳 0(日) - 6(六)
    return (int)date('w', strtotime($date));
}

// 中文星期名
function GetWeekDayName(string $date, string $lang = 'zh'): string {
    $names = [
        'zh' => ['日','一','二','三','四','五','六'],
        'en' => ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
    ];
    $w = GetWeekDay($date);
    return $names[$lang][$w] ?? $names['zh'][$w];
}

// 範例
GetWeekDay('2024-01-15'); // 1 (週一)
GetWeekDayName('2024-01-15'); // "一"

四、日期/時間合法性驗證

function check_date(string $date): bool {
    $parts = explode('-', $date);
    if (count($parts) !== 3) return false;
    [$y, $m, $d] = $parts;
    if (!ctype_digit($y) || !ctype_digit($m) || !ctype_digit($d)) return false;
    return checkdate((int)$m, (int)$d, (int)$y);
}

function check_time(string $time): bool {
    $parts = explode(':', $time);
    if (count($parts) !== 3) return false;
    [$h, $m, $s] = $parts;
    if (!ctype_digit($h) || !ctype_digit($m) || !ctype_digit($s)) return false;
    return $h >= 0 && $h <= 23 && $m >= 0 && $m <= 59 && $s >= 0 && $s <= 59;
}

function check_datetime(string $datetime): bool {
    $parts = explode(' ', $datetime);
    if (count($parts) !== 2) return false;
    return check_date($parts[0]) && check_time($parts[1]);
}

// 現代版:DateTime 例外處理
function checkDateModern(string $date, string $format = 'Y-m-d'): bool {
    $dt = DateTime::createFromFormat($format, $date);
    return $dt !== false && $dt->format($format) === $date;
}

五、時間差計算 (DateDiff)

function DateDiff(string $date1, string $date2, string $unit = 'd'): float|false {
    $units = [
        's' => 1,
        'i' => 60,
        'h' => 3600,
        'd' => 86400,
        'w' => 604800,
        'm' => 2629746, // 近似月秒數
        'y' => 31556952, // 近似年秒數
    ];
    $divisor = $units[$unit] ?? $units['d'];
    
    $t1 = strtotime($date1);
    $t2 = strtotime($date2);
    if ($t1 === false || $t2 === false) return false;
    
    return ($t1 - $t2) / $divisor;
}

// 範例
DateDiff('2024-01-20', '2024-01-15', 'd'); // 5 天
DateDiff('2024-01-15 12:00', '2024-01-15 10:00', 'h'); // 2 小時
DateDiff('2024-01-15 10:00', '2024-01-15 12:00', 'i'); // -120 分鐘 (date1 - date2)

// 精確版:DateInterval (支援月/年真實長度)
function DateDiffExact(string $date1, string $date2): DateInterval {
    $dt1 = new DateTime($date1);
    $dt2 = new DateTime($date2);
    return $dt1->diff($dt2); // 可取 ->y, ->m, ->d, ->h, ->i, ->s
}

// 使用
$diff = DateDiffExact('2024-01-20', '2024-01-15');
echo $diff->days; // 5
$diff = DateDiffExact('2024-03-01', '2024-01-15');
echo "{$diff->y}年{$diff->m}月{$diff->d}天"; // 0年1月16天

六、HTML 內容解析工具

獲取標籤內文 (get_innerhtml)

function get_innerhtml(string $html, string $tag): array {
    // 分割 
    $parts = preg_split("/<\/{$tag}>/i", $html);
    $pattern = "/<{$tag}[^>]*>/i";
    $results = [];
    foreach ($parts as $part) {
        list(, $inner) = preg_split($pattern, $part, 2);
        $results[] = $inner ?? '';
    }
    return $results;
}

// 範例
$html = 'something';
print_r(get_innerhtml($html, 'td')); // ['something']

// 現代 DOM 版
function getInnerHtmlDom(string $html, string $tag): array {
    $dom = new DOMDocument();
    @$dom->loadHTML('' . $html);
    $results = [];
    foreach ($dom->getElementsByTagName($tag) as $el) {
        $results[] = $el->ownerDocument->saveHTML($el); // 含標籤
        // 或 $el->textContent 純文字
    }
    return $results;
}

提取 input value 值

function get_input_value(string $inputHtml): string|false {
    $pos = stripos($inputHtml, 'value=');
    if ($pos === false) return false;
    $pos += 6; // 跳過 'value='
    $str = substr($inputHtml, $pos);
    if ($str[0] === '"' || $str[0] === "'") {
        $quote = $str[0];
        $end = strpos($str, $quote, 1);
        return $end !== false ? substr($str, 1, $end - 1) : false;
    }
    $end = strpos($str, ' ');
    return $end !== false ? substr($str, 0, $end) : $str;
}

// 現代 DOM 版
function getInputValueDom(string $html): string|false {
    $dom = new DOMDocument();
    @$dom->loadHTML('' . $html);
    $input = $dom->getElementsByTagName('input')->item(0);
    return $input?->getAttribute('value') ?? false;
}

提取字串中間內容

function getcontentbetween(string $a, string $b, string $str): string|false {
    if ($str === '' || $a === '' || $b === '') return false;
    $start = strpos($str, $a);
    if ($start === false) return false;
    $start += strlen($a);
    $end = strpos($str, $b, $start);
    if ($end === false) return false;
    return substr($str, $start, $end - $start);
}

// 範例
getcontentbetween('', '', 'My Page'); // 'My Page'

七、瀏覽器與作業系統偵測

瀏覽器偵測 (browse_infor)

function browse_infor(): string {
    $agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $browser = 'Unknown';
    $version = '';
    
    // 現代瀏覽器特徵順序重要 (Chrome 包含 Safari 字樣)
    if (preg_match('/Edg\/(\d+)/', $agent, $m)) { $browser = 'Edge'; $version = $m[1]; }
    elseif (preg_match('/OPR\/(\d+)/', $agent, $m)) { $browser = 'Opera'; $version = $m[1]; }
    elseif (preg_match('/Firefox\/(\d+)/', $agent, $m)) { $browser = 'Firefox'; $version = $m[1]; }
    elseif (preg_match('/Chrome\/(\d+)/', $agent, $m)) { $browser = 'Chrome'; $version = $m[1]; }
    elseif (preg_match('/Safari\/(\d+)/', $agent, $m)) { $browser = 'Safari'; $version = $m[1]; }
    elseif (preg_match('/MSIE (\d+)/', $agent, $m)) { $browser = 'Internet Explorer'; $version = $m[1]; }
    elseif (preg_match('/Trident\/.*rv:(\d+)/', $agent, $m)) { $browser = 'Internet Explorer'; $version = $m[1]; }
    
    return $browser . ($version ? " {$version}" : '');
}

// 使用
echo browse_infor(); // "Chrome 120" 或 "Firefox 115"

作業系統偵測 (osinfo)

function osinfo(): string {
    $agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $os = 'Unknown';
    
    // 移動裝置優先
    if (preg_match('/Android (\d+)/', $agent, $m)) $os = "Android {$m[1]}";
    elseif (preg_match('/iPhone OS (\d+)_(\d+)/', $agent, $m)) $os = "iOS {$m[1]}.{$m[2]}";
    elseif (preg_match('/iPad.*OS (\d+)_(\d+)/', $agent, $m)) $os = "iPadOS {$m[1]}.{$m[2]}";
    // 桌面作業系統
    elseif (preg_match('/Windows NT 10\.0/', $agent)) $os = 'Windows 10/11';
    elseif (preg_match('/Windows NT 6\.3/', $agent)) $os = 'Windows 8.1';
    elseif (preg_match('/Windows NT 6\.2/', $agent)) $os = 'Windows 8';
    elseif (preg_match('/Windows NT 6\.1/', $agent)) $os = 'Windows 7';
    elseif (preg_match('/Windows NT 6\.0/', $agent)) $os = 'Windows Vista';
    elseif (preg_match('/Windows NT 5\.1/', $agent)) $os = 'Windows XP';
    elseif (preg_match('/Mac OS X (\d+)_(\d+)/', $agent, $m)) $os = "macOS {$m[1]}.{$m[2]}";
    elseif (preg_match('/Linux/', $agent)) $os = 'Linux';
    elseif (preg_match('/FreeBSD/', $agent)) $os = 'FreeBSD';
    elseif (preg_match('/Unix/', $agent)) $os = 'Unix';
    
    return $os;
}

總結

這 7 大類工具函數構成了 PHP 專案的基礎設施。**核心升級路徑**:字串操作 → 正則 → **DOMDocument/DateTime/Filter 函數/隨機數擴展**。日期運算請全面改用 `DateTime`/`DateInterval` 物件,支援時區、閏年、夏令時間等複雜邏輯。UA 解析建議使用成熟庫 (如 `WhichBrowser/Parser`),自維護正則難以跟上瀏覽器更新。IP 獲取在雲端/容器環境下極其複雜,建議接入專用服務或信任入口層 (Nginx/ALB) 透過標準標頭傳遞真實 IP。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved