{"id":305,"date":"2021-08-23T11:23:00","date_gmt":"2021-08-23T11:23:00","guid":{"rendered":"https:\/\/www.escueladefrikis.com\/?p=305"},"modified":"2021-08-23T11:23:00","modified_gmt":"2021-08-23T11:23:00","slug":"exception-handler-en-laravel-8","status":"publish","type":"post","link":"https:\/\/escueladefrikis.com\/index.php\/2021\/08\/23\/exception-handler-en-laravel-8\/","title":{"rendered":"Exception Handler en Laravel 8"},"content":{"rendered":"\n<p>Laravel est\u00e1 muy enfocado a mostrar p\u00e1ginas mediante templates, pero en mi caso lo estoy utilizando para implementar un API. En este caso, la gesti\u00f3n de excepciones que viene de base en Laravel (aqu\u00ed la <a href=\"https:\/\/laravel.com\/docs\/8.x\/errors\">documentaci\u00f3n oficial<\/a>) se queda un poco coja porque aunque nos permita devolver un c\u00f3digo de error en cualquier momento:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>abort(404);<\/code><\/pre>\n\n\n\n<p>No permite modelar la respuesta de una excepci\u00f3n.<\/p>\n<p>Por tanto, voy a unir todos los puntos que vengo mostrando ya en un par de art\u00edculos, que es poder utilizar <a href=\"https:\/\/www.escueladefrikis.com\/2021\/06\/21\/dto-en-laravel-8\/\">DTOs que validen su propio modelo;<\/a> y para esto necesito <a href=\"https:\/\/www.escueladefrikis.com\/2021\/08\/09\/exception-handler-en-laravel-8-como-se-hace-en-spring-boot\/\">gestionar las excepciones de una manera similar a como se hace en Spring Boot<\/a> en Java (y que es muy simple y muy potente).<\/p>\n<p>Para ello vamos a:<\/p>\n<ul>\n<li>Definir una excepci\u00f3n que devuelva un JSON.<\/li>\n<li>Utilizar la excepci\u00f3n en el DTO<\/li>\n<\/ul>\n<p>Tenemos la suerte que Laravel 8 ya viene con un Handler por defecto y que en la instalaci\u00f3n por defecto podr\u00e9is encontrar en:<\/p>\n<p><span style=\"color: #1e1e1e; font-family: Menlo, Consolas, monaco, monospace; font-size: 15px; white-space: pre-wrap;\">App\\Exceptions\\Handler<\/span><\/p>\n<div>\n<div><span style=\"font-size: inherit;\">Y definiendo una excepci\u00f3n que devuelva un JSON, ya lo tenemos casi hecho.<\/span><\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Definir una excepci\u00f3n que devuelva un JSON<\/h3>\n\n\n\n<p>Lo primero es definir una excepci\u00f3n que podamos lanzar, que a la que le voy a definir 2 atributos: el c\u00f3digo HTTP que tiene que devolver y el mensaje.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-php\" data-lang=\"PHP\"><code>&lt;?php\n\nnamespace App\\Exceptions;\n\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response;\nuse Mockery\\Exception;\n\nclass CustomException extends Exception\n{\n\n  protected $code;\n\n  protected $message;\n\n  public function __construct($code, $message)\n  {\n    $this-&gt;code = $code;\n    $this-&gt;message = $message;\n  }\n\n\n  public function render($request){\n    $response[&#39;message&#39;] = $this-&gt;message;\n    return response()-&gt;json($response, $this-&gt;code);\n  }\n}<\/code><\/pre><\/div>\n\n\n\n<p>Resalto el hecho de que la respuesta que devuelve la excepci\u00f3n mediante el m\u00e9todo \u00abrender\u00bb es un JSON.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Utilizar la excepci\u00f3n en el DTO<\/h3>\n\n\n\n<p>Puede parecer magia, y casi lo es, pero ahora ya podemos utilizar la excepci\u00f3n en cualquier lugar y como quiero validar el modelo del DTO en el propio DTO, hay que modificar:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-php\" data-lang=\"PHP\"><code>class BookStoreRequestBody extends DataTransferObject\n{\n\n  public string $name;\n\n  public string $author;\n\n  public static function fromRequest(Request $request): self\n  {\n    return BookStoreRequestBody::fromArray($request-&gt;all());\n  }\n\n  public static function fromArray($request): self\n  {\n    $validator = Validator::make($request, [\n      &#39;name&#39; =&gt;  &#39;required&#39;,\n      &#39;author&#39; =&gt;  &#39;required&#39;,\n    ]);\n \n    if($validator-&gt;fails()){\n      return response()-&gt;json($validator-&gt;errors(), 400);\n    }\n    return new self([\n      &#39;name&#39; =&gt; $request[&#39;name&#39;],\n      &#39;author&#39; =&gt; $request[&#39;author&#39;],\n    ]);\n  }\n}<\/code><\/pre><\/div>\n\n\n\n<p>La modificamos a:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-php\" data-lang=\"PHP\"><code>class BookStoreRequestBody extends DataTransferObject\n{\n\n  public string $name;\n\n  public string $author;\n\n  public static function fromRequest(Request $request): self\n  {\n    return BookStoreRequestBody::fromArray($request-&gt;all());\n  }\n\n  public static function fromArray($request): self\n  {\n    $validator = Validator::make($request, [\n      &#39;name&#39; =&gt;  &#39;required&#39;,\n      &#39;author&#39; =&gt;  &#39;required&#39;,\n    ]);\n \n    if($validator-&gt;fails()){\n      throw new CustomException(400,&#39;Bad request&#39;);\n    }\n    return new self([\n      &#39;name&#39; =&gt; $request[&#39;name&#39;],\n      &#39;author&#39; =&gt; $request[&#39;author&#39;],\n    ]);\n  }\n}<\/code><\/pre><\/div>\n\n\n\n<p>Y con esto ya estar\u00edamos devolviendo la excepci\u00f3n directamente, ya que esa excepci\u00f3n ser\u00eda capturada por el Handler y devolver\u00eda en la API la respuesta del m\u00e9todo \u00abrender\u00bb.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prueba de la API<\/h3>\n\n\n\n<p>Voy a probar la API ahora con Postman (que viene a ser la mejor aplicaci\u00f3n para probar una API de largo, si alguien conoce alguna mejor est\u00e1 invitado a comentarla) y ver que efectivamente recibo la respuesta:<\/p>\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"327\" src=\"https:\/\/escueladefrikis.com\/wp-content\/uploads\/2021\/08\/image-1-1024x327.png\" alt=\"\" class=\"wp-image-306\" srcset=\"https:\/\/escueladefrikis.com\/wp-content\/uploads\/2021\/08\/image-1-1024x327.png 1024w, https:\/\/escueladefrikis.com\/wp-content\/uploads\/2021\/08\/image-1-300x96.png 300w, https:\/\/escueladefrikis.com\/wp-content\/uploads\/2021\/08\/image-1-768x245.png 768w, https:\/\/escueladefrikis.com\/wp-content\/uploads\/2021\/08\/image-1.png 1270w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Como pod\u00e9is ver, he pasado de tener que validar en el controlador a tener un DTO que modela la petici\u00f3n y que adem\u00e1s incluye la validaci\u00f3n de su propio modelo.<\/p>\n<p>Adem\u00e1s, ya tenemos una excepci\u00f3n que podemos lanzar desde cualquier punto de c\u00f3digo y nos va a dar una respuesta formateada tal y como queremos, en este caso con el c\u00f3digo HTTP y el body JSON con la informaci\u00f3n deseada.<\/p>\n<p>El c\u00f3digo del ejemplo, lo pod\u00e9is ver en <a href=\"https:\/\/github.com\/jormassa\/laravel-api-example\">github<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aprende a crear un gestionar las excepciones y c\u00f3mo modelar su respuesta en Laravel 8. \u00a1Lanza una excepci\u00f3n desde cualquier lugar en tu c\u00f3digo controlando la respuesta!<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,5],"tags":[8,19,22,25,28],"class_list":["post-305","post","type-post","status-publish","format-standard","hentry","category-laravel-8","category-programacion","tag-api","tag-excepciones","tag-laravel","tag-php","tag-rest"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/posts\/305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/comments?post=305"}],"version-history":[{"count":0,"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/posts\/305\/revisions"}],"wp:attachment":[{"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/media?parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/categories?post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/escueladefrikis.com\/index.php\/wp-json\/wp\/v2\/tags?post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}