-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
edad3e4
commit 5172132
Showing
8 changed files
with
313 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
extends: _layouts.post | ||
section: content | ||
title: "Novedades de Laravel 7" | ||
date: 2020-02-28 | ||
description: "Como en cada nueva versión, Laravel 7 nos trae una serie de nuevas funciones y mejoras. Esta lista pretende resaltar cada una de estas novedades, mejoras y correcciones." | ||
cover_image: /assets/images/posts/0021/0021-novedades-laravel-7.png | ||
featured: true | ||
categories: [laravel, php, programming, series] | ||
--- | ||
|
||
Este **3 de marzo** se realizará el lanzamiento oficial de **Laravel 7**. Como en cada nueva versión, Laravel nos trae una serie de nuevas funciones y mejoras. Esta lista pretende resaltar -en lo posible- cada una de estas. | ||
|
||
Entre las novedades que Laravel nos trae en esta versión, tenemos: | ||
|
||
- [Laravel Airlock: Autenticación ligera para SPAs y APIs](/blog/0019-laravel-airlock-autenticacion-ligera-para-spas-y-apis) | ||
- [Mejoras en el enlazado de modelos a rutas (_Route Model Binding_)](/blog/0022-novedades-de-laravel-7-mejoras-en-el-enlazado-de-modelos-a-rutas) | ||
- [Cliente HTTP](/blog/0023-novedades-de-laravel-7-cliente-http) | ||
- _Operaciones fluidas trabajando con Strings_ | ||
- _Múltiples drivers para emails_ | ||
- _Casting personalizado en Eloquent (Eloquent Custom Casts)_ | ||
- _Etiquetas en componentes Blade y mejoras_ | ||
- _Mejoras de rendimiento en el cacheo de Rutas (Route Caching)_ | ||
- _Soporte nativo para CORS_ | ||
- _Casting en tiempo de Ejecución (Query time casts)_ | ||
- _Mejoras de rendimiento en el manejo de Colas en MySQL 8+_ | ||
- _Comando ``test`` de Artisan_ | ||
- _Mejora en las plantillas Markdown para Emails_ | ||
- _Markdown Mail Template Improvements_ | ||
- _Personalización de Stubs_ | ||
|
||
> Las referencias a este listado se irán actualizando a medida que se publiquen más artículos. | ||
---- | ||
|
||
## Cierre | ||
|
||
Como podrás notar, Laravel 7 no se queda atrás a la hora de **incluir novedades**. De hecho -según el mismo Taylor Otwell- esta versión es de las que más funcionalidad introducirá en comparación con los lanzamientos de los últimos años. | ||
|
||
<div> | ||
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">I think you have to go back to Laravel 5.5 (August 2017) to find a Laravel release as nice as Laravel 7.x will be. 🏄♂️ Hear about it at <a href="https://twitter.com/LaraconOnline?ref_src=twsrc%5Etfw">@LaraconOnline</a></p>— Taylor Otwell 🏝 (@taylorotwell) <a href="https://twitter.com/taylorotwell/status/1222551807907586048?ref_src=twsrc%5Etfw">January 29, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> | ||
</div> |
104 changes: 104 additions & 0 deletions
104
..._posts/0022-novedades-de-laravel-7-mejoras-en-el-enlazado-de-modelos-a-rutas.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
--- | ||
extends: _layouts.post | ||
section: content | ||
title: "Novedades de Laravel 7: Mejoras en el enlazado de modelos a rutas" | ||
date: 2020-02-28 | ||
description: "Como en cada nueva versión, Laravel 7 nos trae una serie de nuevas funciones y mejoras. En este artículo destacaremos las mejoras hacia el enlazado de modelos a rutas (Route Model Binding)." | ||
cover_image: /assets/images/posts/0022/0022-novedades-laravel-7-mejoras-en-el-enlazado-de-modelos-a-rutas.png | ||
featured: false | ||
categories: [laravel, php, programming] | ||
--- | ||
|
||
Como en cada nueva versión, Laravel 7 nos trae una serie de nuevas funciones y mejoras. En este artículo destacaremos las mejoras hacia el **enlazado de modelos a rutas** (_Route Model Binding_). | ||
|
||
------ | ||
|
||
Este artículo pertenece a la serie [Novedades de Laravel 7](/blog/0021-novedades-de-laravel-7). Puedes leer sobre el resto de las características introducidas en esta versión [aquí](/blog/0021-novedades-de-laravel-7). | ||
|
||
----- | ||
|
||
### Enlazado implícito de Modelos a Rutas | ||
|
||
Desde versiones anteriores (v5.2+) Laravel nos da la posibilidad de **enlazar implícitamente modelos a parámetros de rutas** (_Route Model Binding_). Laravel realiza esto deduciendo el nombre del modelo desde la definición de la ruta en sí. | ||
|
||
Antes de la introducción de esta funcionalidad en aquella versión, teníamos que hacer más trabajo. Por ejemplo, para una ruta que muestre el detalle de una **tienda**, hubiéramos hecho: | ||
|
||
# routes/web.php | ||
|
||
Route::get('stores/{id}', 'StoreController@show'); | ||
|
||
Por lo que luego, tenías que buscar el objeto en cuestión inyectando el ``$id`` para finalmente hacer la consulta directamente en el controlador: | ||
|
||
# app/Http/Controllers/StoreController.php | ||
|
||
public function show ($id) | ||
{ // ^^^^ | ||
$store = Store::find($id); | ||
return $store; | ||
} | ||
|
||
Con la introducción del **enlazado implícito de modelos en rutas** -en Laravel 5.2-, esto se facilitó. Tan solo hacía falta modificar la ruta de la siguiente manera: | ||
|
||
Route::get("stores/{store}", 'StoreController@show'); | ||
|
||
De este modo, Laravel intentará encontrar un modelo que corresponda con el parámetro de ruta (``Store``), pudiendo así resolver el modelo e inyectarlo hacia nuestro controlador: | ||
|
||
public function show (Store $store) | ||
{ // ^^^^^ | ||
return $store; // <-- | ||
} | ||
|
||
Sin embargo, **¿qué pasa si no queremos buscar por la llave primaria del modelo -típicamente el ``id``- sino por alguna otra columna?** | ||
|
||
Tomemos el caso de un **Artículo** (modelo ``Post``). Quizás querríamos buscar por el ``slug`` del título, en lugar del ``id`` del artículo en sí. Previo a Laravel 7, se le tenía que indicar a nuestro modelo cómo es que debía de resolver estos enlazados implícitos: | ||
|
||
# app/Post.php | ||
|
||
public function getRouteKeyName() | ||
{ | ||
return 'slug'; // <-- nombre del atributo/columna | ||
} | ||
|
||
El detalle de esta solución es que este cambio **regirá para todas las rutas** que quieran resolver modelos ``Post``. Entonces, ¿qué sucede si en otro lugar de nuestra aplicación, necesitamos buscar por un campo **distinto** a ``slug``? Quizás en el administrador deseamos ahora sí buscar por ``id`` o por ``uuid``. En fin, nos obligaba a volver a la solución inicial, buscando manualmente en cada método que lo necesite. | ||
|
||
Esto quedará en el pasado con las nuevas versiones de Laravel. | ||
|
||
### Mejoras en Laravel 7 | ||
|
||
En Laravel 7, si queremos resolver el modelo por **algún campo en específico distinto al de la llave primaria**, tan solo tenemos que indicarlo en la misma definición de la ruta con la notación ``:columna``. Veamos un ejemplo: | ||
|
||
Route::get("posts/{post:slug}", 'PostController@show'); | ||
// ^^^^^^^^^ | ||
|
||
Así de simple. Ahora, lo _cool_ de esto es que nos da la flexibilidad de poder definir distintas rutas con diferentes modo de resolución de manera simple: | ||
|
||
Route::get('posts/{post:slug}', 'PostController@show'); | ||
// ^^^^^^^^^ | ||
Route::get('admin/posts/{post:uuid}', 'AdminPostController@show'); | ||
// ^^^^^^^^^ | ||
|
||
Genial. | ||
|
||
### Filtros automáticos | ||
|
||
Hay escenarios en los cuales implícitamente enlazas múltiples modelos en una misma definición de ruta, **y quieres filtrar los resultados de uno respecto del otro**. Tomemos el caso de un **autor** (``Author``) con sus **artículos** (``Post``). | ||
|
||
Route::get("authors/{author}/posts/{post:slug}", "AuthorPostController@index"); | ||
// ^^^^^^ ^^^^^^^^^ | ||
|
||
En Laravel 7, cuando uses una llave personalizada para resolver modelos implícitamente, automáticamente se aplicará un filtro (Query scope) tratando de deducir el nombre de las relaciones entre ambos modelos. | ||
|
||
En el ejemplo anterior, Laravel intentará buscar la relación ``posts()`` en el modelo ``Author``, de este modo al tratar de resolver los artículos/_posts_ de un author en específico, internamente **aplicará un filtro para limitar los resultados del segundo modelo, respecto del primero**. Entonces, solo recibiremos los artículos/_posts_ que **pertenezcan** a ese autor en específico. | ||
|
||
Esto es particularmente útil pues, personalmente he tenido situaciones de este tipo y siempre suelo colocar un _check_ adicional al recibir los modelos para garantizar que efectivamente estén vinculados. Siempre puede suceder el caso en el que un usuario pueda querer acceder a realizar operaciones en los recursos a los cuales no debería tener acceso. | ||
|
||
Para leer más detalles sobre esta sección, visita [esta sección](https://laravel.com/docs/master/routing#route-model-binding) de la documentación oficial. | ||
|
||
----- | ||
|
||
## Cierre | ||
|
||
Como puedes notar, este pequeño -pero interesante- cambio nos puede ahorrar unas cuantas líneas de código extra que ahora podremos dedicar a mejorar nuestra lógica de negocio. | ||
|
||
Si te interesó esta nueva funcionalidad, no olvides leer el resto de novedades que trae Laravel 7 ([aquí](/blog/0021-novedades-de-laravel-7)), ya que tenemos [una serie de artículos -"Novedades de Laravel 7"-](/blog/0021-novedades-de-laravel-7) dedicados a este tema. |
158 changes: 158 additions & 0 deletions
158
...des-de-laravel-7-el-nuevo-facade-http-consultas-nativas-a-servicios-externos.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
--- | ||
extends: _layouts.post | ||
section: content | ||
title: "Novedades de Laravel 7: Cliente HTTP" | ||
date: 2020-02-28 | ||
description: "Como en cada nueva versión, Laravel 7 nos trae una serie de nuevas funciones y mejoras. En este artículo destacaremos la integración de Laravel con Zttp bajo el nuevo facade HTTP." | ||
cover_image: /assets/images/posts/0023/0023-novedades-de-laravel-7-el-nuevo-facade-http-consultas-nativas-a-servicios-externos.png | ||
featured: false | ||
categories: [laravel, php, programming] | ||
--- | ||
|
||
Como en cada nueva versión, Laravel 7 nos trae una serie de nuevas funciones y mejoras. En este artículo destacaremos la integración de Laravel con [Zttp](https://github.com/kitetail/zttp) -que a su vez es un wrapper de [Guzzle](https://github.com/guzzle/guzzle)- bajo el nuevo _facade_ **HTTP**. | ||
|
||
------ | ||
|
||
Este artículo pertenece a la serie [Novedades de Laravel 7](/blog/0021-novedades-de-laravel-7). Puedes leer sobre el resto de las características introducidas en esta versión [aquí](/blog/0021-novedades-de-laravel-7). | ||
|
||
----- | ||
|
||
Esta nueva fachada **HTTP** no es nada más que un wrapper de la popular librería **Guzzle**, con una API más familiar e intuitiva. Ofrece también, una manera fácil de aplicarla en nuestras pruebas unitarias y de integración. | ||
|
||
### Haciendo requests | ||
|
||
Escribir una llamada hacia un endpoint exterior es tan simple como: | ||
|
||
use Illuminate\Support\Facades\Http; | ||
|
||
$response = Http::get('http://la-url-del-servicio.com'); | ||
|
||
Este método retornará una instancia de ``Illuminate\Http\Client\Response`` la cual proveerá una serie de métodos que te permitirán inspeccionar la respuesta. | ||
|
||
$response->body() : string; | ||
$response->json() : array; | ||
$response->status() : int; | ||
$response->ok() : bool; | ||
$response->successful() : bool; | ||
$response->serverError() : bool; | ||
$response->clientError() : bool; | ||
$response->header($header) : string; | ||
$response->headers() : array; | ||
|
||
Esta clase también implementa la interfaz ``ArrayAccess``, por lo que puedes acceder a la data de la respuesta JSON directamente desde la respuesta: | ||
|
||
return Http::get('http://la-url-del-servicio.com/users/1')['phone_number']; | ||
// ^^^^^^^^^^^^^^ | ||
|
||
Cuando requieras enviar cierta información adicional al momento de realizar consulta de tipo ``POST``, ``PUT``, ``PATCH``, puedes realizarlo fácilmente pasando data como segundo argumento: | ||
|
||
$response = Http::post('http://la-url-del-servicio.com/users', [ | ||
'name' => 'Kenny', | ||
'role' => 'Titán', | ||
]); | ||
|
||
> Con la misma facilidad, puedes explorar las opciones para hacer [Requests con data codificada en la Url](https://laravel.com/docs/master/http-client#request-data) y [Requests Multi-part](https://laravel.com/docs/master/http-client#request-data). | ||
### Autenticación | ||
|
||
El **_facade_ HTTP** también nos provee una manera cómoda de manejar la **autenticación de nuestras peticiones** cuando hagamos consultas a servicios externos. Para esto, tenemos disponible tres formas de autenticación: Básica, _Digest_ y mediante un _Bearer_ token. | ||
|
||
// Basic auth | ||
$response = Http::withBasicAuth('kennyhorna@gmail.com', 'mi-clave')->post(...); | ||
|
||
// Digest auth | ||
$response = Http::withDigestAuth('kennyhorna@gmail.com', 'mi-clave')->post(...); | ||
|
||
// Mediante un token | ||
$response = Http::withToken('mi-token')->post(...); | ||
|
||
### Cabeceras | ||
|
||
Del mismo modo, podemos añadir cabeceras de esta forma: | ||
|
||
$response = Http::withHeaders([ | ||
'X-una-cabecera' => 'valor-1', | ||
'X-otra-cabecera' => 'valor-2' | ||
])->post('http://la-url-del-servicio.com/users', [ | ||
'name' => 'Lilly Collins', | ||
]); | ||
|
||
### Manejo de errores | ||
|
||
Una de las principales diferencias del uso del **_facade_ HTTP** y de Guzzle es que este último arroja una excepción si es que algo anda mal (errores ``4XX`` y ``5XX``). HTTP no lo hará por defecto, sino que te ofrece distintas formas de tratar los errores dependiendo de cómo quieras manejarlos. De este modo, podemos **consultar** a la respuesta de nuestra petición si es que todo marchó bien o si es que hubo algún error: | ||
|
||
// Determina si el código de respuesta es >= 200 y < 300... | ||
$response->successful(); | ||
|
||
// Determina si el código de respuesta es de nivel 400... | ||
$response->clientError(); | ||
|
||
// Determina si el código de respuesta es de nivel 500... | ||
$response->serverError(); | ||
|
||
Si lo que prefieres es que se arroje una **excepción** (instancia de ``Illuminate\Http\Client\RequestException``), puedes realizar lo siguiente: | ||
|
||
$response = Http::post(...); | ||
|
||
// Arrojar una excepción si es que hubo algún error.. | ||
$response->throw(); | ||
|
||
return $response['data']; | ||
|
||
> Puedes leer más sobre el manejo de errores en [esta](https://laravel.com/docs/master/http-client#error-handling) sección de la documentación. | ||
### Pruebas | ||
|
||
Al igual que muchas funcionalidades de Laravel, esta no es la excepción. El **facade HTTP** nos permite **simular** estas peticiones externas y retornar **fake data**, para que podamos correr nuestras pruebas sin necesidad de realizar peticiones externas. | ||
|
||
Para falsear una petición y respuesta, solo necesitamos invocar al método ``fake()`` antes de la lógica de nuestra prueba: | ||
|
||
use Illuminate\Support\Facades\Http; | ||
|
||
Http::fake(); | ||
|
||
$response = Http::post(...); | ||
|
||
Si es que necesitamos simular peticione a distintos servicios -los cuales deberían retornar distinta data- podemos indicarlo pasando un arreglo de elementos a este método ``fake``: | ||
|
||
Http::fake([ | ||
// Falseamos peticiones hacia endpoints de Facebook... | ||
'facebook.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']), | ||
|
||
// Falseamos peticiones hacia endpoints de Twitter... | ||
'twitter.com/*' => Http::response('Hello World', 200, ['Headers']), | ||
]); | ||
|
||
> Puedes leer más sobre la **simulación de peticiones** [en esta sección](https://laravel.com/docs/master/http-client#faking-responses) de la documentación. | ||
#### Inspeccionando respuestas | ||
|
||
Si lo que necesitas es **asegurarte** de que estás enviando toda la información necesaria y adecuada en tus peticiones, puedes realizar estas validaciones mediante el método ``assetSent(...)`` (luego de haber invocado ``fake()``). Veamos un ejemplo. | ||
|
||
// Activando la simulación de peticiones.. | ||
Http::fake(); | ||
|
||
// Realizando nuestra consulta.. | ||
Http::withHeaders([ | ||
'X-First' => 'foo', | ||
])->post('http://la-url-del-servicio.com/users', [ | ||
'name' => 'Kenny', | ||
'role' => 'author', | ||
]); | ||
|
||
// Verificando que se envió la data correcta.. | ||
Http::assertSent(function ($request) { | ||
return $request->hasHeader('X-First', 'foo') && | ||
$request->url() == 'http://la-url-del-servicio.com/users' && | ||
$request['name'] == 'Kenny' && | ||
$request['role'] == 'author'; | ||
}); | ||
|
||
|
||
----- | ||
|
||
## Cierre | ||
|
||
La introducción del soporte de **peticiones HTTP** de manera **nativa** (si bien sea mediante un _wrapper_ de una de las librerías más utilizadas para estas tareas) hace más robusto aún a Laravel. Definitivamente la implementaré en mis proyectos, pues me atrae sobretodo la manera fácil de poder **integrarla a mis pruebas de software**. Ya ahondaremos en esto en una **futura serie dedicada a esta interesante práctica** ;). | ||
|
||
Si te interesó esta nueva funcionalidad, no olvides leer **el resto de novedades que trae Laravel 7** ([aquí](/blog/0021-novedades-de-laravel-7)), ya que tenemos [una serie de artículos -"Novedades de Laravel 7"-](/blog/0021-novedades-de-laravel-7) dedicados a este tema. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+17.6 KB
...sts/0022/0022-novedades-laravel-7-mejoras-en-el-enlazado-de-modelos-a-rutas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+20.4 KB
...es-de-laravel-7-el-nuevo-facade-http-consultas-nativas-a-servicios-externos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.