En la clase anterior creamos un CRUD básico devolviendo una respuesta en formato JSON para cada uno de los métodos de nuestro controlador de usuarios, pero sólo tomamos en cuenta el posible caso de que los datos fuesen validos y no se encontrara ningún error durante la ejecución. Ahora, en esta lección vamos a agregar las validaciones correspondientes para manejar otros posibles escenarios.

Lo primero que debemos hacer es crear las validaciones para confirmar si los datos que se están recibiendo coinciden con lo esperado y de no ser así vamos a devolver al usuario la respuesta con los errores que contiene la petición para que sean verificados y corregidos.

Iniciamos editando el método para agregar un nuevo usuario, dónde actualmente tenemos lo siguiente:

    public function store(Request $request)
    {
        User::create($request->all());
        return ['created' => true];
    }

Vamos a utilizar el validador de Laravel para evaluar los tipos de datos que estamos recibiendo, si no conoces cómo funciona este feature te invito a leer el post Aprende cómo validar datos con Laravel

    public function store(Request $request)
    {
        // Creamos las reglas de validación
        $rules = [
            'name'      => 'required',
            'email'     => 'required|email',
            'password'  => 'required'
            ];

        // Ejecutamos el validador, en caso de que falle devolvemos la respuesta
        $validator = \Validator::make($request->all(), $rules);
        if ($validator->fails()) {
            return [
                'created' => false,
                'errors'  => $validator->errors()->all()
            ];
        }

        User::create($request->all());
        return ['created' => true];
    }

Si la validación falla devolvemos un array con el estado y los errores que se encontraron; esto lo podemos verificar nuevamente utilizando el componente de pruebas de Laravel, agregando la función testValidationErrorOnCreateUser al archivo UserTest.php con el que veníamos trabajando en la lección anterior:

    public function testValidationErrorOnCreateUser()
    {
        $data = $this->getData(['name' => '', 'email' => 'jane']);
        $this->post('/user', $data)->dump();
    }


    public function getData($custom = array())
    {
        $data = [
            //'name'      => 'joe',
            'email'     => '[email protected]',
            'password'  => '12345'
            ];
        $data = array_merge($data, $custom);
        return $data;
    }

dump() nos permite imprimir en pantalla la respuesta obtenida en la petición, en este caso estamos enviando el campo name vacío y para el campo email un valor que no es una cuenta de email válida. Ejecutamos desde la consola:

vagrant@homestead:~/Code/Laravel$ vendor/bin/phpunit

PHPUnit 4.8.6 by Sebastian Bergmann and contributors.

F{#190
  +"created": false
  +"errors": array:2 [
    0 => "The name field is required."
    1 => "The email must be a valid email address."
  ]
}

Muy bien, aparentemente todo funciona como esperamos. Pero debemos tomar en cuenta los posibles errores del servidor, conexión a base de datos, etc, es decir, todos aquellos casos que pueden hacer que el proceso falle. Para ello podemos hacer uso de try-catch de PHP, en caso de que un bloque de código falle guardamos un log del error ocurrido y devolvemos un mensaje al usuario.

    public function store(Request $request)
    {
        if (!is_array($request->all())) {
            return ['error' => 'request must be an array'];
        }
        // Creamos las reglas de validación
        $rules = [
            'name'      => 'required',
            'email'     => 'required|email',
            'password'  => 'required'
            ];

        try {
            // Ejecutamos el validador y en caso de que falle devolvemos la respuesta
            $validator = \Validator::make($request->all(), $rules);
            if ($validator->fails()) {
                return [
                    'created' => false,
                    'errors'  => $validator->errors()->all()
                ];
            }

            User::create($request->all());
            return ['created' => true];
        } catch (Exception $e) {
            \Log::info('Error creating user: '.$e);
            return \Response::json(['created' => false], 500);
        }
    }

Uso de Excepciones

En algunas ocasiones lo más conveniente pueda ser crear respuestas personalizadas dependiendo del tipo de excepción que genere nuestra aplicación, como por ejemplo, lo que ocurre cuando tratamos de buscar a un usuario que no existe en la base de datos. Vamos a colocar el método show en UserController de la siguiente manera:

    public function show($id)
    {
        return User::findOrFail($id);
    }

Cuando usamos el método findOrFail() forzamos a que la aplicación arroje una excepción de tipo ModelNotFoundException, podemos capturar entonces el tipo de excepcion y enviar una respuesta personalizada, esto lo hacemos editando el archivo app/Exceptions/Handler.php

    public function render($request, Exception $e)
    {
        if ($e instanceof ModelNotFoundException) {
            $e = new NotFoundHttpException($e->getMessage(), $e);
            return \Response::json(['error' => 'Model not found'], 404);
        }
        return parent::render($request, $e);
    }

En este caso devolvemos el mensaje de error correspondiente acompañado por el código de respuesta adecuado (404).

Recuerda que todo esto lo puedes verificar usando las pruebas en Laravel

    public function testNotFoundUser()
    {
        $this->get('user/10')->seeJsonEquals(['error' => 'Model not found']);
    }

Esto debería ser suficiente.

vagrant@homestead:~/Code/Laravel$ vendor/bin/phpunit
PHPUnit 4.8.6 by Sebastian Bergmann and contributors.

...

Time: 5.61 seconds, Memory: 20.50Mb

OK (3 tests, 6 assertions)

Actividades

Aplica lo aprendido anteriormente para validar correctamente las funciones de editar y eliminar usuarios.

Recuerda dejar tus dudas en la sección de comentarios, no olvides compartir el contenido en redes sociales.

Material relacionado

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior API REST con Laravel 5.1 - CRUD de usuarios Lección siguiente API REST con Laravel 5.1 - Route Model Binding