Destripando el nuevo starter Kit de Livewire en Laravel 12

Publicado por Andrés López

Destripando el nuevo starter Kit de Livewire en Laravel 12

Cada que implementan algo nuevo en Laravel me gusta destripar su código fuente, puedes aprender mucho de programación, Laravel e incluso PHP revisando a profundidad lo que otros desarrolladores crean sobre todo los que contribuyen al framework de Laravel.

Vamos a dar un vistazo rápido y para ello tenemos que instalar el starter kit:

laravel new livewire-app

Instalación de livewire starter kit

No olvides correr npm install y npm run dev.

Omitiré el funcionamiento obvio del starter kit, realmente ya sabemos como funciona livewire, la autenticación en Laravel y en general como construir esta lógica, me concentraré en las cosas curiosas que vi y algunas prácticas que podrías implementar en otras secciones de tu aplicación.

¿Forzados a usar Volt?

A primera vista, todo se instala a nivel de aplicación, no existen nuevas dependencias (como ocurría con Laravel UI) más alla de Livewire, podemos ver Volt aunque hayamos prescindido de el durante la instalación, curioso:

// composer.json
"require": {
        "php": "^8.2",
        "laravel/framework": "^12.0",
        "laravel/tinker": "^2.10.1",
        "livewire/flux": "^2.0",
        "livewire/volt": "^1.6.7"
    },
"require-dev": {
    "fakerphp/faker": "^1.23",
    "laravel/pail": "^1.2.2",
    "laravel/pint": "^1.18",
    "laravel/sail": "^1.41",
    "mockery/mockery": "^1.6",
    "nunomaduro/collision": "^8.6",
    "pestphp/pest": "^3.7",
    "pestphp/pest-plugin-laravel": "^3.1"
},

Enrutamiento de Laravel

Una cosa curiosa que vi es este starter kit tiene separadas las rutas de autenticación.

routes/
    auth.php
    web.php
    console.php

No se porque pero lo que hacen para agregar este nuevo archivo a las rutas es mediante un require, no digo que sea malo, pero siempre se puede modificar el archivo bootstrap/app.php para agregar nuevos enrutadores, aquí te muestro como puedes hacerlo sin necesidad del require:

// boostrap/app.php
<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: [
            __DIR__.'/../routes/web.php',
            __DIR__.'/../routes/auth.php' // agrega esta línea        ],
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

El método magico __invoke

Hay una implementación curiosa para crear acciones en PHP, y es gracias al método __invoke, imaginemos que tenemos la siguiente clase:

<?php

namespace App\Livewire\Actions;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;

class Logout
{
    /**
     * Log the current user out of the application.
     */
    public function __invoke()
    {
        Auth::guard('web')->logout();

        Session::invalidate();
        Session::regenerateToken();

        return redirect('/');
    }
}

Te preguntarás como hacemos para llamarla, quiza si...

use App\Livewire\Actions\Logout;

new Logout()->__invoke(); // estamos usando PHP8.4 esto es totalmente normal

Nah, esto se ve horrible ¿no?

Bueno en el nuevo starter kit podemos ver el uso del resolving de la inyección de dependencias de Laravel combinado con el método magico __invoke:

// app/Livewire/Auth/VerifyEmail.php

public function logout(Logout $logout): void
{
    $logout(); // esta definición llama al método __invoke
    $this->redirect('/', navigate: true);
}

Una forma muy elegante de utilizar un patrón actions en tu aplicación.

Cambiar el tema

Aunque esta es una funcionalidad exclusiva de Flux UI me sigue pareciendo muy interesante incluirlo, en uno de los componentes de livewire app/Livewire/Settings/Appearance.php ni siquiera hay código de implementación, sin embargo todo esta en su vista, todo la magia esta en el uso de $flux.appearance, el cual lo manipulan mediante AlpineJS y este valor se guarda en el localStorage del navegador.

<div class="flex flex-col items-start">
    @include('partials.settings-heading')

    <x-settings.layout :heading="__('Appearance')" :subheading=" __('Update the appearance settings for your account')">
        <flux:radio.group x-data variant="segmented" x-model="$flux.appearance">
            <flux:radio value="light" icon="sun">{{ __('Light') }}</flux:radio>
            <flux:radio value="dark" icon="moon">{{ __('Dark') }}</flux:radio>
            <flux:radio value="system" icon="computer-desktop">{{ __('System') }}</flux:radio>
        </flux:radio.group>
    </x-settings.layout>
</div>

En caso de que requieras acceder sin el uso de AlpineJS, puedes hacerlo de la siguiente manera:

console.log(window.Flux.appearance)
window.Flux.appearance = 'system'
window.Flux.appearance = 'dark'
window.Flux.appearance = 'light'

Manejo de validaciones en Livewire

Dentro del archivo app/Livewire/Settings/Password.php podemos encontrar código muy interesante, por ejemplo la validación de campos, explicación rápida: cuando trabajamos con validación autómatica en Laravel lo que realmente esta pasando es que internamente Laravel esta lanzando excepciones cada que se llama el método validate y los campos no son correctos en base a las reglas de validación que definimos, por eso se siente tan mágico que automáticamente el usuario pueda recibir feedback haciendo tan poco desarrollo.

Y, como habrás imaginado, si manejamos excepciones, podemos atraparlas en un try catch, y justo es lo que lo hace tan interesante este código, porque aprovechan la funcionalidad de PHP, Laravel y Livewire

  1. Hace un try catch para atrapar las excepciones de tipo Illuminate\Validation\ValidationException (PHP)
  2. Valida los campos mediante la función validate (Laravel)
  3. Limpia los campos de contraseña por seguridad (Livewire)
  4. Vuelve a arrojar la excepción atrapada previamente (PHP)
  5. Muestra los mensajes de error de validación al usuario (Laravel)
use Illuminate\Validation\ValidationException;

public function updatePassword(): void
{
    try {
        $validated = $this->validate([
            'current_password' => ['required', 'string', 'current_password'],
            'password' => ['required', 'string', PasswordRule::defaults(), 'confirmed'],
        ]);
    } catch (ValidationException $e) {
        $this->reset('current_password', 'password', 'password_confirmation');

        throw $e;
    }
}

Definitivamente una implementación tan corta pero tan poderosa.

Te invito a probar este starter kit y a aprender de Livewire, eso sí no olvides que si piensas usar Livewire en una aplicación sería, sí o sí tendrás que usar AlpineJS para hacer buenas interacciones, tiempos de respuestas y experiencias de usuario dignas de un buen desarrollador.

Andrés López

Andrés López

Gran fan de Laravel, entusiasta de Vue y escritor de cualquier cosa que suene interesante