10-Introducción a Blade en Laravel con un Ejemplo Práctico
Introducción a Blade en Laravel con un Ejemplo Práctico
Blade es el motor de plantillas de Laravel que permite crear vistas de manera elegante y eficiente. A continuación te mostraré un ejemplo completo de cómo usar Blade para crear una aplicación simple de gestión de tareas.
Estructura del Proyecto
Vamos a crear:
Una plantilla base (layout)
Una página de índice para ver todas las tareas
Una página para agregar nueva tarea
Una página para ver los detalles de una tarea
Un menú de navegación
Funcionalidad para salir (logout)
1. Plantilla Base (resources/views/layouts/app.blade.php)
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title') - Gestor de Tareas</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">Gestor de Tareas</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{{ route('tasks.index') }}">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('tasks.create') }}">Nueva Tarea</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="btn btn-link nav-link">Salir</button>
</form>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
@yield('content')
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>2. Página de Índice (resources/views/tasks/index.blade.php)
@extends('layouts.app')
@section('title', 'Lista de Tareas')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Lista de Tareas</h1>
<a href="{{ route('tasks.create') }}" class="btn btn-primary">Nueva Tarea</a>
</div>
@if($tasks->isEmpty())
<div class="alert alert-info">No hay tareas registradas.</div>
@else
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Título</th>
<th>Estado</th>
<th>Fecha</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
@foreach($tasks as $task)
<tr>
<td>{{ $task->id }}</td>
<td>{{ $task->title }}</td>
<td>
<span class="badge {{ $task->completed ? 'bg-success' : 'bg-warning' }}">
{{ $task->completed ? 'Completada' : 'Pendiente' }}
</span>
</td>
<td>{{ $task->created_at->format('d/m/Y') }}</td>
<td>
<a href="{{ route('tasks.show', $task->id) }}" class="btn btn-sm btn-info">Ver</a>
<a href="{{ route('tasks.edit', $task->id) }}" class="btn btn-sm btn-warning">Editar</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
@endsection3. Página para Crear Tarea (resources/views/tasks/create.blade.php)
@extends('layouts.app')
@section('title', 'Crear Nueva Tarea')
@section('content')
<div class="card">
<div class="card-header">
<h2>Nueva Tarea</h2>
</div>
<div class="card-body">
<form action="{{ route('tasks.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Título</label>
<input type="text" class="form-control @error('title') is-invalid @enderror" id="title" name="title" value="{{ old('title') }}">
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Descripción</label>
<textarea class="form-control @error('description') is-invalid @enderror" id="description" name="description" rows="3">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="completed" name="completed">
<label class="form-check-label" for="completed">Completada</label>
</div>
<button type="submit" class="btn btn-primary">Guardar</button>
<a href="{{ route('tasks.index') }}" class="btn btn-secondary">Cancelar</a>
</form>
</div>
</div>
@endsection4. Página para Ver Tarea (resources/views/tasks/show.blade.php)
@extends('layouts.app')
@section('title', 'Detalles de la Tarea')
@section('content')
<div class="card">
<div class="card-header">
<h2>Detalles de la Tarea</h2>
</div>
<div class="card-body">
<div class="mb-3">
<h5 class="card-title">{{ $task->title }}</h5>
<span class="badge {{ $task->completed ? 'bg-success' : 'bg-warning' }}">
{{ $task->completed ? 'Completada' : 'Pendiente' }}
</span>
</div>
<p class="card-text">{{ $task->description }}</p>
<div class="mt-4">
<p><strong>Creada:</strong> {{ $task->created_at->format('d/m/Y H:i') }}</p>
<p><strong>Actualizada:</strong> {{ $task->updated_at->format('d/m/Y H:i') }}</p>
</div>
<div class="mt-4">
<a href="{{ route('tasks.edit', $task->id) }}" class="btn btn-warning">Editar</a>
<a href="{{ route('tasks.index') }}" class="btn btn-secondary">Volver</a>
</div>
</div>
</div>
@endsection5. Rutas (routes/web.php)
<?php
use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;
// Página de inicio (lista de tareas)
Route::get('/', [TaskController::class, 'index'])->name('tasks.index');
// Mostrar formulario para crear nueva tarea
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
// Guardar nueva tarea
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
// Mostrar detalles de una tarea
Route::get('/tasks/{task}', [TaskController::class, 'show'])->name('tasks.show');
// Mostrar formulario para editar tarea
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit'])->name('tasks.edit');
// Actualizar tarea
Route::put('/tasks/{task}', [TaskController::class, 'update'])->name('tasks.update');
// Eliminar tarea
Route::delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('tasks.destroy');
// Cerrar sesión
Route::post('/logout', function () {
auth()->logout();
return redirect('/');
})->name('logout');6. Controlador (app/Http/Controllers/TaskController.php)
<?php
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Http\Request;
class TaskController extends Controller
{
public function index()
{
$tasks = Task::latest()->get();
return view('tasks.index', compact('tasks'));
}
public function create()
{
return view('tasks.create');
}
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'description' => 'nullable',
'completed' => 'boolean'
]);
Task::create($validated);
return redirect()->route('tasks.index')
->with('success', 'Tarea creada correctamente');
}
public function show(Task $task)
{
return view('tasks.show', compact('task'));
}
public function edit(Task $task)
{
return view('tasks.edit', compact('task'));
}
public function update(Request $request, Task $task)
{
$validated = $request->validate([
'title' => 'required|max:255',
'description' => 'nullable',
'completed' => 'boolean'
]);
$task->update($validated);
return redirect()->route('tasks.show', $task)
->with('success', 'Tarea actualizada correctamente');
}
public function destroy(Task $task)
{
$task->delete();
return redirect()->route('tasks.index')
->with('success', 'Tarea eliminada correctamente');
}
}Características de Blade demostradas en este ejemplo:
Herencia de plantillas: Uso de
@extendsy@sectionInclusión de contenido:
@yielden el layout y@sectionen las vistasEstructuras de control:
@if,@else,@foreachDirectivas de Blade:
@csrf,@error,@methodMostrar datos:
{{ $variable }}con escape automáticoCondicionales en clases:
class="{{ $condition ? 'class1' : 'class2' }}"Formateo de fechas: Uso de métodos de Carbon (
format())Sistema de rutas:
route()para generar URLs
Este ejemplo proporciona una base sólida para entender cómo funciona Blade en Laravel y cómo estructurar una aplicación básica con las páginas que mencionaste.
Comentarios
Publicar un comentario