Laravel 9 - Cambios en español

laravel 19 de mar. de 2022

Laravel 9

Como ya sabrán, Laravel hizo la transición a lanzamientos anuales con el lanzamiento de Laravel 8. Anteriormente, las versiones principales se lanzaban cada 6 meses. Esta transición tiene como objetivo aliviar la carga de mantenimiento de la comunidad y desafiar al equipo de Laravel a ofrecer nuevas funciones sorprendentes y potentes sin introducir cambios importantes.

Laravel 9 sigue las mejoras realizadas en Laravel 8.x introduciendo soporte para los componentes 6.0 de Symfony, Symfomny Mailer, Flysystem 3.0, mejoras de salida en route:list, un driver de Laravel Scout para la base de datos, una sintáxis nueva para accesors/mutators, la posibilidad de usar Enums en las rutas implicitas, y una variedad de otras correcciones y mejoras de usabilidad.

PHP 8.0

Laravel 9.x requiere mínimo PHP 8.0.

Symfony Mailer

Versiones anteriores de Laravel usaban la librería Swift Mailer para enviar email. Esa librería no tiene más mantenimiento y ahora fue reemplazada por Symfony Mailer.

Flysystem 3.x

Laravel 9.x actualiza la dependencia de Flysystem a la 3.x.
Flysystem se encarga de todas las interacciones con el sistema de archivos ofrecidos por la fachada Storage.

Mejoras en los Accessors / Mutators de Eloquent

Laravel 9.x ofrece una nueva forma de definir accesors y mutators en Eloquent. En versiones previas de Laravel, la única forma de definirlos era mediante métodos prefixeados en tu modelo:

public function getNameAttribute($value)
{
    return strtoupper($value);
}

public function setNameAttribute($value)
{
    $this->attributes['name'] = $value;
}

Sin embargo, en Laravel 9.x puedes definir accessors y mutators usando un método único, sin prefixes, usando Attribute como type-hint.

use Illuminate\Database\Eloquent\Casts\Attribute;

public function name(): Attribute
{
    return new Attribute(
        get: fn ($value) => strtoupper($value),
        set: fn ($value) => $value,
    );
}

Además, este nuevo enfoque permite definir accesors que se pueden cachear, mejorando el rendimiento:

use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;

public function address(): Attribute
{
    return new Attribute(
        get: fn ($value, $attributes) => new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two'],
        ),
        set: fn (Address $value) => [
            'address_line_one' => $value->lineOne,
            'address_line_two' => $value->lineTwo,
        ],
    );
}

Casting de atributos a Enums

Solo disponible para PHP 8.1+.

Eloquent ahora te permite castear tus atributos a Enums definidos en PHP.
Para lograr esto, puedes especificar un atributo y un Enum al que quieres transformarlo en el array $casts de tu modelo:

use App\Enums\ServerStatus;

/**
 * The attributes that should be cast.
 *
 * @var array
 */
protected $casts = [
    'status' => ServerStatus::class,
];

Una vez que definiste el cast para tu modelo, el atributo especificado será automaticamente transformado desde y hacia el Enum elegido:

if ($server->status == ServerStatus::provisioned) {
    $server->status = ServerStatus::ready;

    $server->save();
}

Parámetros en rutas implicitas con Enums

PHP 8.1 introduce soporte para Enums. Laravel 9 agrega la habilidad de usar un Enum como type-hint en la definición de tu ruta y Laravel solo invocara la ruta si ese segmento corresponde a un Enum valido. De otra forma, devuelve un 404.
Por ejemplo, dado el siguiente Enum:

enum Category: string
{
    case Fruits = 'fruits';
    case People = 'people';
}

Puedes definir una ruta que solo será invocada si el segmento {category} de la ruta es "fruits" o "people". De otra manera, se devolverá una respuesta 404:

Route::get('/categories/{category}', function (Category $category) {
    return $category->value;
});

Limitación forzada de Route Bindings (uniones de ruta)

En versiones anteriores de Laravel, podías limitar el segundo modelo de Eloquent en la definición de una ruta como el hijo del modelo anterior.
Por ejemplo, considera la siguiente definición de una ruta que recibe un blog post por slug de un usuario específico:

use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

Cuando se usa una clave implicita para hacer la unión como un parámetro anidado, Laravel automáticamente limita la consulta para recuperar el modelo anidado usando convenciones para adivinar la relación entre el hijo y el padre.
Sin embargo, este comportamiento estaba soportado previamente por Laravel solo cuando se usaba una clave personalizada para limitar la ruta hijo (slug en este caso).

Ahora, en Laravel 9, puedes indicar a Laravel que limite el "hijo" incluso cuando no hay una clave personalizada definida. Para hacer esto, puedes invocar el método scopeBindings cuando defines la ruta:

use App\Models\Post;
use App\Models\User;

Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

O, puedes indicar a un grupo entero de definiciones de ruta a usar uniones limitadas:

Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
        return $post;
    });
});

Controladores para grupos de rutas

Ahora puede usar el método controller para definir un controlador común para todas las rutas dentro del grupo. Luego, al definir las rutas, solo necesitas proporcionar el Controller que invocan:

use App\Http\Controllers\OrderController;

Route::controller(OrderController::class)->group(function () {
    Route::get('/orders/{id}', 'show');
    Route::post('/orders', 'store');
});

Búsquedas de texto completo para índices y consultas where

Al usar MySQL o PostgreSQL, ahora se puede agregar el método fullText a las definiciones de columna para generar índices de texto completo:

$table->text('bio')->fullText();

Además, los métodos whereFullText y orWhereFullText se pueden usar para agregar cláusulas "where" de texto completo a una consulta de columnas que tienen índices de texto completo. Laravel transformará estos métodos en el SQL apropiado para el sistema de base de datos subyacente. Por ejemplo, se generará una cláusula MATCH AGAINST para aplicaciones que utilicen MySQL:

$users = DB::table('users')
           ->whereFullText('bio', 'web developer')
           ->get();

Motor de base de datos de Laravel Scout

Si su aplicación interactúa con bases de datos pequeñas o medianas o tiene una carga de trabajo liviana, ahora puede usar el motor de "base de datos" de Scout en lugar de un servicio de búsqueda dedicado como Algolia o MeiliSearch. El motor de la base de datos utilizará cláusulas whereLike e índices de texto completo cuando filtre los resultados de su base de datos existente para determinar los resultados de búsqueda aplicables para su consulta.

Para aprender más sobre el motor de base de datos Scout, consulte la documentación de Scout.

Renderizar plantillas Blade en línea

A veces, es posible que deba transformar una cadena de plantilla Blade sin procesar en HTML válido. Puede lograr esto utilizando el método de renderizado proporcionado por la fachada de Blade. El método de representación acepta la cadena de plantilla Blade y una matriz opcional de datos para proporcionar a la plantilla:

use Illuminate\Support\Facades\Blade;

return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

De manera similar, el método renderComponent se puede usar para representar un componente de clase dado pasando la instancia del componente al método:

use App\View\Components\HelloComponent;

return Blade::renderComponent(new HelloComponent('Julian Bashir'));

Método corto para nombres de Slots

En versiones anteriores de Laravel, los nombres de los slots se proporcionaban mediante un atributo de nombre en la etiqueta x-slot:

<x-alert>
    <x-slot name="title">
        Server Error
    </x-slot>

    <strong>Whoops!</strong> Something went wrong!
</x-alert>

Sin embargo, a partir de Laravel 9.x, puede especificar el nombre de la ranura usando una sintaxis conveniente y más corta:

<x-slot:title>
    Server Error
</x-slot>

Directivas Blade para Selected y Checked

Para mayor comodidad, ahora puede usar la directiva @checked para indicar fácilmente si una entrada de casilla de verificación HTML determinada está "marcada". Esta directiva se repetirá si la condición proporcionada se evalúa como verdadera:

<input type="checkbox"
        name="active"
        value="active"
        @checked(old('active', $user->active)) />

Del mismo modo, la directiva @selected se puede usar para indicar si una determinada opción de selección debe ser "seleccionada":

<select name="version">
    @foreach ($product->versions as $version)
        <option value="{{ $version }}" @selected(old('version') == $version)>
            {{ $version }}
        </option>
    @endforeach
</select>

Bootstrap 5 Pagination Views

Laravel ahora incluye vistas de paginación creadas con Bootstrap 5. Para usar estas vistas en lugar de las vistas predeterminadas de Tailwind, puede llamar al método useBootstrapFive del paginador dentro del método boot de su clase App\Providers\AppServiceProvider:

use Illuminate\Pagination\Paginator;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Paginator::useBootstrapFive();
}

Mejoras de validación para datos en matrices anidadas

A veces, es posible que necesite acceder al valor de un elemento de matriz anidado determinado al asignar reglas de validación al atributo. Ahora puede lograr esto usando el método Rule::forEach. El método forEach acepta una función de clausura que se invocará para cada iteración del atributo de matriz siendo validado, y recibirá el valor del atributo y el nombre de atributo explícito y completamente expandido. La función de clausura debe devolver una matriz de reglas para asignar al elemento de la matriz:

use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$validator = Validator::make($request->all(), [
    'companies.*.id' => Rule::forEach(function ($value, $attribute) {
        return [
            Rule::exists(Company::class, 'id'),
            new HasPermission('manage-company', $value),
        ];
    }),
]);

API de Laravel Breeze y Next.js

El kit de inicio de Laravel Breeze ha recibido un modo "API" de scaffolding/andamiaje y una implementación de frontend complementaria de Next.js. Este kit inicial se puede usar para poner en marcha sus aplicaciones Laravel que sirven como backend a través de una API autenticada de Laravel Sanctum para una interfaz de JavaScript.

Página de excepción Ignition mejorada

Ignition, la página de depuración de excepciones de código abierto creada por Spatie, se ha rediseñado desde cero. El nuevo y mejorado Ignition viene con Laravel 9.x e incluye temas claro/oscuro, funcionalidad personalizable de "abrir en el editor" y más.

Mejoras en la salida del comando de CLI `route:list``

La salida de CLI de route:list se ha mejorado significativamente para la versión Laravel 9.x, lo que ofrece una hermosa experiencia nueva al explorar las definiciones de ruta.

Cobertura de pruebas con el comando test de Artisan

El comando test de Artisan recibió una nueva opción --coverage que puede usar para explorar la cantidad de cobertura de código que sus pruebas brindan a su aplicación:

php artisan test --coverage

Los resultados de la cobertura de la prueba se mostrarán directamente en la salida de la CLI.

Además, si desea especificar un umbral mínimo que debe cumplir el porcentaje de cobertura de su prueba, puede usar la opción --min. La suite de pruebas fallará si no se alcanza el umbral mínimo dado:

php artisan test --coverage --min=80.3

Servidor de Echo: Soketi

Aunque no es exclusivo de Laravel 9.x, Laravel ha ayudado recientemente con la documentación de Soketi, un servidor Web Socket compatible con Laravel Echo escrito para Node.js. Soketi ofrece una excelente alternativa de código abierto a Pusher y Ably para aquellas aplicaciones que prefieren administrar su propio servidor Web Socket.

Para obtener más información sobre el uso de Soketi, consulte la documentación de transmisión y la documentación de Soketi.

Mejor soporte del IDE para Colecciones

Laravel 9.x agrega definiciones "genéricas" mejoradas al componente de colecciones, mejorando el soporte de análisis estático y IDE. Los IDE como PHPStorm o las herramientas de análisis estático como PHPStan ahora comprenderán mejor las colecciones de Laravel de forma nativa.

Nuevos helpers

Laravel 9.x presenta dos funciones helpers nuevas y convenientes que puede usar en su propia aplicación.

str

La función str devuelve una nueva instancia de Illuminate\Support\Stringable para el string dado.
Esta función es equivalente al método Str::of:

$string = str('Taylor')->append(' Otwell');

// 'Taylor Otwell'

Si no se proporciona ningún argumento a la función str, la función devuelve una instancia de Illuminate\Support\Str:

$snake = str()->snake('LaravelFramework');

// 'laravel_framework'

to_route

La función to_route genera una respuesta HTTP de redirección para una ruta con nombre determinada, lo que proporciona una forma expresiva de redirigir a rutas con nombre desde sus rutas y controladores:

return to_route('users.show', ['user' => 1]);

Si es necesario, puede pasar el código HTTP que debe asignarse a la redirección y cualquier encabezado de respuesta adicional como el tercer y cuarto argumento del método to_route:

return to_route('users.show', ['user' => 1], 302, ['X-Framework' => 'Laravel']);

Etiquetas

¡No dejes que nos quedemos dormidos 😴, invitanos un cafecito!

Invitame un café en cafecito.app
¡Genial! Te has suscrito con éxito.
¡Genial! Ahora, completa el checkout para tener acceso completo.
¡Bienvenido de nuevo! Has iniciado sesión con éxito.
Éxito! Su cuenta está totalmente activada, ahora tienes acceso a todo el contenido.