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

PHP 開發常用 8 大實用技巧:命名慣例、超全域變數、表單判斷、IP/時間取得與現代寫法

     編輯:PHP 相關知識

PHP 開發中有許多「知道會用、不懂原理」的常用片段。本文精選 8 大高頻場景,提供現代寫法 (PHP 7.4+)、安全性分析、效能考量與最佳實踐,替換舊式 $_POST['key']、mysql_*、$_SERVER['REMOTE_ADDR'] 等過時用法。

1. 陣列/物件命名慣例 (PSR-12 / Laravel / Symfony 風格)

// 變數/屬性/方法:camelCase
$userName = 'Alice';
$orderItems = [];
function getUserName() {}

// 類別/介面/Trait:StudlyCase
class UserController {}
interface LoggerInterface {}
trait Loggable {}

// 常數/Enum:SCREAMING_SNAKE_CASE
const MAX_RETRY = 3;
enum Status: string { case PENDING = 'pending'; }

// 命名空間:小寫、單數、反映業務域
namespace App\Http\Controllers\Api\V1;
namespace App\Models;
namespace App\Services\Payment;

2. 取得核選框值並安全構建 SQL (現代 PDO 版)

<form method="post">
    <input type="checkbox" name="ids[]" value="1"> 項目 1
    <input type="checkbox" name="ids[]" value="2"> 項目 2
    <button type="submit" name="action" value="delete">刪除</button>
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $ids = $_POST['ids'] ?? [];
    // 驗證:全為整數
    $ids = array_filter($ids, 'is_numeric');
    $ids = array_map('intval', $ids);

    if ($ids) {
        $placeholders = implode(',', array_fill(0, count($ids), '?'));
        $sql = "DELETE FROM items WHERE id IN ($placeholders)";
        $stmt = $pdo->prepare($sql);
        $stmt->execute($ids); // 參數化,完全防注入
    }
}

3. 判斷表單是否提交 (多種可靠方式)

// 方式一:檢查 REQUEST_METHOD (最通用)
if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }

// 方式二:檢查特定按鈕 name (多按鈕表單)
if (isset($_POST['action'])) {
    match ($_POST['action']) {
        'save' => saveData(),
        'delete' => deleteData(),
        'preview' => previewData(),
    };
}

// 方式三:隱藏欄位標識 (避免按鈕 name 衝突)
<input type="hidden" name="form_submitted" value="user_profile">
if (($_POST['form_submitted'] ?? '') === 'user_profile') { ... }

// ❌ 不推薦:isset($HTTP_POST_VARS['Button1']) (已移除)

4. 取得字串長度 (多位元組安全)

$str = '中文 English 123';

// 字元數 (視覺長度)
$len = mb_strlen($str, 'UTF-8'); // 17

// 位元組數 (儲存長度)
$bytes = strlen($str); // 23

// ❌ 舊式 strlen($str) 直接用於中文會得到位元組數,導致截斷錯誤
// 截取時務必用 mb_substr
$short = mb_substr($str, 0, 10, 'UTF-8');

5. URL 重導向 (安全、標準)

// 內部重導向
$url = '/dashboard';
header("Location: $url", true, 302);
exit;

// 絕對 URL (防開放重導向攻擊)
$allowedHosts = ['example.com', 'api.example.com'];
$target = $_POST['redirect'] ?? '/';
$parsed = parse_url($target);
if ($parsed && isset($parsed['host']) && in_array($parsed['host'], $allowedHosts)) {
    header("Location: $target", true, 302);
} else {
    header("Location: /", true, 302);
}
exit;

// ❌ 舊式 Header("Location: " . $_SERVER['HTTP_REFERER']) 易遭 Referer 注入攻擊

6. 超全域變數存取 (現代最佳實踐)

舊式 (不推薦)現代 (推薦)說明
$HTTP_POST_VARS['key']$_POST['key']PHP 4.1+ 引入超全域
$HTTP_GET_VARS['key']$_GET['key']
$HTTP_SERVER_VARS['REMOTE_ADDR']$_SERVER['REMOTE_ADDR']
global $var; $GLOBALS['var']依賴注入 / 單例 / 靜態屬性避免全域狀態汙染
$_REQUEST明確用 $_GET / $_POST$_REQUEST 合併順序不固定,安全風險

7. 取得客戶端真實 IP (支援代理/負載平衡器)

function getClientIp(): string
{
    $headers = [
        'HTTP_CF_CONNECTING_IP',      // Cloudflare
        'HTTP_X_FORWARDED_FOR',       // 標準代理
        'HTTP_X_REAL_IP',             // Nginx proxy_set_header
        'HTTP_CLIENT_IP',             // 部分代理
        'REMOTE_ADDR',                // 直接連線
    ];

    foreach ($headers as $header) {
        if (!empty($_SERVER[$header])) {
            // X-Forwarded-For 可能包含多個 IP,取第一個
            $ips = explode(',', $_SERVER[$header]);
            $ip = trim($ips[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

// ⚠️ 僅在「信任代理」情況下使用 HTTP_X_FORWARDED_FOR
// Nginx 需設定:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
// PHP 信任代理 IP 白名單機制 (如 Symfony Request::setTrustedProxies)

8. 取得當前日期時間 (DateTimeImmutable 現代寫法)

// 當前時間 (不可變物件,執行緒安全)
$now = new DateTimeImmutable('now', new DateTimeZone('Asia/Taipei'));

// 格式化輸出
echo $now->format('Y-m-d H:i:s');     // 2024-01-15 14:30:00
echo $now->format('Y年m月d日 H:i:s'); // 2024年01月15日 14:30:00
echo $now->format('c');               // ISO 8601: 2024-01-15T14:30:00+08:00
echo $now->format('r');               // RFC 2822: Mon, 15 Jan 2024 14:30:00 +0800

// 時間運算
$tomorrow = $now->modify('+1 day');
$nextWeek = $now->add(new DateInterval('P1W'));
$timestamp = $now->getTimestamp(); // Unix timestamp

// ❌ 舊式 date('Y-m-d') 依賴全域時區設定,易出錯
// ✅ 推薦:統一使用 DateTimeImmutable + 明確時區

總結:現代 PHP 開發鐵律

  1. 輸入永遠驗證:filter_var, assert, 表單請求類別。
  2. 資料庫永遠參數化:PDO 預處理,拒絕字串拼接。
  3. 輸出永遠編碼:模板引擎自動逃逸,htmlspecialchars、json_encode。
  4. 時間永遠用 DateTimeImmutable + 明確時區。
  5. IP 取得需信任代理白名單。
  6. 重導向需驗證目標域名。
  7. 拒絕 $_REQUEST、global、$HTTP_*_VARS。
  8. 字串長度/截取用 mb_* 函式。

這 8 大技巧看似基礎,卻是資安漏洞、編碼亂碼、時區錯誤、重導向攻擊的高發區。建立團隊編碼規範、引入靜態分析 (PHPStan/Psalm)、使用現代框架內建機制,能從根本上消除這類低級錯誤。

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