respect php validation model

respect - ¿El mejor enfoque para la validación de modelos en PHP?



respect validation (1)

No creo que haya un solo enfoque, depende de cómo vayas a utilizar tus clases. En este caso, cuando solo tiene un objeto de datos simple, preferiría usar el Método n.º 2: Validación usando métodos de validación en la clase de modelo .

Las cosas malas no son tan malas, en mi opinión:

El modelo puede estar en un estado inválido

Algunas veces es deseable poder tener un modelo en un estado inválido.

Por ejemplo, si completa el objeto Persona desde un formulario web y desea iniciar sesión. Si utilizas el primer enfoque, tendrías que extender la clase Person, anular todos los setters para detectar excepciones y luego podrías tener este objeto en un estado no válido para el registro.

El desarrollador debe recordar llamar al método de validación is_valid ()

Si el modelo no debe estar en un estado inválido, o si un método requiere que el modelo esté en un estado válido, siempre puede llamar a is_valid() desde dentro de la clase para asegurarse de que esté en un estado válido.

La clase de modelo puede ser larga debido a la gran cantidad de validación

El código de validación todavía debe ir a alguna parte. La mayoría de los editores le permiten doblar las funciones, por lo que no debería ser un problema al leer el código. En todo caso, creo que es bueno tener toda la validación en un solo lugar.

Aprendí que a menudo hay muchas formas de resolver un problema de programación, cada enfoque suele tener sus propios beneficios y efectos secundarios negativos.

Lo que estoy tratando de determinar hoy es la mejor manera de hacer la validación del modelo en PHP. Usando el ejemplo de una persona, describí cuatro enfoques diferentes que he usado en el pasado, cada uno incluyendo las clases y un ejemplo de uso, así como también lo que me gusta y no me gusta de cada enfoque.

Mi pregunta aquí es esta: ¿Qué enfoque crees que es el mejor? ¿O tienes un mejor enfoque?

Método n. ° 1: Validación utilizando métodos setter en la clase de modelo

El bueno

  • Simple, solo una clase
  • Al arrojar excepciones, la clase nunca puede estar en un estado inválido (a excepción de la lógica comercial, es decir, la muerte se produce antes del nacimiento)
  • No tiene que recordar llamar a ningún método de validación

El malo

  • Solo puede devolver 1 error (a través de Exception )
  • Requiere el uso de excepciones y capturarlas, incluso si los errores no son muy excepcionales
  • Solo puede actuar sobre un parámetro, ya que es posible que aún no se hayan establecido otros parámetros (no hay forma de comparar birth_date y death_date )
  • La clase de modelo puede ser larga debido a la gran cantidad de validación

class Person { public $name; public $birth_date; public $death_date; public function set_name($name) { if (!is_string($name)) { throw new Exception(''Not a string.''); } $this->name = $name; } public function set_birth_date($birth_date) { if (!is_string($birth_date)) { throw new Exception(''Not a string.''); } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $birth_date)) { throw new Exception(''Not a valid date.''); } $this->birth_date = $birth_date; } public function set_death_date($death_date) { if (!is_string($death_date)) { throw new Exception(''Not a string.''); } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $death_date)) { throw new Exception(''Not a valid date.''); } $this->death_date = $death_date; } }

// Usage: try { $person = new Person(); $person->set_name(''John''); $person->set_birth_date(''1930-01-01''); $person->set_death_date(''2010-06-06''); } catch (Exception $exception) { // Handle error with $exception }

Método n. ° 2: Validación utilizando métodos de validación en la clase de modelo

El bueno

  • Simple, solo una clase
  • Posibilidad de validar (comparar) múltiples parámetros (ya que la validación se produce después de que se hayan establecido todos los parámetros del modelo)
  • Puede devolver múltiples errores (a través del método de errors() )
  • Libertad de excepciones
  • Hojas getter y setter métodos disponibles para otras tareas

El malo

  • El modelo puede estar en un estado inválido
  • El desarrollador debe recordar llamar al método de validación is_valid()
  • La clase de modelo puede ser larga debido a la gran cantidad de validación

class Person { public $name; public $birth_date; public $death_date; private $errors; public function errors() { return $this->errors; } public function is_valid() { $this->validate_name(); $this->validate_birth_date(); $this->validate_death_date(); return count($this->errors) === 0; } private function validate_name() { if (!is_string($this->name)) { $this->errors[''name''] = ''Not a string.''; } } private function validate_birth_date() { if (!is_string($this->birth_date)) { $this->errors[''birth_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->birth_date)) { $this->errors[''birth_date''] = ''Not a valid date.''; } } private function validate_death_date() { if (!is_string($this->death_date)) { $this->errors[''death_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->death_date)) { $this->errors[''death_date''] = ''Not a valid date.''; break; } if ($this->death_date < $this->birth_date) { $this->errors[''death_date''] = ''Death cannot occur before birth''; } } }

// Usage: $person = new Person(); $person->name = ''John''; $person->birth_date = ''1930-01-01''; $person->death_date = ''2010-06-06''; if (!$person->is_valid()) { // Handle errors with $person->errors() }

Método n. ° 3: Validación en una clase de validación separada

El bueno

  • Modelos muy simples (toda validación ocurre en una clase separada)
  • Posibilidad de validar (comparar) múltiples parámetros (ya que la validación se produce después de que se hayan establecido todos los parámetros del modelo)
  • Puede devolver múltiples errores (a través del método de errors() )
  • Libertad de excepciones
  • Hojas getter y setter métodos disponibles para otras tareas

El malo

  • Ligeramente más complicado ya que se requieren dos clases para cada modelo
  • El modelo puede estar en un estado inválido
  • El desarrollador debe recordar usar la clase de validación

class Person { public $name; public $birth_date; public $death_date; }

class Person_Validator { private $person; private $errors = array(); public function __construct(Person $person) { $this->person = $person; } public function errors() { return $this->errors; } public function is_valid() { $this->validate_name(); $this->validate_birth_date(); $this->validate_death_date(); return count($this->errors) === 0; } private function validate_name() { if (!is_string($this->person->name)) { $this->errors[''name''] = ''Not a string.''; } } private function validate_birth_date() { if (!is_string($this->person->birth_date)) { $this->errors[''birth_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->person->birth_date)) { $this->errors[''birth_date''] = ''Not a valid date.''; } } private function validate_death_date() { if (!is_string($this->person->death_date)) { $this->errors[''death_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->person->death_date)) { $this->errors[''death_date''] = ''Not a valid date.''; break; } if ($this->person->death_date < $this->person->birth_date) { $this->errors[''death_date''] = ''Death cannot occur before birth''; } } }

// Usage: $person = new Person(); $person->name = ''John''; $person->birth_date = ''1930-01-01''; $person->death_date = ''2010-06-06''; $validator = new Person_Validator($person); if (!$validator->is_valid()) { // Handle errors with $validator->errors() }

Método n. ° 4: Validación en la clase de modelo y la clase de validación

El bueno

  • Al arrojar excepciones, la clase nunca puede estar en un estado inválido (a excepción de la lógica comercial, es decir, la muerte se produce antes del nacimiento)
  • Posibilidad de validar (comparar) múltiples parámetros (ya que la validación comercial ocurre después de que se hayan establecido todos los parámetros del modelo)
  • Puede devolver múltiples errores (a través del método de errors() )
  • La validación se organiza en dos grupos: tipo (clase de modelo) y negocio (clase de validación)
  • Hojas getter y setter métodos disponibles para otras tareas

El malo

  • El manejo de errores es más complicado si hay excepciones lanzadas (clase de modelo) y una matriz de errores (clase de validación)
  • Ligeramente más complicado ya que se requieren dos clases para cada modelo
  • El desarrollador debe recordar usar la clase de validación

class Person { public $name; public $birth_date; public $death_date; private function validate_name() { if (!is_string($this->person->name)) { $this->errors[''name''] = ''Not a string.''; } } private function validate_birth_date() { if (!is_string($this->person->birth_date)) { $this->errors[''birth_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->person->birth_date)) { $this->errors[''birth_date''] = ''Not a valid date.''; } } private function validate_death_date() { if (!is_string($this->person->death_date)) { $this->errors[''death_date''] = ''Not a string.''; break; } if (!preg_match(''/(/d{4})-([01]/d)-([0-3]/d)/'', $this->person->death_date)) { $this->errors[''death_date''] = ''Not a valid date.''; } } }

class Person_Validator { private $person; private $errors = array(); public function __construct(Person $person) { $this->person = $person; } public function errors() { return $this->errors; } public function is_valid() { $this->validate_death_date(); return count($this->errors) === 0; } private function validate_death_date() { if ($this->person->death_date < $this->person->birth_date) { $this->errors[''death_date''] = ''Death cannot occur before birth''; } } }

// Usage: try { $person = new Person(); $person->set_name(''John''); $person->set_birth_date(''1930-01-01''); $person->set_death_date(''2010-06-06''); $validator = new Person_Validator($person); if (!$validator->is_valid()) { // Handle errors with $validator->errors() } } catch (Exception $exception) { // Handle error with $exception }