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

时间:2017-04-12 15:27:33

标签: php forms validation oop

我创建了一个类'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>

3 个答案:

答案 0 :(得分:3)

  

每个人总是制作“数据库类”和“验证类”。呃.... whaaaaay?

不要进行验​​证课程。它永远不会奏效。用于验证用户输入的最可靠...可持续性选项包括:

使用实体进行验证,非常简单。在您的情况下,您将拥有类Profile,其中您有方法setFirstName(string $name)。然后在此方法中进行验证并在出错时抛出自定义的exception,如InvalidFirstName ..或类似的东西。

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

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

因此,要获得此行为,您可以将类定义为:_ / p>

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 :(得分:1)

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

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

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

这样做的原因是,

function __constructor() 

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

function __construct()

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

修改后问题就解决了。

答案 2 :(得分:0)

做一个验证器类。

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

<?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.