En el artículo anterior introduje una manera de implementar DTOs para las entradas y salidas (requests y responses) de una API pero quedó coja porque dentro del DTO pretendía validar el modelo.
Antes de ver la solución en Laravel, me gustaría mostrar la solución a la que quiero llegar pero en otro lenguaje y con otro framework: Spring Boot en Java.
Spring Boot permite una gestión bastante simple de las excepciones mediante dos anotaciones:
- @ControllerAdvice: permite definir una clase que gestione las excepciones de manera global.
- @ExceptionHandler: permite definir un método que gestione un tipo de excepción concreto.
Uno de los miles tutoriales que podéis encontrar está en tutorialspoint y muestro un ejemplo en el que defino dos clases:
- NotFoundException: una excepción particular
package com.escueladefrikis.example.exception;
public class NotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
- Una clase que gestione las excepciones y en el que incluyo un método que gestione la excepción que acabo de definir:
package com.escueladefrikis.example.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = NotFoundException.class)
public ResponseEntity<Object> handleNotFoundException(NotFoundException exception) {
return new ResponseEntity<>("Item not found", HttpStatus.NOT_FOUND);
}
}
Ahora, esta excepción la podemos utilizar en cualquier punto en el código, dentro del controlador, dentro del servicio, etc. Cuando lancemos la excepción (si no la capturamos) la respuesta a la llamada al endpoint será la respuesta del método “handleNotFoundException”, que es 404 con el texto “Not found”. Por ejemplo:
package com.escueladefrikis.example.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.escueladefrikis.example.exception.NotFoundException;
import com.escueladefrikis.example.controller.model.Book;
@RestController
public class BooksController {
@RequestMapping(value = "/books/{id}", method = RequestMethod.GET)
public ResponseEntity<Object> getBook(@PathVariable("id") String id) {
return findBook(id);
}
private ResponseEntity<Object> findBook(String id) {
Optional<Book> book = respository.findById(id);
if (book.isEmpty()) {
throw new NotFoundException();
}
// The rest of the code
}
}
Es un ejemplo muy simplificado, pero creo que muestra cuál es la solución que quiero conseguir en Laravel 8. En el siguiente artículo mostraré cómo.