萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 表單驗證與過濾類別實作:規則定義、型別檢查、輸出轉義、錯誤回饋

設計目標

  • 聲明式規則定義:欄位名、必要性、型別/格式、錯誤訊息
  • 支援陣列欄位 (核取方塊、多選)
  • 內建常用驗證:長度、數字、Email、URL、中文、英文、字母數字、電話、敏感詞
  • 輸出過濾:HTML 轉義、換行轉換、MD5、資料庫跳脫
  • 錯誤回饋:JavaScript 彈窗/欄位標示

核心類別架構

class FormValidator {
    private $rules = [];      // 驗證規則
    private $data = [];       // 通過驗證的資料
    private $errors = [];     // 錯誤訊息
    
    // 規則格式: 'field_name' => 'required|type:param|type2:param2'
    public function setRules(array $rules): self {
        $this->rules = $rules;
        return $this;
    }
    
    public function validate(array $input = null): bool {
        $input = $input ?? $_POST;
        $this->data = [];
        $this->errors = [];
        
        foreach ($this->rules as $field => $ruleString) {
            $value = $input[$field] ?? null;
            $rules = explode('|', $ruleString);
            
            foreach ($rules as $rule) {
                if (!$this->checkRule($field, $value, $rule)) {
                    break; // 該欄位驗證失敗,停止後續規則
                }
            }
        }
        return empty($this->errors);
    }
    
    private function checkRule(string $field, $value, string $rule): bool {
        // 解析 rule: "type:param1,param2"
        if (strpos($rule, ':') !== false) {
            [$type, $params] = explode(':', $rule, 2);
            $params = explode(',', $params);
        } else {
            $type = $rule;
            $params = [];
        }
        
        $method = 'validate' . ucfirst(strtolower($type));
        if (!method_exists($this, $method)) {
            $this->errors[$field] = "未知驗證規則: $type";
            return false;
        }
        
        return $this->$method($field, $value, $params);
    }
    
    // 內建驗證方法...
    protected function validateRequired($field, $value): bool {
        if (is_array($value)) return !empty($value);
        return $value !== '' && $value !== null;
    }
    
    protected function validateLength($field, $value, array $params): bool {
        [$min, $max] = $params + [0, PHP_INT_MAX];
        $len = is_array($value) ? count($value) : mb_strlen((string)$value);
        if ($len < $min || $len > $max) {
            $this->errors[$field] = "長度需在 $min-$max 之間";
            return false;
        }
        return true;
    }
    
    protected function validateEmail($field, $value): bool {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            $this->errors[$field] = 'Email 格式錯誤';
            return false;
        }
        return true;
    }
    // ... url, numeric, chinese, alpha, alphanum, phone, sensitive 等
    
    // 取得結果
    public function getData(): array { return $this->data; }
    public function getErrors(): array { return $this->errors; }
    public function getErrorString(string $glue = ', '): string {
        return implode($glue, $this->errors);
    }
    
    // 輸出 JS 錯誤提示 (舊版相容)
    public function getErrorScript(): string {
        if (empty($this->errors)) return '';
        $js = "<script>";
        foreach ($this->errors as $field => $msg) {
            $js .= "document.getElementById('err_$field').textContent=" . json_encode($msg) . ";";
        }
        $js .= "</script>";
        return $js;
    }
}

使用範例

$validator = new FormValidator();
$validator->setRules([
    'username' => 'required|length:3,20|alphanum',
    'email'    => 'required|email',
    'password' => 'required|length:8,32',
    'age'      => 'numeric|length:1,3',
    'bio'      => 'length:0,500',
    'tags'     => 'array', // 多選
]);

if ($validator->validate()) {
    $cleanData = $validator->getData();
    // 存入資料庫...
    // $cleanData 已經過驗證,但入庫仍需預處理/參數綁定
} else {
    // 顯示錯誤
    foreach ($validator->getErrors() as $field => $msg) {
        echo "<div class='error' id='err_$field'>$msg</div>";
    }
}

輸出過濾方法

class OutputFilter {
    public static function html($str): string {
        return htmlspecialchars((string)$str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
    public static function nl2br($str): string {
        return nl2br(self::html($str));
    }
    public static function sql(PDO $pdo, $str): string {
        return $pdo->quote($str); // 或使用預處理
    }
    public static function md5($str): string {
        return md5($str);
    }
}

現代替代方案

  • Symfony Validator:獨立元件,支援註解/屬性/XML/YAML 定義規則
  • Laravel Validation:流暢介面、豐富規則、自動重導攜帶錯誤
  • Respect\Validation:鏈式語法、可擴充
  • PHP 內建 filter_var/filter_input:簡單驗證無需依賴
copyright © 萬盛學電腦網 all rights reserved