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

PHP 開發必備 9 大實用功能函數:從可變參數到性能分析、序列化與緩存技巧

     編輯:PHP 綜合知識

1. 可變參數函數:func_get_args() / ... 操作符

PHP 支援任意數量參數,現代寫法使用 ...(PHP 5.6+):

<?php
// 現代寫法(推薦)
function sum(...$numbers): float
{
    return array_sum($numbers);
}
echo sum(1, 2, 3, 4.5); // 10.5

// 經典寫法(兼容舊版)
function legacySum()
{
    $args = func_get_args();
    return array_sum($args);
}

// 結合類型提示(PHP 8+)
function logMessage(string $level, string ...$messages): void
{
    foreach ($messages as $msg) {
        error_log("[$level] $msg");
    }
}
logMessage('INFO', 'User login', 'IP: 192.168.1.1');

2. glob() 文件模式匹配(比 scandir() 更強)

<?php
// 所有 PHP 文件
$phpFiles = glob('*.php');

// 多擴展名(需 GLOB_BRACE)
$codeFiles = glob('*.{php,js,css,html}', GLOB_BRACE);

// 遞歸查找(PHP 5.5+ GLOB_BRACE 不支援遞歸,需配合 RecursiveDirectoryIterator)
$allPhp = glob('src/**/*.php', GLOB_BRACE); // 不支援 **,見下文

// 正確遞歸查找
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('src', RecursiveDirectoryIterator::SKIP_DOTS)
);
$phpFiles = new RegexIterator($iterator, '/\.php$/i');

// 獲取絕對路徑
$absPaths = array_map('realpath', glob('../images/a*.jpg'));

3. 內存使用分析:memory_get_usage() / memory_get_peak_usage()

<?php
echo "初始內存: " . memory_get_usage() . " bytes\n"; // ~360KB

// 分配大數組
$data = [];
for ($i = 0; $i < 100000; $i++) {
    $data[] = md5($i);
}
echo "峰值內存: " . memory_get_peak_usage() . " bytes\n"; // ~13MB

// 釋放一半
for ($i = 0; $i < 50000; $i++) {
    unset($data[$i]);
}
echo "當前內存: " . memory_get_usage() . " bytes\n"; // ~8MB

// 實際項目中:監控內存洩漏
register_shutdown_function(function() {
    $peak = memory_get_peak_usage(true); // 真實系統分配
    if ($peak > 100 * 1024 * 1024) { // 100MB 閾值
        error_log("Memory peak exceeded: " . ($peak / 1024 / 1024) . " MB");
    }
});

4. CPU 使用分析:getrusage()(僅 Linux/Unix)

<?php
// 僅 CLI/Unix 環境可用
$data = getrusage();

// 用戶態 CPU 時間(秒)
$userTime = $data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1_000_000;
// 內核態 CPU 時間
$sysTime = $data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1_000_000;

echo "用戶態: $userTime 秒, 內核態: $sysTime 秒\n";

// 對比:睡眠 vs 計算
sleep(3); // 不佔用 CPU
$data = getrusage();
echo "睡眠後用戶態: " . ($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec']/1e6) . "\n"; // ~0

// 密集計算
for ($i = 0; $i < 10_000_000; $i++) {}
$data = getrusage();
echo "計算後用戶態: " . ($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec']/1e6) . "\n"; // ~1.4s

5. 魔術常量:調試與路徑解析利器

常量含義典型用途
__LINE__當前行號調試輸出、錯誤定位
__FILE__當前文件完整路徑require_once dirname(__FILE__) . '/config.php'
__DIR__當前文件目錄(PHP 5.3+)require __DIR__ . '/config.php' 更簡潔
__FUNCTION__函數名日誌記錄、AOP 切面
__CLASS__類名工廠模式、反射
__METHOD__類方法名精確調試定位
__NAMESPACE__命名空間動態類加載

調試函數示例

function debug(mixed $msg): void
{
    $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] ?? [];
    echo "[{$bt['file'] ?? '?'}]:{$bt['line'] ?? '?'} {$bt['function'] ?? '?'} - $msg\n";
}
debug('進入訂單處理'); // [/app/Order.php:45] handle - 進入訂單處理

6. 唯一 ID 生成:uniqid() vs md5()

<?php
// ❌ 老舊寫法:長、無序、無語義
$id = md5(time() . mt_rand(1, 1000000)); // 32 字符

// ✅ 現代寫法:短、按時間有序、可加前綴
echo uniqid();           // 4bd67c947233e (13 字符,微秒級時間)
echo uniqid('order_');   // order_4bd67c947233e (帶前綴)
echo uniqid('', true);   // 4bd67c947233e.12345678 (更多熵,含微秒小數)
echo uniqid('usr_', true); // usr_4bd67c947233e.12345678

// 極高併發/分布式:UUID v4 / ULID / Snowflake
// 使用 ramsey/uuid 或自定義 Snowflake 實現

7. 序列化:serialize() vs json_encode()

<?php
$data = ['hello', 42, [1, 'two'], 'apple'];

// PHP 原生序列化(含類型、對象)
$ser = serialize($data);
// a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";}
$restored = unserialize($ser);

// JSON(跨語言、可讀、緊湊)
$json = json_encode($data);
// ["hello",42,[1,"two"],"apple"]
$restored = json_decode($json, true); // true 返回關聯數組

// 對比
/*
| 特性          | serialize()      | json_encode()       |
| 類型保持      | ✅ 完整           | ⚠️ 數字/字符串/數組/對象 |
| 對象支援      | ✅ 含私有屬性      | ❌ 僅公共屬性          |
| 跨語言        | ❌ PHP 專用        | ✅ 標準格式           |
| 性能          | 較快              | 較慢 (解析開銷)       |
| 安全性        | ⚠️ 反序列化風險    | ✅ 安全               |
*/
// 建議:緩存/存儲用 JSON,會話/內部傳遞用 serialize(信任數據源前提)

8. 字符串壓縮:gzcompress() / gzencode()

<?php
$text = "Lorem ipsum dolor sit amet... (800 字節長文本)";

$compressed = gzcompress($text);      // zlib 壓縮
echo "原始: " . strlen($text) . " 字節\n";    // 800
echo "壓縮: " . strlen($compressed) . " 字節\n"; // ~418 (近 50%)

$original = gzuncompress($compressed); // 解壓

// gzencode() 使用 gzip 格式(含頭部),適合 HTTP 傳輸
$gzipped = gzencode($text, 9); // 級別 1-9
// 瀏覽器可直接解碼 gzip Content-Encoding

9. 關閉回調:register_shutdown_function()

<?php
// 問題:exit() / 致命錯誤 / 瀏覽器關閉 導致腳本中途結束,末尾代碼不執行
$start = microtime(true);
// ... 業務邏輯 ...
echo "耗時: " . (microtime(true) - $start) . " 秒"; // 可能不執行

// 解決:註冊關閉函數,無論如何退出都會執行
$start = microtime(true);
register_shutdown_function(function() use ($start) {
    echo "總耗時: " . (microtime(true) - $start) . " 秒\n";
    // 可在此記錄日誌、發送監控指標、釋放鎖等
});

// 模擬中途退出
if (rand(0, 1)) exit('隨機退出');
// 即使 exit,關閉函數仍會執行

綜合應用示例:性能監控中間件

<?php
class PerformanceMiddleware
{
    public function handle(callable $next): mixed
    {
        $startTime = microtime(true);
        $startMem = memory_get_usage();
        $startCpu = getrusage();

        register_shutdown_function([$this, 'logMetrics'], $startTime, $startMem, $startCpu);

        return $next();
    }

    public function logMetrics(float $startTime, int $startMem, array $startCpu): void
    {
        $time = microtime(true) - $startTime;
        $mem = memory_get_peak_usage(true) - $startMem;
        $cpu = getrusage();
        $userCpu = ($cpu['ru_utime.tv_sec'] + $cpu['ru_utime.tv_usec']/1e6) -
                   ($startCpu['ru_utime.tv_sec'] + $startCpu['ru_utime.tv_usec']/1e6);

        error_log(json_encode([
            'time_ms' => round($time * 1000, 2),
            'memory_kb' => round($mem / 1024, 2),
            'cpu_user_sec' => round($userCpu, 4),
            'url' => $_SERVER['REQUEST_URI'] ?? 'cli',
        ]));
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved