Inicio Blog Página 3

Guía de Laravel 12 con caso de uso de ejemplo

0

Aunque han pasado unos días desde que en febrero se lanzó Laravel 12 (tal como anunciamos en nuestro anterior post), hemos querido hacer un repaso especial a las novedades que esta nueva versión nos presenta. Para ello, además de mostrarte las principales mejoras, te presentamos un caso de uso realista en el que hemos aplicado las nuevas funcionalidades. Esta guía de Laravel 12 te ayudará a comprender mejor las nuevas características y cómo aplicarlas en tu próximo proyecto.

¿Quieres ver el anuncio oficial? Puedes consultar la noticia del lanzamiento de Laravel 12 aquí.

Novedades principales de Laravel 12

Laravel 12 trae principalmente mejoras incrementales que facilitan el trabajo diario de los desarrolladores:

  • Uso de UUID v7 como identificadores únicos ordenados cronológicamente.
  • Nuevo método nestedWhere() en el Query Builder para simplificar consultas complejas.
  • Validación mejorada de archivos, especialmente restringiendo imágenes SVG por defecto.
  • Ejecución paralela optimizada usando Concurrency::run() manteniendo claves asociativas.
  • Colecciones con saltos en range(), permitiendo definir pasos personalizados.
  • Starter Kits renovados con autenticación avanzada lista para usar.

Todo esto se explica con ejemplos en esta guía Laravel 12, pensada para que puedas aplicarlo fácilmente en tus proyectos.

Caso de uso: Aplicación «Gestor de Tareas» usando Laravel 12

Instalación del proyecto

composer create-project laravel/laravel:^12.0 gestor-tareas
npm install && npm run dev
php artisan migrate
php artisan storage:link

Migración para tareas

// database/migrations/create_tasks_table.php
public function up() {
    Schema::create('tasks', function (Blueprint $table) {
        $table->uuid('id')->primary(); // UUID v7 por defecto en Laravel 12
        $table->foreignId('user_id')->constrained()->cascadeOnDelete();
        $table->string('titulo');
        $table->text('descripcion')->nullable();
        $table->string('imagen_path')->nullable();
        $table->timestamps();
    });
}

La columna id usa UUID v7 automáticamente gracias al trait HasUuids, como te sugerimos en esta guía de Laravel 12.

Modelo Task

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Concerns\HasUuids;

class Task extends Model {
    use HasUuids;

    protected $fillable = ['titulo', 'descripcion', 'imagen_path', 'user_id'];

    public function user() {
        return $this->belongsTo(User::class);
    }
}

Aquí el trait HasUuids garantiza que cada tarea creada tenga automáticamente su UUID v7 único.

Controlador de tareas

class TaskController extends Controller {
    public function __construct() {
        $this->middleware('auth');
    }

    public function index() {
        $tareas = Task::where('user_id', auth()->id())->latest()->get();
        return view('tasks.index', compact('tareas'));
    }

    public function store(Request $request) {
        $request->validate([
            'titulo' => 'required|string|max:255',
            'descripcion'=> 'nullable|string',
            'imagen'=> ['nullable', File::image()] // No permite SVG por defecto
        ]);

        $request->mergeIfMissing(['descripcion' => '']);

        $datos = $request->only(['titulo', 'descripcion']);
        if ($request->hasFile('imagen')) {
            $datos['imagen_path'] = $request->file('imagen')->store('imagenes', 'public');
        }

        $datos['user_id'] = Auth::id();

        Task::create($datos);

        return redirect()->route('tasks.index')->with('success', 'Tarea creada.');
    }
}

Aquí ves validación avanzada (sin SVG), asignación automática del usuario autenticado y el uso del método mergeIfMissing().

Uso del método nestedWhere() en Laravel 12

¿Quieres consultas más limpias? Ahora es más fácil:

$tareasImportantes = Task::nestedWhere(
    'prioridad', '=', 'alta', 'or', 'fecha_limite', '<', now()->addDays(7)
)->get();

Con nestedWhere() puedes combinar condiciones de forma sencilla y ordenada, tal como te proponemos en esta guía de Laravel 12.

Comando para ejecutar tareas concurrentes en Laravel 12

class ComputeStats extends Command {
    protected $signature = 'compute:stats';

    public function handle() {
        $resultados = Concurrency::run([
            'conteo_tareas' => fn() => DB::table('tasks')->count(),
            'calculo_matematico' => fn() => array_sum(range(1, 1000000)),
        ]);

        foreach ($resultados as $clave => $valor) {
            $this->info("{$clave}: {$valor}");
        }
    }
}

Esta nueva ejecución paralela en Laravel 12 es muy útil para tareas pesadas o procesos simultáneos.

Método range() mejorado en colecciones

Ahora puedes generar rangos personalizados fácilmente:

$numeros = Collection::range(1, 10, 2)->all(); // [1,3,5,7,9]

Otra pequeña joya que facilita el día a día, como detallamos en esta guía Laravel 12.

Prueba unitaria usando Pest PHP v3

use App\Models\Task;
use App\Models\User;

test('crear tarea genera UUID v7', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $this->post('/tasks', ['titulo' => 'Ejemplo']);
    $tarea = Task::first();

    expect($tarea->id)->toBeUuid();
});

Así puedes comprobar fácilmente que tus tareas se están creando correctamente con UUID v7.

Cómo ejecutar el proyecto localmente

Sigue estos pasos:

composer install
npm install && npm run dev
php artisan migrate
php artisan storage:link
php artisan serve

Y para probar el comando concurrente:

php artisan compute:stats

Así de sencillo gracias a las mejoras de Laravel 12 que te hemos resumido en esta guía.


¿Te ha gustado esta guía Laravel 12?
Si quieres profundizar aún más, no te pierdas la documentación oficial de Laravel 12.

Node.js 22: Novedades y una Kata Inspirada en Talent Arena

0

La nueva versión de Node.js 22 trae mejoras importantes en rendimiento, seguridad y compatibilidad con las últimas características de JavaScript. Vamos a repasar los cambios más relevantes y además te proponemos una kata práctica inspirada en el Talent Arena que se celebra en Barcelona.

Novedades principales de Node.js 22

Motor V8 actualizado a la versión 12.4

Esta actualización mejora el rendimiento general. Además, añade funciones como Array.fromAsync, nuevos métodos para Set y optimizaciones en la gestión de memoria para WebAssembly.

Activación del compilador Maglev

El compilador Maglev ahora está habilitado por defecto en sistemas compatibles. Esto acelera la ejecución de programas de corta duración, algo muy útil en proyectos que requieren rapidez.

Soporte experimental para require() en módulos ES

Se incorpora la opción --experimental-require-module. Gracias a ella, ahora es posible cargar módulos ES de forma síncrona, facilitando su integración en proyectos existentes.

Mejoras de seguridad

Con Node.js 22 llega una actualización en TLS y mejoras en la validación de certificados, reforzando la protección contra posibles ataques.

Optimización del sistema de módulos

Se ha mejorado la compatibilidad y el rendimiento de los módulos ES. Esto hace que sea más sencillo aprovechar la sintaxis moderna de JavaScript en nuestros proyectos Node.js.

Kata práctica: Gestión de sesiones en Talent Arena

Para poner en práctica estas novedades, te proponemos una kata que simula la gestión de participantes en un evento como Talent Arena, usando las nuevas características de Node.js 22.

Objetivo

Desarrollar una pequeña aplicación que permita:

  • Registrar participantes usando Array.fromAsync.
  • Asignar sesiones evitando duplicados con Set.
  • Notificar cambios en tiempo real mediante WebSockets.
  • Generar reportes de participantes utilizando iteradores.

Consideraciones técnicas

  • Optimizar la ejecución con el compilador Maglev.
  • Aplicar mejoras de seguridad usando TLS actualizado.
  • Utilizar módulos ES para una organización moderna del código.

¿Listo para empezar? Vamos paso por paso.

Paso 1: Configurar el proyecto

Primero, crea una carpeta y configura tu proyecto:

mkdir talent-arena
cd talent-arena
npm init -y

Asegúrate de tener instalada la versión 22 de Node.js (node -v). Si no, descárgala desde la página oficial de Node.js.

Paso 2: Registrar participantes

Vamos a usar Array.fromAsync para procesar participantes de manera asíncrona:

// participants.js
export async function fetchParticipants() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(["Alice", "Bob", "Charlie", "David"]);
        }, 1000);
    });
}

export async function registerParticipants() {
    const participants = await fetchParticipants();
    const processed = await Array.fromAsync(participants, async (participant) => {
        return { name: participant, registeredAt: new Date() };
    });
    return processed;
}

Con fetchParticipants() simulamos cargar datos desde un servidor, y Array.fromAsync() transforma cada participante de manera eficiente.

Paso 3: Asignar sesiones sin duplicaciones

Ahora organizamos a los participantes en sesiones sin duplicados usando Set:

// sessions.js
export function assignSessions(participants) {
    const session1 = new Set();
    const session2 = new Set();
    participants.forEach((participant, index) => {
        if (index % 2 === 0) {
            session1.add(participant.name);
        } else {
            session2.add(participant.name);
        }
    });
    return { session1: [...session1], session2: [...session2] };
}

Así conseguimos una distribución ordenada y sin riesgos de repetir participantes.

Paso 4: Notificaciones en tiempo real con WebSockets

Instalamos la librería ws:

npm install ws

Y configuramos el servidor WebSocket:

// server.js
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Cliente conectado');
    ws.send(JSON.stringify({ message: "Bienvenido a Talent Arena!" }));

    ws.on('message', (data) => {
        console.log(`Mensaje recibido: ${data}`);
    });

    ws.on('close', () => {
        console.log('Cliente desconectado');
    });
});

console.log("Servidor WebSocket corriendo en ws://localhost:8080");

Este servidor enviará un mensaje de bienvenida a cada nuevo participante.

Paso 5: Generar reportes usando iteradores

Ahora generamos un informe detallado de todos los participantes:

// reports.js
export function generateReport(participants) {
    function* reportGenerator() {
        for (const participant of participants) {
            yield `Participante: ${participant.name}, Registrado el: ${participant.registeredAt}`;
        }
    }

    const report = [];
    for (const entry of reportGenerator()) {
        report.push(entry);
    }
    return report;
}

Así podemos crear reportes sin necesidad de cargar toda la lista en memoria al mismo tiempo.

Paso 6: Integrar todo en un solo flujo

Finalmente, juntamos todas las piezas en un archivo principal:

// index.js
import { registerParticipants } from './participants.js';
import { assignSessions } from './sessions.js';
import { generateReport } from './reports.js';

async function main() {
    const participants = await registerParticipants();
    console.log("Participantes Registrados:", participants);

    const sessions = assignSessions(participants);
    console.log("Sesiones Asignadas:", sessions);

    const report = generateReport(participants);
    console.log("Reporte de Participantes:\n", report.join("\n"));
}

main();

Para ejecutar el proyecto:

node index.js

¿Te ha gustado esta kata sobre Node.js 22?
Si quieres seguir aprendiendo y explorar más ejercicios prácticos, no dudes en visitar la web oficial.

Nos vemos en Talent Arena: mentoría el 3 y 4 de marzo

0

¡Nos complace anunciar nuestra participación en la primera edición de Talent Arena, el evento europeo líder dedicado al talento digital! Este se celebrará del 3 al 5 de marzo de 2025 en el Pabellón 8 de Fira de Barcelona, Montjuïc. Este evento es una gran oportunidad para el crecimiento personal y profesional.

Durante estos tres días, más de 200 expertos compartirán sus conocimientos en áreas clave como inteligencia artificial, ingeniería de software, computación en la nube y ciberseguridad. Destacan ponentes de renombre como Steve Wozniak, cofundador de Apple, y Garry Kasparov, campeón mundial de ajedrez y promotor de la IA. Esta es una ocasión para el crecimiento personal y profesional.

Nos encontrarás en la Zona de Mentoría los días 3 y 4 de marzo, donde ofreceremos orientación personalizada para ayudarte a avanzar en tu carrera profesional. Este espacio está diseñado para que profesionales de la tecnología puedan asesorarte en tus retos y objetivos. También te brindarán estrategias y consejos adaptados a tus necesidades para tu crecimiento personal y profesional.

Además, al registrarte y asistir a Talent Arena, obtendrás un pase gratuito para el 6 de marzo en MWC Barcelona 2025. Esto ampliará aún más tus oportunidades de aprendizaje y networking. Todo ello contribuirá a tu crecimiento personal y profesional.

No pierdas esta oportunidad única de conectar con líderes de la industria, ampliar tus conocimientos y dar un impulso a tu trayectoria profesional. ¡Te esperamos en Talent Arena 2025!

Eventos en Laravel: Guía para Desarrolladores

0

Laravel es un framework de PHP conocido por su elegancia y facilidad de uso. Una de sus características más poderosas es su sistema de eventos, que permite a los desarrolladores ejecutar acciones en respuesta a ciertos cambios dentro de la aplicación.

¿Qué es el sistema de eventos en Laravel?

El sistema de eventos permite desacoplar partes de una aplicación mediante la ejecución de eventos y la escucha de estos con listeners (escuchadores). Un evento es una acción o cambio en la aplicación, mientras que un listener es una clase que ejecuta lógica específica cuando ese evento ocurre.

Configuración inicial en Laravel

Antes de empezar, asegúrate de tener un proyecto Laravel funcionando. Si no lo tienes, puedes crear uno siguiendo la guía oficial de instalación de Laravel:

composer create-project --prefer-dist laravel/laravel MiProyecto

Luego, ingresa al directorio del proyecto:

cd MiProyecto

Ejecuta las migraciones para generar la estructura de base de datos inicial:

php artisan migrate

Creación de un evento en Laravel

Laravel nos proporciona el comando make:event para crear eventos. Supongamos que estamos construyendo un sistema de pedidos y queremos lanzar uno cuando se cree un pedido:

php artisan make:event PedidoCreado

Esto generará un archivo en app/Events/PedidoCreado.php con el siguiente código base:

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\Pedido;

class PedidoCreado
{
    use Dispatchable, SerializesModels;

    public $pedido;

    public function __construct(Pedido $pedido)
    {
        $this->pedido = $pedido;
    }
}

Creación de un Listener para capturar el evento

Ahora, creamos un listener que responderá a este evento:

php artisan make:listener EnviarNotificacionPedido --event=PedidoCreado

Este comando generará un archivo en app/Listeners/EnviarNotificacionPedido.php:

namespace App\Listeners;

use App\Events\PedidoCreado;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Mail;
use App\Mail\PedidoConfirmado;

class EnviarNotificacionPedido implements ShouldQueue
{
    use InteractsWithQueue;

    public function handle(PedidoCreado $event)
    {
        Mail::to($event->pedido->usuario->email)->send(new PedidoConfirmado($event->pedido));
    }
}

Registrar los eventos y listeners en Laravel

En app/Providers/EventServiceProvider.php, registramos el evento con su listener dentro de la propiedad $listen:

protected $listen = [
    PedidoCreado::class => [
        EnviarNotificacionPedido::class,
    ],
];

Para que Laravel detecte los cambios, ejecutamos:

php artisan event:clear
php artisan event:cache

(Más detalles sobre cómo trabajar con el Event Service Provider).

Lanzar el evento desde un controlador

En app/Http/Controllers/PedidoController.php, disparamos el evento cuando se crea un pedido:

namespace App\Http\Controllers;

use App\Models\Pedido;
use App\Events\PedidoCreado;
use Illuminate\Http\Request;

class PedidoController extends Controller
{
    public function store(Request $request)
    {
        $pedido = Pedido::create([
            'usuario_id' => auth()->id(),
            'total' => $request->total,
            'estado' => 'pendiente'
        ]);

        event(new PedidoCreado($pedido));

        return response()->json(['message' => 'Pedido creado y evento disparado.']);
    }
}

Probando el sistema de eventos

Para probar si todo funciona correctamente, podemos hacer una solicitud POST al endpoint:

curl -X POST http://localhost/api/pedidos \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer TU_TOKEN" \
     -d '{"total": 100.50}'

Conclusión

El sistema de eventos de Laravel es una herramienta increíblemente útil para desacoplar la lógica de negocio y responder de manera eficiente a los cambios en la aplicación. En este tutorial, aprendimos a:

  • Crear eventos y listeners.
  • Registrar y despachar eventos.
  • Ejecutar eventos en segundo plano con colas.

Este enfoque mejora la estructura de nuestras aplicaciones, haciéndolas más mantenibles y escalables.