Undefined array key(PHP 8+)或 Undefined index(PHP 7)是 Notice 級別 警告,非致命錯誤。但大量警告會:
| 方案 | 代碼示例 | 優點 | 缺點 | 推薦 |
|---|---|---|---|---|
| 1. php.ini 全局抑制 | error_reporting = E_ALL & ~E_NOTICE |
一勞永逸 | 掩蓋真實問題、不利調試、共享主機不可改 | ❌ 禁止 |
2. 代碼級抑制 @ |
$v = @$_GET['key'] |
針對性強 | 性能極差(每次調用修改錯誤處理器)、掩蓋所有錯誤、不可讀 | ❌ 禁止 |
| 3. 運行時關閉報錯 | error_reporting(0) |
快速生效 | 影響全局、隱藏致命錯誤 | ❌ 禁止 |
4. isset() 判斷 |
if (isset($_GET['key'])) { $v = $_GET['key']; } |
語義明確、標準寫法 | 代碼冗長、重複鍵名 | ✅ 推薦 |
5. ?? 空合併運算符 (PHP 7+) |
$v = $_GET['key'] ?? 'default' |
簡潔、表達意圖、性能佳 | 僅適用有默認值場景 | ✅ 強烈推薦 |
6. array_key_exists() |
if (array_key_exists('key', $_GET)) |
區分 null 值與鍵不存在 |
函數調用開銷、較少用 | ⚠️ 特定場景 |
| 7. 封裝獲取函數 | function g($k, $d=null) { return $_GET[$k] ?? $d; } |
統一入口、可擴展驗證/過濾 | 增加函數調用、團隊需約定 | ✅ 專案級推薦 |
<?php
/**
* 輸入獲取與驗證基類
*/
class Input
{
/** @var array 合併後的輸入數據 */
private static array $data = [];
public static function init(): void
{
// 優先級:POST > GET > REQUEST(自定義策略)
self::$data = array_merge($_GET, $_POST);
// JSON API 支援
if (strpos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') === 0) {
$json = json_decode(file_get_contents('php://input'), true);
if (is_array($json)) {
self::$data = array_merge(self::$data, $json);
}
}
}
/**
* 獲取輸入值
* @param string $key 鍵名,支援點號路徑如 'user.name'
* @param mixed $default 默認值
* @param callable|null $filter 過濾器
* @return mixed
*/
public static function get(string $key, mixed $default = null, callable $filter = null): mixed
{
$value = data_get(self::$data, $key, $default);
return $filter ? $filter($value) : $value;
}
/** 批量獲取,返回鍵值對 */
public static function only(array $keys): array
{
return array_intersect_key(self::$data, array_flip($keys));
}
/** 排除指定鍵 */
public static function except(array $keys): array
{
return array_diff_key(self::$data, array_flip($keys));
}
}
/** 簡易點號路徑獲取 */
function data_get(array $data, string $key, mixed $default = null): mixed
{
if (strpos($key, '.') === false) {
return $data[$key] ?? $default;
}
foreach (explode('.', $key) as $segment) {
if (!is_array($data) || !array_key_exists($segment, $data)) {
return $default;
}
$data = $data[$segment];
}
return $data;
}
// 引導文件調用
Input::init();
// 控制器中使用
$name = Input::get('name', '', 'trim');
$page = Input::get('page', 1, 'intval');
$filters = Input::get('filters', [], fn($v) => is_array($v) ? $v : []);
<?php
abstract class FormRequest
{
protected array $data;
public function __construct(array $data)
{
$this->data = $data;
}
abstract public function rules(): array;
public function validate(): bool
{
$validator = new Validator($this->data, $this->rules());
if ($validator->fails()) {
$this->failedValidation($validator);
return false;
}
return true;
}
protected function failedValidation(Validator $validator): void
{
throw new ValidationException($validator->errors());
}
public function __get(string $key)
{
return $this->data[$key] ?? null;
}
}
// 使用
class StoreUserRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|string|max:50',
'email' => 'required|email|unique:users',
'age' => 'integer|min:1|max:120',
];
}
}
// 控制器
public function store(StoreUserRequest $request)
{
// 驗證已通過,直接使用
User::create($request->only(['name', 'email', 'age']));
}
\$_(\w+)\['([^']+)'\] → ($_$1['$2'] ?? null)??,舊模塊逐步重構; php.ini 生產環境推薦
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
; 注意:保留 E_NOTICE,通過日誌監控系統(如 Sentry)告警
配合日誌聚合系統(ELK/Sentry),設置 Notice 級別告警閾值,實現「開發期嚴格、生產期可觀測」。
array_splice() 最佳實務
PHP 統計數組非空元素個數:array_filter + count 一行搞定
Windows Server 2003 實現 MySQL 每日自動備份:PHP + mysqldump + WinRAR + 任務計劃完整方案
Linux 下創建 Nginx 系統服務腳本(支持 start/stop/reload/status)
Smarty 模板引擎入門筆記:實現前後端分離與靜態緩存
Linux mv、cp、rm 命令詳解:檔案操作核心指令完全指南