如何使用面向对象技术验证 PHP 中的表单字段

问题描述 投票:0回答:4

我创建了一个类“validate”来验证两个字段,即“firstname”和“lastname”。它工作不正常,当字段为空时它显示错误,但是当我提交包含非空字段的表单时,错误仍然存在。如何在表单提交时执行此操作?

 <?php

  class validation {

  public $firstName, $lastName, $errorFirstName = '', $errorLastName = '';

  function __constructor($fName, $lName){
    $this->firstName = $fName;
    $this->lastName = $lName;
  }

  function check(){

      if($_SERVER["REQUEST_METHOD"] == "POST"){
        if(empty($this->firstName)){
        $this->errorFirstName = 'First name is required';
       } else {
        $this->errorFirstName = 'Input is okay';
       }

     if(empty($this->lastName)){
         $this->errorLastName = 'Last name is required';
      }  else {
       $this->errorLastName = 'Input is okay';
      }
    }
   }
  }

 $obj = new validation($_POST['firstname'], $_POST['lastname']);
 $obj->check();
 $errorF = $obj->errorFirstName;
 $errorL = $obj->errorLastName;

 ?>

  <!DOCTYPE html>
  <html lang = "en-US" dir = "ltr">
   <head>
    <title>Home</title>
    <meta charset = "UTF-8"/>
   </head>
   <body>
   <form method = "POST" action="<?php echo $_SERVER["PHP_SELF"]?>">
    <label>First Name: </label>
    <input type = "text" name = "firstname" placeholder = "John"/>
    <p class = "error"><?php echo $errorF;?></p>
    <label>Last Name: </label>
    <input type = "text" name = "lastname" placeholder = "Doe"/>
    <p class = "error"><?php echo $errorL;?></p>
    <input type="submit">
   </form>
  </body>
 </html>
php forms validation oop
4个回答
5
投票

大家总是做“数据库类”和“验证类”。呃....什么啊?

不要创建验证类。它永远不会起作用。用于验证用户输入的最.. emm ...可持续选项是:

  • 在域实体中执行验证
  • 使用值对象

使用实体进行验证,非常简单。在您的情况下,您将有类

Profile
,其中您有方法
setFirstName(string $name)
。然后在这个方法中,您进行验证,并在出错时抛出自定义的 Exception,例如
InvalidFirstName
.. 或类似的东西。

使用值对象有点棘手,但它可以防止代码重复。例如,您需要验证电子邮件地址。因此,您想要使用它的方式将类似于:

try {
    $profile = new Profile;
    $profile->setEmail(new EmailAddress($_POST['email']));
} catch (InvalidArgumentException $e){
    // validation failed
}

因此,要获得这种行为,您需要像这样定义类:

class EmailAddress
{
    private $email;


    public function __construct(int $emailId = null, string $email = null)
    {
        if (!$this->isValid($email)) {
            throw new InvalidArgumentException('Not valid email address');
        }
        $this->email = $email;
    }


    private function isValid($email)
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }


    public function __toString()
    {
        return $this->email;
    }
}

这种方法更具表现力,但在与持久层交互时,它往往会变得很粗糙。

在实践中,最好的选择是结合使用这两种解决方案:

  • 在实体中保留唯一的规则验证
  • 将值对象用于经常重复的约束

1
投票

创建一个验证器类。

表单通常由多个字段组成,这意味着在建议的方法中,您在设置对象时尝试/捕获错误将在单个字段上失败,当您可能有多个无效字段并且在表单提交时,您希望验证所有字段并且返回所有错误,以便可以同时显示它们。

<?php

class MyValidator
{
    /**
     * Is form valid;
     *
     * @var bool
     */
    private $isValid = true;
    /**
     * List of errors, assoc array with error messages one per fieldName
     *
     * @var array
     */
    private $errors = [];

    /**
     * Check if form is valid
     *
     * @return bool
     */
    public function isValid(): bool
    {
        return $this->isValid;
    }

    /**
     * Get error message
     *
     * @param $fieldName
     * @return mixed|string
     */
    public function getError($fieldName)
    {
        return isset($this->errors[$fieldName]) ? $this->errors['fieldName'] : '';
    }

    /**
     * @param array $rules list of rules
     * @param array $payload list of form parameters
     * @return bool Return validation result, same as isValid
     */
    public function validate(array $rules, array $payload)
    {
        foreach ($rules as $rule) {
            if (!$this->validateRequired($rule, $payload)) {
                continue;
            }
            switch ($rule['type']) {
                case 'string':
                    $this->validateString($rule, $payload);
                    break;
                case 'email':
                    $this->validateEmail($rule, $payload);
                    break;
                    //extend with other validation rules as needed
            }
        }

        return $this->isValid();
    }

    public function validateRequired(array $rule, array $payload)
    {
        if (true === $rule['required'] && !isset($payload[$rule['fieldName']])) {
            $this->isValid = false;
            $this->errors[$rule['fieldName']] = 'This field is required';

            return false;
        }

        return true;
    }

    public function validateString($rule, $payload)
    {
        // Checkup logic, set $this->isValid to false if not valid, add
        // See add $this->errors[$rule['fieldname']] = 'your message';
    }

    public function validateEmail($rule, $payload)
    {
        // Checkup logic, set $this->isValid to false if not valid, add
        // See add $this->errors[$rule['fieldname']] = 'your message';
    }

}

// Call validator by giving validator ruleset in the format

$rules = [
    [
        'fieldName' => 'firstName',
        'type' => 'string',
        'minLength' => 10,
        'maxLength' => 20,
        'required' => true,
    ],
    [
        'fieldName' => 'email',
        'type' => 'email',
        'required' => true,
    ]
];

$validator = new MyValidator();
$isValid = $validator->validate($rules, $_POST);

// if false do repeat form with error messages shown
// use $validator->getError('firstName'); to get error message for a field.

1
投票

在提到的代码中,其编写方式是在创建类时将表单值传递给类,并且在构造函数内,类变量将使用提供的值进行初始化。

之后 check() 方法将检查字段是否为空。

但这并没有按预期工作,因为从表单传递的值无法初始化为 $firstName 和 $lastName。

原因是,

function __constructor() 

不是类的构造函数,它应该是

function __construct()

这就是为什么类变量没有分配表单中给出的值并且出现错误的原因。

修改后问题就解决了。


0
投票

我正在尝试以这种方式从页面进行验证。

 public static function validation($rules)
{
    $errors = [];
    $all_data = [];
    try {
        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            $result = str_replace('"', '', $_GET);
        } elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $result = str_replace('"', '', $_POST);
        } elseif ($_SERVER['REQUEST_METHOD'] === 'PUT') {
            $result = str_replace('"', '', $_GET);
        } elseif ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
            $result = str_replace('"', '', $_POST);
        }
        foreach ($rules as $key => $data) {
            $value = explode('|', $data);
            $required = preg_match('/required/', $data, $matches) ? $matches[0] : null;
            $max = preg_match('/max:(\d+)/', $data, $matches) ? $matches[1] : 256;
            $min = preg_match('/min:(\d+)/', $data, $matches) ? $matches[1] : 1;
            $unique = preg_match('/unique:(\w+)/', $data, $matches) ? $matches[1] : null;
            $email = preg_match('/email/', $data, $matches) ? $matches[0] : null;


            if ($required === $value[0]) {
                if (empty($result[$key])) {
                    $errors[$key] = $key . " Is required";
                } else {
                    if ((int)$min >= strlen($result[$key]) || (int)$max <= strlen($result[$key])) $errors[$key] = $key . "Min required or Max required";

                    if ($email=== $value[0]) {
                        if (!filter_var($result[$key], FILTER_VALIDATE_EMAIL)) {
                            $errors[$key] = $key . "Is Email Not Valid";
                        }
                    }
                    if ($unique !== null) {
                        $data = (new Database())->query("select * from $unique where $key = '$result[$key]'")->get();

                        if ($data === null) {
                            $errors[$key] = $key . "Is Unique Value Exists";
                        }
                    }
                    $all_data[$key]= $result[$key];
                }
            }
        }
    } catch (\Exception $e) {
        echo 'Caught exception: ', $e->getMessage(), "\n";
    }
   return [
       'errors' => $errors,
       'data' => $all_data
   ];
}

给班级打电话,

  $validations = Validation::validation([
        'name' => 'required|unique:shops|min:1|max:255',
        'email' => 'required|unique:shops|min:1|max:255|email'          
    ]);

    if ($validations['errors']) {
        echo $validations['errors'];
        return header('location: /');
    }
© www.soinside.com 2019 - 2024. All rights reserved.