DS:一个处理php前端数据的实用类

这需要根据项目规模和复杂度来权衡,不是绝对的。 让我分析一下各种情况的适用方案:

📊 封装决策指南

1. 小型项目/简单表单 - 不需要过度封装

<?php
// 简单直接的做法
$required = ['title', 'content', 'category_id'];
$errors = [];

foreach ($required as $field) {
    if (empty($_POST[$field])) {
        $errors[] = "{$field} 是必填字段";
    }
}

if (!empty($errors)) {
    echo json_encode(['success' => false, 'errors' => $errors]);
    exit;
}

// 简单清理
$cleanData = [
    'title' => htmlspecialchars(trim($_POST['title']), ENT_QUOTES, 'UTF-8'),
    'content' => htmlspecialchars(trim($_POST['content']), ENT_QUOTES, 'UTF-8'),
    'category_id' => (int)$_POST['category_id'],
    'created_at' => date('Y-m-d H:i:s')
];

$articleId = AdService::addArticle($articlesModel, $cleanData);
?>

2. 中型项目 - 适度封装

<?php
class SimpleValidator {
    public static function validate(array $data, array $rules) {
        $errors = [];
        
        foreach ($rules as $field => $fieldRules) {
            $value = $data[$field] ?? null;
            
            foreach ($fieldRules as $rule) {
                if ($rule === 'required' && empty($value)) {
                    $errors[] = "{$field} 是必填字段";
                } elseif ($rule === 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $errors[] = "{$field} 邮箱格式无效";
                }
                // 更多简单规则...
            }
        }
        
        return $errors;
    }
    
    public static function sanitize(array $data) {
        $clean = [];
        foreach ($data as $key => $value) {
            $clean[$key] = is_string($value) 
                ? htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8')
                : $value;
        }
        return $clean;
    }
}

// 使用
$rules = [
    'title' => ['required'],
    'email' => ['required', 'email'],
    'category_id' => ['required']
];

$errors = SimpleValidator::validate($_POST, $rules);
if ($errors) {
    echo json_encode(['success' => false, 'errors' => $errors]);
    exit;
}

$cleanData = SimpleValidator::sanitize($_POST);
$articleId = AdService::addArticle($articlesModel, $cleanData);
?>

3. 大型项目/复杂业务 - 完整封装

<?php
// 完整的验证器类
class ArticleValidator {
    private $data;
    private $errors = [];
    
    public function __construct(array $data) {
        $this->data = $data;
    }
    
    public function validate() {
        $this->validateTitle();
        $this->validateContent();
        $this->validateCategory();
        $this->validateAuthor();
        
        return empty($this->errors);
    }
    
    public function getErrors() {
        return $this->errors;
    }
    
    public function getSanitizedData() {
        return [
            'title' => $this->sanitizeString($this->data['title'] ?? ''),
            'content' => $this->sanitizeContent($this->data['content'] ?? ''),
            'category_id' => (int)($this->data['category_id'] ?? 0),
            'author' => $this->sanitizeString($this->data['author'] ?? ''),
            'status' => in_array($this->data['status'] ?? 1, [0, 1]) ? (int)$this->data['status'] : 1,
            'created_at' => date('Y-m-d H:i:s')
        ];
    }
    
    private function validateTitle() {
        $title = $this->data['title'] ?? '';
        if (empty($title)) {
            $this->errors[] = '标题不能为空';
        } elseif (mb_strlen($title) > 255) {
            $this->errors[] = '标题不能超过255个字符';
        }
    }
    
    private function validateContent() {
        $content = $this->data['content'] ?? '';
        if (empty($content)) {
            $this->errors[] = '内容不能为空';
        } elseif (mb_strlen($content) < 10) {
            $this->errors[] = '内容至少需要10个字符';
        }
    }
    
    private function sanitizeString($value) {
        return htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
    }
    
    private function sanitizeContent($value) {
        // 允许一些HTML标签
        return strip_tags(trim($value), '<p><br><strong><em>');
    }
}

// 使用
$validator = new ArticleValidator($_POST);
if (!$validator->validate()) {
    echo json_encode(['success' => false, 'errors' => $validator->getErrors()]);
    exit;
}

$cleanData = $validator->getSanitizedData();
$articleId = AdService::addArticle($articlesModel, $cleanData);
?>

🎯 封装的好处 vs 成本

✅ 应该封装的情况:

// 当你有:
// 1. 多个地方使用相同验证逻辑
// 2. 复杂的业务规则
// 3. 团队协作开发
// 4. 需要单元测试
// 5. 项目会长期维护

class UserRegistrationValidator {
    // 复杂的用户注册验证逻辑
    // 可以复用和测试
}

❌ 不需要封装的情况:

// 当你有:
// 1. 一次性简单表单
// 2. 个人小项目
// 3. 时间紧迫的原型
// 4. 验证逻辑非常简单

// 直接内联处理更合适
if (empty($_POST['name']) || empty($_POST['email'])) {
    die('请填写必填字段');
}
$name = htmlspecialchars(trim($_POST['name']));
// ... 直接使用

🔧 渐进式封装策略

阶段1:函数式封装

function validate_article_data($data) {
    $errors = [];
    if (empty($data['title'])) $errors[] = '标题必填';
    if (empty($data['content'])) $errors[] = '内容必填';
    return $errors;
}

function sanitize_article_data($data) {
    return [
        'title' => htmlspecialchars(trim($data['title'])),
        'content' => htmlspecialchars(trim($data['content']))
    ];
}

阶段2:静态类封装

class ArticleDataHelper {
    public static function validate($data) { /* ... */ }
    public static function sanitize($data) { /* ... */ }
}

阶段3:完整面向对象

class ArticleDataProcessor {
    private $validator;
    private $sanitizer;
    
    public function process($rawData) {
        // 完整的处理流程
    }
}

📝 实际建议

对于大多数项目,我推荐:

<?php
// 实用主义方案 - 平衡封装和简单性
class DataHelper {
    public static function getCleanData($input, $fieldConfig) {
        $clean = [];
        
        foreach ($fieldConfig as $field => $config) {
            $value = $input[$field] ?? $config['default'] ?? '';
            
            // 根据类型清理
            switch ($config['type'] ?? 'string') {
                case 'string':
                    $clean[$field] = htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
                    break;
                case 'int':
                    $clean[$field] = (int)$value;
                    break;
                case 'email':
                    $clean[$field] = filter_var($value, FILTER_SANITIZE_EMAIL);
                    break;
                default:
                    $clean[$field] = $value;
            }
        }
        
        return $clean;
    }
    
    public static function validateRequired($data, $requiredFields) {
        $errors = [];
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 是必填字段";
            }
        }
        return $errors;
    }
}

// 使用
$fieldConfig = [
    'title' => ['type' => 'string', 'required' => true],
    'content' => ['type' => 'string', 'required' => true],
    'category_id' => ['type' => 'int', 'required' => true],
    'author' => ['type' => 'string', 'required' => false, 'default' => '匿名']
];

$cleanData = DataHelper::getCleanData($_POST, $fieldConfig);
$requiredFields = ['title', 'content', 'category_id'];
$errors = DataHelper::validateRequired($cleanData, $requiredFields);

if ($errors) {
    echo json_encode(['success' => false, 'errors' => $errors]);
    exit;
}

$articleId = AdService::addArticle($articlesModel, $cleanData);
?>

🎯 总结

封装决策矩阵:

项目规模 推荐方案 理由
小项目/原型 内联处理 快速开发,过度封装是负担
中型项目 工具类/静态方法 平衡可维护性和开发效率
大型项目 完整类封装 便于测试、维护和扩展
企业级 验证框架 使用成熟的验证库

核心原则:从简单开始,按需封装。不要为了封装而封装!

posted @ 2025-10-18 13:17  充实地生活着  阅读(6)  评论(0)    收藏  举报