在哪里验证用户输入?

ffm*_*ngh 5 php oop validation

我正在使用面向对象的方法开发一个新的应用程序,其中涉及一些REST,我没有使用任何框架.

我的问题是在下面的setter中验证用户输入的最佳位置:

public function setSalary($salary)
{
    if (Validator::money($salary))
        $this->salary = $salary;
    else
        return 'Error that is an invalid number';
}
Run Code Online (Sandbox Code Playgroud)

还是在控制器中?

public function updateSalary()
{
    $errors = array();

    if (Validator::money($_POST['salary']))
        $salary = $_POST['salary'];
        else
            $errors ['salary']  = 'Error that is an invalid number';

    if(count($errors))
        return $errors;

    $employee = new Employee($_POST['e_Id']);
    $employee->setSalary($salary);

    $employee->save();
}
Run Code Online (Sandbox Code Playgroud)

如果我要放入setter我的控制器应该如何看,并返回验证错误?

我已经看到大多数人在控制器中进行验证,但是我认为应该是验证的模型,因为它将使用数据,我们可以重用该模型而不重复自己.但是,有时候验证规则可能需要在某些特殊情况下有所不同,例如对不同视图的不同验证或对晚餐管理员的不同验证.

你会说哪一个符合最佳做法?

ter*_*ško 8

首先,既然你似乎渴望实现类似MVC的结构,那么让我们从一些与验证直接无关的一般错误开始.

  • 只有部分代码(包含PHP超级全局)应该是引导阶段.在你的代码中撒满了超级全局,这使得测试变得非常困难.而且您的代码也会通过<input>名称与HTML紧密结合.

  • 即使您的foror if语句包含单行,也应始终使用大括号.嗯,一般来说,您的代码应遵循PSR-1PSR-2指南.

  • 控制器不应该有任何逻辑,也不应该处理数据保存.阅读这篇文章,也许它清除了一些东西.

好的..现在回到原来的主题.

一般来说,有两种思想流派:

  1. 您在域实体中进行验证

    您的域实体(在您的情况下Employee)包含与其相关的所有业务角色.如果它处于有效状态,它可以使用这些规则进行评估.

    代码将是这样的:

    $employee = new Entity\Employee;
    $employee->setID($id);
    $employee->setSalary($money);    
    if ($employee->isValid()) {
        $mapper = new Mapper\Employee($dbConn);
        $mapper->store($emplyee);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您永远不会创建无效的域实体

    这种方法来自DDD,其中您的域实体由其他类创建,并且它只能从一个有效状态更改为另一个有效状态.基本上,如果你想探索这种方法,你将不得不阅读这本书(可能好几次).

此外,还有另一个验证表单,前两个说明涵盖了注释:数据完整性检查.这是验证的类型,实际上是我的RDBMS.例如,UNIQUE约束.

当遇到ans完整性违规时,通常会抛出异常,即在服务层中处理.


Nik*_*kov 2

每次将数据写入数据库时​​都必须调用验证。所以在这种情况下来自控制器。实际验证发生在模型中。模型是对象,它知道它的字段遵循哪些规则,并且可以检查数据是否有效。此外,模型是世界其他部分和数据库之间的边界。所以,我会做这样的事情:

public function updateSalary()
{
    $employee = new Employee($_POST['e_Id']);
    $employee->setSalary($_POST['salary']));
    if ($employee->validate()) {
        $employee->save();             
    } else {
        return $employee->getErrors();
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我以这种方式向您提供:

  • 因为您将验证保存在一处。稍后,如果您想验证另一个字段,您将再次调用 validate() 方法。您不会为每个字段或类编写另一个验证;
  • 您可以创建一个基类并将 validate() 方法放在那里 - 所有客户端都会调用 validate() 方法,并且不会关心字段的具体情况。验证方法将只关心要验证的内容 - 哪些字段以及规则是什么。此信息将在特定(子)类中设置,例如 Employee 类。
  • 如果您只想验证一个字段(如您的情况),在 validate() 方法中,您可以简单检查哪些字段已更改,并仅对这些字段进行验证。