UNIDAD-1
Requisitos previos (lo esencial)
Para instalar y ejecutar Laravel en Windows, necesitas estos 4 componentes:
Opcional pero recomendado: Node.js y NPM si vas a trabajar con frontend (CSS, JavaScript, Vite).
🚀 Paso a paso para instalar Laravel
1. Instalar XAMPP (PHP + servidor web + MySQL)
Descarga XAMPP desde su sitio oficial.
Durante la instalación, asegúrate de seleccionar PHP, Apache y MySQL.
Al terminar, abre el panel de control de XAMPP y inicia los servicios de Apache y MySQL.
2. Instalar Composer
Descarga el instalador Composer-Setup.exe desde getcomposer.org.
Cuando te pregunte por la ubicación de php.exe, selecciona la carpeta donde XAMPP instaló PHP. Normalmente es:
C:\xampp\php\php.exe
3. Instalar Laravel usando Composer
Abre una terminal (CMD, PowerShell o Git Bash) y ejecuta:
bash
composer global require laravel/installer
Importante: Después de este comando, el instalador te mostrará una carpeta donde se guardó el ejecutable de Laravel (ej: %USERPROFILE%\AppData\Roaming\Composer\vendor\bin).
Agrega esa ruta a la variable de entorno PATH de Windows para poder usar el comando laravel desde cualquier lugar.
4. Crear tu primer proyecto Laravel
Ubícate en la carpeta donde quieres crear el proyecto (ejemplo: C:\mis-proyectos):
bash
cd C:\mis-proyectos
laravel new mi-primer-sitio
Esto creará una carpeta llamada mi-primer-sitio con todo el Laravel ya instalado.
💻 Cómo ejecutar tu proyecto
Entra a la carpeta del proyecto:
bash
cd mi-primer-sitio
Inicia el servidor de desarrollo de Laravel:
bash
php artisan serve
Abre tu navegador y ve a: http://localhost:8000
¡Listo! Ya tienes Laravel funcionando en Windows.
⚠️ Nota importante sobre versiones
Si usas XAMPP, ten en cuenta que las versiones más recientes pueden incluir una versión antigua de PHP. Verifica que tu XAMPP tenga PHP 8.2 o superior.
Si tu XAMPP tiene una versión más vieja, puedes:
Instalar PHP manualmente por separado, o
Usar Laragon (alternativa más moderna y recomendada para Laravel en Windows).
🔧 Alternativa recomendada: Laragon
Si quieres algo más sencillo, puedes usar Laragon, que ya incluye PHP, Composer, MySQL, Apache/NGINX y está especialmente optimizado para Laravel. Solo lo instalas y ya puedes crear proyectos con laravel new.
CONVENCIÓN DE NOMBRES
Te explico las convenciones de nomenclatura en Laravel con énfasis en la estructura Verbo + Sustantivo:
estructura para controladores:
📝 Controladores - Estructura Correcta
Nombres de Clases (Controladores)
Caso: PascalCase
Estructura: Sujeto/Objeto (Sustantivo) + Controller
Sufijo: Controller
Número: Sustantivo en Plural (representa la colección que maneja)
✅ Ejemplos Correctos:
php
// Controlador para manejar usuarios (colección de usuarios)
class UsersController extends Controller {} // Sujeto: Users
// Controlador para manejar productos (colección de productos)
class ProductsController extends Controller {} // Sujeto: Products
// Controlador para categorías de productos
class ProductCategoriesController extends Controller {} // Sujeto: ProductCategories
❌ Ejemplos Incorrectos:
php
class UserController extends Controller {} // ❌ Debe ser plural: UsersController
class ManageUsersController extends Controller {} // ❌ No sigue estructura Sustantivo + Controller
class user_controller extends Controller {} // ❌ Caso incorrecto
🔧 Métodos - Estructura Correcta
Métodos RESTful Estándar:
php
class ProductsController extends Controller
{
// SUJETO: Products | VERBO: index (listar)
public function index() {} // GET /products
// SUJETO: Product | VERBO: create (mostrar formulario creación)
public function create() {} // GET /products/create
// SUJETO: Product | VERBO: store (almacenar)
public function store() {} // POST /products
// SUJETO: Product | VERBO: show (mostrar)
public function show() {} // GET /products/{id}
// SUJETO: Product | VERBO: edit (mostrar formulario edición)
public function edit() {} // GET /products/{id}/edit
// SUJETO: Product | VERBO: update (actualizar)
public function update() {} // PUT/PATCH /products/{id}
// SUJETO: Product | VERBO: destroy (eliminar)
public function destroy() {} // DELETE /products/{id}
}
Métodos Personalizados:
php
class UsersController extends Controller
{
// SUJETO: User | VERBO: activate (activar)
public function activate() {} // PUT /users/{id}/activate
// SUJETO: User | VERBO: suspend (suspender)
public function suspend() {} // PUT /users/{id}/suspend
// SUJETO: UserProfile | VERBO: update (actualizar)
public function updateProfile() {} // PUT /users/{id}/profile
// SUJETO: UserPassword | VERBO: change (cambiar)
public function changePassword() {} // PUT /users/{id}/password
}
🎯 Estructura Generalizada
Para Controladores:
text
[SUSTANTIVO_PLURAL] + Controller
Sustantivo: Representa el recurso/entidad que se manipula
Plural: Indica que maneja una colección del recurso
Controller: Identifica el tipo de clase
Para Métodos:
text
[VERBO] + [SUSTANTIVO_OPCIONAL]()
Verbo: La acción a realizar (index, create, store, show, edit, update, destroy)
Sustantivo: Opcional, para especificar sub-recursos (profile, password, settings)
Nombres de Modelos
Caso: PascalCase
Estructura: Sustantivo en Singular
Ejemplos:
User (Modelo para usuario) ✅
Product (Modelo para producto) ✅
Category (Modelo para categoría) ✅
php
// VERBO: Definir | SUSTANTIVO: Modelo de Usuario
class User extends Model
{
// VERBO: Obtener | SUSTANTIVO: Posts del usuario
public function getUsersPosts() {}
// VERBO: Calcular | SUSTANTIVO: Edad del usuario
public function calculateUserAge() {}
}
📊 Variables
Variables y Propiedades
Caso: camelCase
Estructura: Sustantivo descriptivo (a veces con adjetivo)
Ejemplos:
php
// ✅ Variables con sustantivos descriptivos
$userName = 'John'; // Nombre de usuario
$productList = []; // Lista de productos
$totalAmount = 100; // Monto total
$isActiveUser = true; // Usuario activo
$hasValidSubscription = false; // Tiene suscripción válida
// ✅ Colecciones (sustantivo en plural)
$activeUsers = User::where('active', true)->get(); // Usuarios activos
$productCategories = Category::all(); // Categorías de productos
📋 Resumen Completo de Reglas
🎯 Ejemplos Prácticos Completos
Controlador con Métodos Personalizados
php
class OrderController extends Controller
{
// ✅ VERBO + SUSTANTIVO: Calcular total de orden
public function calculateOrderTotal($orderId)
{
$order = Order::find($orderId);
$total = $order->calculateTotal();
return response()->json(['total' => $total]);
}
// ✅ VERBO + SUSTANTIVO: Aplicar descuento a orden
public function applyOrderDiscount($orderId, $discount)
{
$order = Order::find($orderId);
$order->applyDiscount($discount);
return response()->json(['success' => true]);
}
// ✅ VERBO + SUSTANTIVO: Generar factura de orden
public function generateOrderInvoice($orderId)
{
$invoice = Order::generateInvoice($orderId);
return response()->download($invoice);
}
}
Modelo con Métodos
php
class User extends Model
{
// ✅ VERBO + SUSTANTIVO: Verificar contraseña de usuario
public function verifyUserPassword($password)
{
return Hash::check($password, $this->password);
}
// ✅ VERBO + SUSTANTIVO: Actualizar perfil de usuario
public function updateUserProfile($data)
{
$this->update($data);
return $this;
}
// ✅ VERBO + SUSTANTIVO: Calcular edad de usuario
public function calculateUserAge()
{
return now()->diffInYears($this->birthdate);
}
}
🔄 Rutas con Convenciones
php
// Rutas RESTful automáticas
Route::resource('products', ProductController::class);
// Rutas personalizadas con nombres VERBO + SUSTANTIVO
Route::post('products/{id}/activate', [ProductController::class, 'activateProduct'])
->name('products.activate'); // activateProduct = VERBO + SUSTANTIVO
Route::get('users/{id}/reports', [UserController::class, 'generateUserReport'])
->name('users.generateReport'); // generateUserReport = VERBO + SUSTANTIVO
Esta estructura Verbo + Sustantivo hace que el código sea:
Más legible: Se entiende inmediatamente qué acción realiza cada método
Más mantenible: Nombres consistentes y predecibles
Más intuitivo: Sigue el flujo natural de lenguaje (acción + objeto
resumen
Modelo: User (singular) → Instancia individual
Tabla: users (plural) → Colección de instancias
Controlador: UsersController → Maneja la colección
Métodos: index(), show(), etc. → Operaciones sobre la colección
Esta estructura sigue el principio de que el controlador maneja colecciones de recursos, por eso el sustantivo va en plural, mientras que los métodos operan sobre elementos individuales o la colección completa.
Rutas en Laravel: Explicación y Ejemplos
Las rutas en Laravel son el mecanismo que permite definir cómo responde tu aplicación a las solicitudes HTTP entrantes. Todas las rutas de Laravel se definen en los archivos dentro del directorio routes/.
Tipos básicos de rutas
1. Rutas básicas
php
Route::get('/saludo', function () {
return '¡Hola Mundo!';
});
Cuando se visita /saludo en el navegador, se mostrará "¡Hola Mundo!".
1.1 Devolver un arreglo directamente (JSON automático)
Laravel convierte automáticamente a JSON cualquier array o colección que devuelvas desde una ruta o controlador.
Route::get('/tareas', function () {
$tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
return $tareas; // Laravel lo convierte a JSON automáticamente
});
Al visitar /tareas verás en el navegador (o en tu cliente HTTP) algo como:
json
[
{"id":1,"nombre":"Comprar pan"},
{"id":2,"nombre":"Estudiar Laravel"},
{"id":3,"nombre":"Hacer ejercicio"}
]
2. Rutas con parámetros
php
Route::get('/usuario/{id}', function ($id) {
return 'Usuario '.$id;
});
Esta ruta capturará el ID de la URL y lo pasará a la función.
3. Rutas con parámetros opcionales
php
Route::get('/post/{titulo?}', function ($titulo = 'Título por defecto') {
return $titulo;
});
El parámetro titulo es opcional y tiene un valor por defecto.
4. Rutas con restricciones
php
Route::get('/user/{id}', function ($id) {
// Solo se ejecutará si {id} es numérico
})->where('id', '[0-9]+');
5. Rutas con nombre
php
Route::get('/perfil', function () {
// ...
})->name('perfil');
Puedes generar URLs a esta ruta usando route('perfil').
6-Rutas hacia controladores
php
Route::get('/productos', 'ProductoController@index');
Esto dirigirá las solicitudes GET a /productos al método index de ProductoController.
6.1. Rutas hacia vistas: Route::view()
Laravel tiene un método específico para esto que es muy legible:
php
Route::view('/productos', 'productos.index');
¿Qué hace?
Cuando visites /productos, Laravel cargará directamente la vista que se encuentra en resources/views/productos/index.blade.php.
¿Y si quiero pasar datos estáticos a la vista?
El tercer parámetro de Route::view() acepta un arreglo de datos:
php
Route::view('/productos', 'productos.index', [
'titulo' => 'Lista de Productos',
'categoria' => 'Electrónicos'
]);
Luego en tu vista index.blade.php puedes usar {{ $titulo }} y {{ $categoria }}.
7-Grupos de rutas
php
Route::prefix('admin')->group(function () {
Route::get('/usuarios', function () {
// Ruta: /admin/usuarios
});
Route::get('/config', function () {
// Ruta: /admin/config
});
});
Tabla de comandos comunes de rutas
Las rutas son fundamentales en Laravel y ofrecen muchas más posibilidades como middleware, binding de modelos, subdominios, etc. Esta es solo una introducción básica.
1. Rutas individuales (manualmente)
php
use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;
Route::get('/tasks', [TaskController::class, 'index'])->name('tasks.index');
Route::get('/tasks/create', [TaskController::class, 'create'])->name('tasks.create');
Route::post('/tasks', [TaskController::class, 'store'])->name('tasks.store');
Route::get('/tasks/{task}', [TaskController::class, 'show'])->name('tasks.show');
Route::get('/tasks/{task}/edit', [TaskController::class, 'edit'])->name('tasks.edit');
Route::put('/tasks/{task}', [TaskController::class, 'update'])->name('tasks.update');
Route::delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('tasks.destroy');
2. Rutas agrupadas con resource (recomendado)
Laravel permite generar todas las rutas CRUD automáticamente con Route::resource:
php
use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;
Route::resource('tasks', TaskController::class);
Esto crea las mismas rutas que el método anterior, pero en una sola línea.
Rutas generadas por Route::resource:
3. Rutas apiResource (para APIs)
Si estás construyendo una API, usa apiResource para excluir las rutas de vistas como create y edit:
php
Route::apiResource('tasks', TaskController::class);
¿Dónde colocar estas rutas?
Rutas web: En routes/web.php (para aplicaciones con vistas).
Rutas API: En routes/api.php (si es una API RESTful).
Si usas Laravel 9+, asegúrate de importar el controlador:
php
use App\Http\Controllers\TaskController;
Consejo adicional
Si quieres ver todas las rutas definidas en tu proyecto, ejecuta:
bash
php artisan route:list
Esto mostrará una tabla con todas las rutas, métodos y controladores
asociados.
Tips Importantes
Redirecciones:
php
return redirect()->route('tasks.index'); // Redirige a la lista de tareas
return redirect()->back(); // Redirige a la página anterior
Mensajes de sesión:
php
return redirect()->route('tasks.index')->with('success', 'Tarea creada!');
Comando route:list en Laravel
El comando route:list es una herramienta muy útil que muestra una tabla con todas las rutas registradas en tu aplicación Laravel, incluyendo sus métodos HTTP, URIs, nombres (si los tienen), acciones y middlewares aplicados.
Ejemplo de uso
Para ver la lista de rutas, ejecuta en tu terminal:
bash
php artisan route:list
Esto mostrará una salida similar a:
+--------+----------+-------------------+------+---------+--------------+
| Method | URI | Name | Action | Middleware |
+--------+----------+-------------------+------+---------+--------------+
| GET | / | | Closure | web |
| GET | saludo | | Closure | web |
| GET | usuario/{id} | | Closure | web |
| GET | perfil | perfil | Closure | web |
| GET | productos | | ProductoController@index | web |
+--------+----------+-------------------+------+---------+--------------+
Opciones útiles del comando
Puedes usar varias opciones para filtrar o formatear la salida:
bash
# Mostrar solo rutas con nombre
php artisan route:list --name=perfil
# Mostrar rutas que coincidan con un URI específico
php artisan route:list --path=usuario
# Mostrar en formato JSON
php artisan route:list --json
# Mostrar más detalles (incluyendo middlewares)
php artisan route:list -v
Tabla actualizada con el comando route:list
El comando route:list es especialmente útil para:
Depurar problemas de rutas
Verificar que todas las rutas estén correctamente definidas
Comprobar los middlewares aplicados a cada ruta
Identificar conflictos entre rutas
Documentar tu API o sistema de rutas
VISTAS
@extends : La vista hija dice "yo voy a usar un layout padre"
@section : Define un bloque de contenido (como un hueco o sección)
@yield : En el layout padre, muestra el contenido que la vista hija ponga en esa sección
@show : Muestra la sección (similar a @yield pero usada en el layout)
Con @show (tu código original):
blade
@section('sidebar')
Este es mi master sidebar.
@show
Resultado si la hija NO define 'sidebar': Muestra "Este es mi master sidebar."
Sin @show (usando @yield):
blade
@yield('sidebar')
Tu ejemplo (layout padre)
blade
<!-- resources/views/layouts/master.blade.php -->
<html>
<head>
<title>@yield('title', 'Título por defecto')</title>
</head>
<body>
@section('sidebar')
Este es mi master sidebar.
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
Ejemplo aún más pequeño (3 líneas)
Layout padre (layout.blade.php):
blade
<html>
<body>
@yield('contenido')
</body>
</html>
Vista hija (home.blade.php):
blade
@extends('layout')
@section('contenido')
<h1>Hola Mundo!</h1>
@endsection
Resultado final:
html
<html>
<body>
<h1>Hola Mundo!</h1>
</body>
</html>
1. Layout padre – layouts/app.blade.php (sin cambios)
blade
<html>
<head>
<title>Mi App - @yield('title')</title>
</head>
<body>
<nav>Menú principal</nav>
@section('sidebar')
<aside>Sidebar por defecto</aside>
@show
<main>
@yield('content')
</main>
<footer>© 2026</footer>
</body>
</html>
2. Vista hija – tareas/index.blade.php (ahora sin @php)
blade
@extends('layouts.app')
@section('title', 'Lista de tareas')
@section('sidebar')
<aside>
<h3>Filtros</h3>
<ul>
<li>Pendientes</li>
<li>Completadas</li>
</ul>
</aside>
@endsection
@section('content')
<h1>Lista de tareas</h1>
<ul>
@foreach ($tareas as $tarea)
<li>{{ $tarea['nombre'] }} (ID: {{ $tarea['id'] }})</li>
@endforeach
</ul>
@endsection
Nota: Ahora la vista espera que la variable $tareas exista en el entorno de renderizado.
3. Resultado final renderizado (idéntico al anterior)
html
<html>
<head>
<title>Mi App - Lista de tareas</title>
</head>
<body>
<nav>Menú principal</nav>
<aside>
<h3>Filtros</h3>
<ul>
<li>Pendientes</li>
<li>Completadas</li>
</ul>
</aside>
<main>
<h1>Lista de tareas</h1>
<ul>
<li>Comprar pan (ID: 1)</li>
<li>Estudiar Laravel (ID: 2)</li>
<li>Hacer ejercicio (ID: 3)</li>
</ul>
</main>
<footer>© 2026</footer>
</body>
</html>
4. ¿Cómo pasar el arreglo desde la ruta?
Puedes hacerlo de dos maneras comunes:
Opción A – Usando un closure en routes/web.php
php
use Illuminate\Support\Facades\Route;
Route::get('/tareas', function () {
$tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
return view('tareas.index', compact('tareas'));
});
Opción B – Usando un controlador
Primero, crea el controlador (ej. TareaController) con un método index:
php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TareaController extends Controller
{
public function index()
{
$tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
return view('tareas.index', compact('tareas'));
}
}
Luego, en routes/web.php:
php
use App\Http\Controllers\TareaController;
Route::get('/tareas', [TareaController::class, 'index']);
5. Diferencia clave (repaso)
En nuestro ejemplo, usamos @section ... @show en el layout, y la vista hija lo sobrescribe con su propio sidebar de filtros. Si no lo sobrescribiera, veríamos el texto "Sidebar por defecto".
6. Ejemplo adicional: pasar el arreglo directamente desde la ruta sin variable intermedia (solo por curiosidad)
También puedes pasar los datos usando view() con un arreglo asociativo en el segundo parámetro:
php
Route::get('/tareas', function () {
return view('tareas.index', [
'tareas' => [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
]
]);});
El resultado en la vista será el mismo, porque $tareas estará disponible.
PASAR VARIABLES DE RUTA A LA VISTA
En Laravel, puedes pasar variables y arreglos de la ruta a la vista de varias maneras:
1. Usando with() encadenado
php
Route::get('/usuario/{id}', function ($id) {
$nombre = "Juan";
$datos = ['email' => 'juan@email.com', 'edad' => 30];
return view('perfil')->with('id', $id)
->with('nombre', $nombre)
->with('datos', $datos);
});
1. Usando with() - Pasando el arreglo completo
php
Route::get('/usuario/{id}', function ($id) {
// Creas un arreglo con todos los datos
$datosUsuario = [
'id' => $id,
'nombre' => 'Juan',
'email' => 'juan@email.com',
'edad' => 30,
'direccion' => 'Calle Principal 123'
];
return view('perfil')->with('usuario', $datosUsuario);
});
2. Usando arreglo asociativo en segundo parámetro
php
Route::get('/usuario/{id}', function ($id) {
$nombre = "Juan";
$datos = ['email' => 'juan@email.com', 'edad' => 30];
return view('perfil', [
'id' => $id,
'nombre' => $nombre,
'datos' => $datos
]);
});
2. Usando arreglo asociativo - Pasando el arreglo completo
php
Route::get('/usuario/{id}', function ($id) {
$usuario = [
'id' => $id,
'nombre' => 'Juan',
'email' => 'juan@email.com',
'edad' => 30
];
return view('perfil', ['usuario' => $usuario]);
});
3. Usando compact()
php
Route::get('/usuario/{id}', function ($id) {
$nombre = "Juan";
$datos = ['email' => 'juan@email.com', 'edad' => 30];
return view('perfil', compact('id', 'nombre', 'datos'));
});
3. Usando compact() - Pasando el arreglo completo
php
Route::get('/usuario/{id}', function ($id) {
$usuario = [
'id' => $id,
'nombre' => 'Juan',
'email' => 'juan@email.com',
'edad' => 30,
'hobbies' => ['leer', 'nadar', 'programar']
];
return view('perfil', compact('usuario'));
});
4. Desde un controlador
php
// En web.php
Route::get('/usuario/{id}', [UserController::class, 'show']);
// En UserController.php
public function show($id)
{
$nombre = "Juan";
$datos = ['email' => 'juan@email.com', 'edad' => 30];
return view('perfil', [
'id' => $id,
'nombre' => $nombre,
'datos' => $datos
]);
}
5. En la vista (perfil.blade.php)
<h1>Perfil de usuario</h1>
<p>ID: {{ $id }}</p>
<p>Nombre: {{ $nombre }}</p>
<h2>Datos del usuario:</h2>
<ul>
<li>Email: {{ $datos['email'] }}</li>
<li>Edad: {{ $datos['edad'] }}</li>
</ul>
{{-- O si es un array indexado --}}
@foreach($datos as $key => $value)
<li>{{ $key }}: {{ $value }}</li>
@endforeach
Ejemplo con múltiples parámetros en la ruta
// Ruta con múltiples parámetros
Route::get('/producto/{categoria}/{id}', function ($categoria, $id) {
$producto = ['nombre' => 'Laptop', 'precio' => 1000];
$caracteristicas = ['RAM' => '8GB', 'SSD' => '256GB'];
return view('producto', compact('categoria', 'id', 'producto', 'caracteristicas'));
});
La opción más común y recomendada es usar compact() o el arreglo asociativo directo, ya que son más limpios y fáciles de leer.
Controladores en Laravel (sin modelos)
En este tutorial aprenderás a crear un controlador, definir un método que retorne una vista con datos y vincularlo a una ruta, todo sin usar modelos. Solo trabajaremos con arreglos de prueba………………………………………………………………
1. ¿Qué es un controlador?
Un controlador es una clase que agrupa la lógica de manejo de peticiones HTTP. En lugar de poner toda la lógica en las rutas (closures), los controladores permiten organizar el código en métodos reutilizables.
2. Crear un controlador con Artisan
Ejecuta en la terminal (en la raíz de tu proyecto Laravel):
bash
php artisan make:controller TareaController
Esto creará el archivo app/Http/Controllers/TareaController.php.
3. Definir un método index
Abre el controlador recién creado y agrega un método index que devuelva una vista con un arreglo de tareas.
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TareaController extends Controller
{
public function index()
{
// Datos de ejemplo (sin modelos)
$tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
// Retorna la vista 'tareas.index' y le pasa la variable $tareas
return view('tareas.index', compact('tareas'));
}
}
compact('tareas') crea un arreglo asociativo ['tareas' => $tareas] que la vista recibirá.
La vista debe existir en resources/views/tareas/index.blade.php.
4. Crear la vista (sin CSS)
Crea el directorio tareas dentro de resources/views y dentro coloca index.blade.php con el siguiente contenido:
blade
<!DOCTYPE html>
<html>
<head>
<title>Lista de tareas</title>
</head>
<body>
<h1>Mis tareas</h1>
<ul>
@foreach ($tareas as $tarea)
<li>{{ $tarea['nombre'] }} (ID: {{ $tarea['id'] }})</li>
@endforeach
</ul>
</body>
</html>
Usamos Blade @foreach para recorrer el arreglo.
Mostramos el nombre y el ID de cada tarea.
5. Registrar la ruta
Abre routes/web.php y añade:
php
use App\Http\Controllers\TareaController;
Route::get('/tareas', [TareaController::class, 'index']);
Esto asigna la URL /tareas al método index del TareaController.
6. Probar la aplicación
Inicia el servidor de desarrollo:
bash
php artisan serve
Abre tu navegador en http://localhost:8000/tareas y verás la lista de tareas renderizada.
7. Explicación del flujo
El usuario hace una petición GET a /tareas.
Laravel enruta la petición al método index de TareaController.
El método prepara los datos (el arreglo $tareas) y llama a view('tareas.index', compact('tareas')).
Blade renderiza la vista con la variable $tareas disponible.
El HTML resultante se envía al navegador.
8. Buenas prácticas básicas
Nombres de métodos: Usa verbos HTTP (index, show, create, store, edit, update, destroy) para acciones típicas.
Pasar datos: Siempre usa compact() o arreglos explícitos (['tareas' => $tareas]).
Organización: Agrupa rutas relacionadas con Route::resource() (opcional, pero útil cuando tengas CRUD).
Resumen
Los controladores centralizan la lógica de tus rutas.
Los métodos retornan vistas con datos.
Las rutas enlazan URLs con métodos del controlador.
No necesitas modelos para empezar; puedes usar arreglos de prueba.
2. Obtener Todo el Contenido del Request
Laravel inyecta automáticamente el objeto
Illuminate\Http\Request en los métodos del controlador.
Ejemplo: Recuperar todos los datos del request
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
// Obtener todos los datos del request (formulario, JSON, etc.)
$allData = $request->all();
// Mostrar los datos (útil para debugging)
dd($allData);
// También puedes usar:
// $request->input() → Equivalente a all(), pero permite valores por defecto
}
}
📌 Uso común:
$request->all() → Devuelve un array asociativo con todos los inputs.
$request->input() → Similar a all(), pero permite definir un valor por defecto si el campo no existe.
3. Validar Inputs Específicos
Laravel ofrece validación integrada para asegurar que los datos cumplan ciertas reglas.
Ejemplo: Validar campos obligatorios
public function store(Request $request)
{
// Validación básica
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8',
]);
// Si pasa la validación, continuamos
return response()->json(['success' => 'Usuario creado!']);
}
📌 Reglas comunes:
required → El campo es obligatorio.
email → Debe ser un email válido.
unique:users → El email no debe existir en la tabla users.
min:8 → Mínimo 8 caracteres.
💡 Métodos alternativos para acceder a inputs específicos:
php
$name = $request->input('name'); // Obtiene el campo 'name'
$email = $request->email; // Sintaxis alternativa (propiedad dinámica)
$defaultValue = $request->input('role', 'user'); // Valor por defecto si no existef
FLUJO DE DATOS EN EL CRUD
📥 1. Del Modelo al Controlador (Obtener datos)
php
// Obtener todos los registros
$productos = Producto::all();
// Obtener un registro específico
$producto = Producto::find($id);
$producto = Producto::findOrFail($id); // Lanza error 404 si no existe
// Obtener con condiciones
$productosActivos = Producto::where('activo', true)->get();
// Obtener el último registro
$ultimoProducto = Producto::latest()->first();
// Obtener con relaciones (si tienes)
$producto = Producto::with('categoria')->find($id);
📤 2. Del Controlador a la Vista (Inyectar datos)
Método 1: Usando compact()
php
public function index()
{
$productos = Producto::all();
$titulo = "Lista de Productos";
return view('productos.index', compact('productos', 'titulo'));
}
Método 2: Usando with()
php
public function show($id)
{
$producto = Producto::findOrFail($id);
return view('productos.show')->with('producto', $producto);
}
Método 3: Usando array asociativo
php
public function edit($id)
{
$producto = Producto::findOrFail($id);
$categorias = Categoria::all();
return view('productos.edit', [
'producto' => $producto,
'categorias' => $categorias,
'modo' => 'edición'
]);
}
📥 3. De la Vista al Controlador (Recibir datos)
Para formularios GET (búsquedas, filtros):
php
public function index(Request $request)
{
// Obtener parámetros de la URL
$busqueda = $request->input('buscar');
$categoria = $request->query('categoria');
// También puedes usar
$busqueda = $request->get('buscar');
$busqueda = $request->buscar; // Si existe en la URL
// Ejemplo de búsqueda
$productos = Producto::where('nombre', 'LIKE', "%{$busqueda}%")
->when($categoria, function($query) use ($categoria) {
return $query->where('categoria_id', $categoria);
})
->get();
return view('productos.index', compact('productos'));
}
Para formularios POST (crear, actualizar):
php
public function store(Request $request)
{
// Forma 1: Obtener todos los datos
$datos = $request->all();
// Forma 2: Obtener solo algunos campos
$nombre = $request->input('nombre');
$precio = $request->input('precio');
// Forma 3: Obtener con validación (recomendado)
$validated = $request->validate([
'nombre' => 'required|max:255',
'precio' => 'required|numeric|min:0',
'descripcion' => 'nullable|string'
]);
// Guardar usando los datos validados
$producto = Producto::create($validated);
}
📤 4. Del Controlador a la Vista con Redirección
php
public function store(Request $request)
{
// Validar y guardar
$validated = $request->validate([
'nombre' => 'required|max:255',
'precio' => 'required|numeric'
]);
$producto = Producto::create($validated);
// 🔥 DIFERENTES FORMAS DE REDIRECCIONAR
// 1. Redirigir a una ruta con nombre
return redirect()->route('productos.index');
// 2. Redirigir a una URL específica
return redirect('/productos');
// 3. Redirigir al detalle del producto creado
return redirect()->route('productos.show', $producto->id);
// 4. Redirigir hacia atrás
return redirect()->back();
// 5. Redirigir con mensaje flash
return redirect()->route('productos.index')
->with('success', 'Producto creado exitosamente');
}
💬 MENSAJES FLASH (Sistema de notificaciones)
En el Controlador (Guardar mensaje):
php
// Mensaje de éxito
return redirect()->route('productos.index')
->with('success', '¡Producto creado correctamente!');
// Mensaje de error
return redirect()->back()
->with('error', 'Hubo un problema al guardar el producto');
// Mensaje de advertencia
return redirect()->route('productos.index')
->with('warning', 'El producto no tiene stock');
// Múltiples mensajes
return redirect()->route('productos.index')
->with([
'success' => 'Producto actualizado',
'info' => 'Revisa los cambios realizados'
]);
// Mensaje con datos adicionales
return redirect()->route('productos.show', $producto->id)
->with('success', 'Producto actualizado')
->with('producto_id', $producto->id);
En la Vista (Mostrar mensajes):
Mostrar un arreglo de tareas con vistas y debugging
Este tutorial te guía paso a paso para crear una pequeña aplicación en Laravel que solo muestra una lista de tareas desde un arreglo en memoria. No incluye formulario para agregar, solo la visualización, y además incorpora técnicas de depuración con dump() y dd() para que veas qué ocurre internamente.
1. Estructura del proyecto
Crearemos:
Una ruta GET para acceder a la lista.
Un controlador con un arreglo estático de tareas.
Una vista Blade que renderiza la lista.
Puntos de debugging para inspeccionar los datos.
2. Definir la ruta (routes/web.php)
Abre el archivo routes/web.php y agrega la siguiente ruta:
php
<?php
use App\Http\Controllers\TareaController;
use Illuminate\Support\Facades\Route;
Route::get('/tareas', [TareaController::class, 'index'])->name('tareas.index');
GET /tareas: Cuando el usuario visite esa URL, se ejecutará el método index del TareaController.
name('tareas.index'): Asigna un nombre a la ruta para usarla en las vistas o redirecciones (aunque en este ejemplo solo la usaremos para mostrar).
3. Crear el controlador (app/Http/Controllers/TareaController.php)
Genera el controlador con el comando Artisan:
bash
php artisan make:controller TareaController
Luego, edita el archivo con el siguiente contenido:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TareaController extends Controller
{
// Arreglo estático de ejemplo (simula datos)
private $tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
public function index()
{
// Debug: mostramos el contenido del arreglo antes de enviarlo a la vista
dump($this->tareas); // Muestra en la barra de depuración (o en la página)
// También podemos usar dd() si queremos detener la ejecución para inspeccionar
// dd($this->tareas); // Descomenta para probar
return view('tareas.index', ['tareas' => $this->tareas]);
}
}
Explicación del controlador:
private $tareas: Es un arreglo fijo que simula una base de datos. En una aplicación real, aquí vendrían los datos desde un modelo.
index(): Prepara los datos y los pasa a la vista.
dump($this->tareas): Muestra el contenido del arreglo en la salida (útil para verificar que los datos existen). No detiene la ejecución.
dd($this->tareas): Si se descomenta, muestra el arreglo y detiene la ejecución, ideal para depurar en un punto crítico.
4. Crear la vista (resources/views/tareas/index.blade.php)
Crea la carpeta tareas dentro de resources/views y dentro de ella el archivo index.blade.php:
html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lista de Tareas</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.debug-box { background: #f4f4f4; padding: 10px; border-left: 4px solid #007bff; margin-bottom: 20px; }
ul { list-style: none; padding: 0; }
li { background: #e9ecef; margin: 5px 0; padding: 8px; border-radius: 4px; }
</style>
</head>
<body>
<h1>📋 Mis Tareas</h1>
<!-- Caja de depuración en la vista -->
<div class="debug-box">
<strong>🔍 Debug: Contenido de la variable $tareas</strong>
@dump($tareas) <!-- Muestra el contenido de $tareas en la vista -->
</div>
<!-- Lista de tareas -->
@if(count($tareas) > 0)
<ul>
@foreach($tareas as $tarea)
<li>
<strong>ID:</strong> {{ $tarea['id'] }} -
<strong>Nombre:</strong> {{ $tarea['nombre'] }}
</li>
@endforeach
</ul>
@else
<p>No hay tareas para mostrar.</p>
@endif
<p><small>Datos estáticos (se pierden al reiniciar el servidor).</small></p>
</body>
</html>
Explicación de la vista:
@dump($tareas): Muestra el contenido de la variable en un formato legible, directamente en la página. Es súper útil para ver qué datos está recibiendo la vista.
@foreach recorre el arreglo y muestra cada tarea.
Se usa {{ }} para escapar la salida y evitar inyección XSS.
5. Probar la aplicación
Inicia el servidor de desarrollo:
php artisan serve
Ahora abre tu navegador en: http://localhost:8000/tareas
Verás:
La lista de tareas con sus IDs y nombres.
Un bloque de depuración que muestra el arreglo completo (gracias a @dump en la vista).
En la parte superior (si estás en modo de depuración), también verás la salida de dump($this->tareas) del controlador.
6. Flujo de trabajo explicado
El usuario hace una petición GET a /tareas.
Laravel busca la ruta definida en web.php y ejecuta el método index del TareaController.
El controlador tiene un arreglo $tareas con datos de ejemplo.
Se ejecuta dump($this->tareas) que muestra el arreglo en la barra de depuración (no detiene la ejecución).
El controlador retorna la vista tareas.index pasándole el arreglo.
La vista recibe $tareas, y con @dump($tareas) lo muestra en el HTML para inspección visual.
Finalmente, la vista renderiza la lista de tareas.
7. ¿Qué pasa si usamos dd() en lugar de dump()?
Si en el controlador cambias dump($this->tareas) por dd($this->tareas), la ejecución se detiene y solo verás el contenido del arreglo, sin llegar a la vista. Esto es útil cuando quieres verificar que los datos existen antes de que ocurra cualquier otro procesamiento.
Puedes probar cambiando esa línea y recargando la página para ver el efecto.
8. Notas importantes
Datos en memoria: El arreglo se define dentro del controlador. Cada vez que se ejecuta el método index, se crea el arreglo desde cero. Si modificaramos el arreglo (por ejemplo, agregando una tarea), los cambios no se persistirían porque no hay una base de datos.
Para aplicaciones reales: En lugar de un arreglo estático, usarías un modelo de Eloquent para obtener datos desde la base de datos.
Depuración en producción: dump() y dd() solo deben usarse en entornos de desarrollo. En producción, asegúrate de que APP_DEBUG=false en tu archivo .env.
9. Ampliación: Mostrar también en consola
Si prefieres ver la información en la consola (cuando ejecutas pruebas o comandos), puedes usar logger() o info():
php
logger('Tareas:', $this->tareas);
Esto escribirá en el archivo de logs (storage/logs/laravel.log).
10. Resumen del código final
Ruta (routes/web.php):
php
Route::get('/tareas', [TareaController::class, 'index'])->name('tareas.index');
Controlador (app/Http/Controllers/TareaController.php):
php
<?php
namespace App\Http\Controllers;
class TareaController extends Controller
{
private $tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
public function index()
{
dump($this->tareas); // Depuración en el controlador
return view('tareas.index', ['tareas' => $this->tareas]);
}
}
Vista (resources/views/tareas/index.blade.php):
html
<!DOCTYPE html>
<html>
<head>
<title>Lista de Tareas</title>
</head>
<body>
<h1>Mis Tareas</h1>
@dump($tareas) <!-- Depuración en la vista -->
<ul>
@foreach($tareas as $tarea)
<li>{{ $tarea['id'] }} - {{ $tarea['nombre'] }}</li>
@endforeach
</ul>
</body>
</html>
Conclusión
Has creado un ejemplo funcional que muestra un arreglo de tareas en una vista, con puntos de depuración para entender mejor el flujo de datos. Este es el primer paso para construir aplicaciones más complejas, donde los datos vendrán de la base de datos y se podrán agregar, editar o eliminar.
¡Sigue practicando! Prueba a modificar el arreglo, agregar más campos o cambiar el estilo de la vista. Cuando te sientas cómodo, avanza al siguiente nivel: conectar con una base de datos usando Eloquent.
Separar controladores para Web y API en Laravel (Enfoque para principiantes)
Crear el controlador (TareaController)
Genera el controlador si no existe:
bash
php artisan make:controller TareaController
Luego, edita el archivo app/Http/Controllers/TareaController.php con el siguiente contenido:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TareaController extends Controller
{
// Arreglo de ejemplo (simula base de datos)
private $tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
/**
* Muestra la lista de tareas.
* Si la solicitud espera JSON, devuelve los datos en formato JSON.
* Si no, devuelve la vista Blade.
*/
public function index(Request $request)
{
// Depuración: mostrar el arreglo en la barra de debug (solo en desarrollo)
dump($this->tareas);
// Si la solicitud es para una API (espera JSON)
if ($request->wantsJson()) {
// También podemos usar dd() para inspeccionar antes de devolver
// dd($this->tareas); // Descomentar para depurar
return response()->json([
'status' => 'success',
'data' => $this->tareas
]);
}
// Si no espera JSON, devuelve la vista web
return view('tareas.index', ['tareas' => $this->tareas]);
}
/**
* (Opcional) Obtener una tarea específica por ID.
* Este método solo se usará para la API.
*/
public function show($id)
{
// Buscar la tarea por ID (simulación)
$tarea = collect($this->tareas)->firstWhere('id', $id);
if (!$tarea) {
return response()->json(['error' => 'Tarea no encontrada'], 404);
}
return response()->json($tarea);
}
}
Explicación del controlador:
$tareas: Arreglo estático con datos de ejemplo.
index(Request $request):
Usa $request->wantsJson() para detectar si el cliente espera una respuesta JSON (generalmente cuando el encabezado Accept: application/json está presente).
Si es así, devuelve un JsonResponse con los datos y un estado success.
Si no, devuelve la vista tareas.index pasando el arreglo.
show($id): Método adicional para la API que devuelve una tarea específica. No tiene vista asociada, solo JSON.
Pregunta frecuente: ¿Es mejor crear un solo controlador que maneje tanto vistas como JSON, o crear dos controladores separados?
Respuesta: Para un principiante, lo más normal y recomendado es usar dos controladores separados. Aunque técnicamente es posible usar el mismo, separarlos te da un código más limpio, fácil de mantener y seguir las buenas prácticas de Laravel.
En este tutorial construirás una aplicación de tareas con:
Controlador Web: Para mostrar vistas Blade.
Controlador API: Para devolver JSON (endpoints RESTful).
Ambos compartirán la misma lógica de negocio (por ahora un arreglo en memoria).
Incluiremos técnicas de depuración con dump() y dd() para que entiendas el flujo.
¿Por qué separar controladores?
Responsabilidad única: Cada controlador tiene un propósito claro (web vs API).
Mantenibilidad: Si cambia la API (ej. agregar versionado), no afecta la web.
Flexibilidad: Puedes usar diferentes middlewares, validaciones o formatos de respuesta.
Principio de separación de concerns: Es más fácil de entender para otros desarrolladores.
En proyectos grandes, es la práctica estándar (Laravel incluso sugiere estructuras como app/Http/Controllers/Api).
1. Configuración inicial
Asegúrate de tener un proyecto Laravel nuevo o existente. Si no, crea uno:
bash
composer create-project laravel/laravel tareas-app
cd tareas-app
2. Crear los controladores
2.1. Controlador Web
El controlador web estará en app/Http/Controllers/TareaController.php (el nombre por defecto). Lo creamos con Artisan:
bash
php artisan make:controller TareaController
2.2. Controlador API
Para la API, es común crear una subcarpeta Api dentro de Controllers. Lo haremos así:
bash
php artisan make:controller Api/TareaController
Esto creará app/Http/Controllers/Api/TareaController.php.
3. Definir las rutas
3.1. Rutas web (routes/web.php)
php
<?php
use App\Http\Controllers\TareaController;
use Illuminate\Support\Facades\Route;
Route::get('/tareas', [TareaController::class, 'index'])->name('tareas.index');
3.2. Rutas API (routes/api.php)
php
<?php
use App\Http\Controllers\Api\TareaController as ApiTareaController;
use Illuminate\Support\Facades\Route;
Route::get('/tareas', [ApiTareaController::class, 'index']);
Route::get('/tareas/{id}', [ApiTareaController::class, 'show']);
Nota: Usamos un alias ApiTareaController para evitar conflicto de nombres con el controlador web.
4. Implementar el Controlador Web
Abre app/Http/Controllers/TareaController.php y escribe:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TareaController extends Controller
{
// Arreglo de ejemplo (simula base de datos)
private $tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
/**
* Muestra la lista de tareas en una vista.
*/
public function index()
{
// Depuración: mostrar el arreglo antes de enviar a la vista
dump($this->tareas); // Aparece en la barra de debug (si está instalada) o en la salida
return view('tareas.index', ['tareas' => $this->tareas]);
}
// (Opcional) Podrías agregar otros métodos como store, edit, etc., pero para este ejemplo solo mostramos.
}
Observaciones:
El controlador web solo se preocupa por devolver vistas.
No tiene lógica de detección de JSON, porque su función es puramente web.
Usamos dump() para inspeccionar el arreglo.
5. Implementar el Controlador API
Abre app/Http/Controllers/Api/TareaController.php y escribe:
php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class TareaController extends Controller
{
// El mismo arreglo de ejemplo (podríamos extraerlo a un servicio compartido, pero por simplicidad lo duplicamos)
private $tareas = [
['id' => 1, 'nombre' => 'Comprar pan'],
['id' => 2, 'nombre' => 'Estudiar Laravel'],
['id' => 3, 'nombre' => 'Hacer ejercicio'],
];
/**
* Devuelve todas las tareas en JSON.
*/
public function index()
{
// Depuración: inspeccionar antes de devolver
dump($this->tareas); // Visible en la barra de debug
// Podríamos usar dd() para detener la ejecución y ver el arreglo
// dd($this->tareas); // Descomentar para probar
return response()->json([
'status' => 'success',
'data' => $this->tareas
]);
}
/**
* Devuelve una tarea específica en JSON.
*/
public function show($id)
{
// Buscar la tarea por ID
$tarea = collect($this->tareas)->firstWhere('id', (int)$id);
if (!$tarea) {
return response()->json([
'status' => 'error',
'message' => 'Tarea no encontrada'
], 404);
}
return response()->json([
'status' => 'success',
'data' => $tarea
]);
}
}
Observaciones:
El controlador API siempre devuelve JSON.
Incluye manejo de errores con códigos HTTP apropiados (404).
Podemos usar dump() para depurar antes de enviar la respuesta.
El arreglo está duplicado; en una aplicación real, lo ideal sería tener una capa de servicio o un repositorio para compartir la lógica (pero eso es más avanzado).
6. Crear la vista web
Crea la carpeta resources/views/tareas y dentro el archivo index.blade.php:
html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mis Tareas</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.debug-box { background: #f0f0f0; padding: 10px; border-left: 4px solid #007bff; margin-bottom: 20px; }
ul { list-style: none; padding: 0; }
li { background: #e9ecef; margin: 5px 0; padding: 8px; border-radius: 4px; }
.api-info { background: #d4edda; padding: 10px; border-radius: 4px; margin-top: 20px; }
</style>
</head>
<body>
<h1>📋 Lista de Tareas (Web)</h1>
<!-- Depuración en la vista -->
<div class="debug-box">
<strong>🔍 Debug: Contenido de $tareas (desde la vista)</strong>
@dump($tareas)
</div>
@if(count($tareas) > 0)
<ul>
@foreach($tareas as $tarea)
<li><strong>ID:</strong> {{ $tarea['id'] }} - <strong>Nombre:</strong> {{ $tarea['nombre'] }}</li>
@endforeach
</ul>
@else
<p>No hay tareas.</p>
@endif
<div class="api-info">
<p><strong>🌐 También dispones de una API:</strong></p>
<p>Endpoint: <code>/api/tareas</code> (devuelve JSON)</p>
<p>Prueba con curl: <code>curl -H "Accept: application/json" http://localhost:8000/api/tareas</code></p>
</div>
</body>
</html>
7. Probar la aplicación
7.1. Iniciar el servidor
bash
php artisan serve
7.2. Probar la web
Abre http://localhost:8000/tareas en tu navegador. Verás la lista de tareas y el bloque de depuración.
7.3. Probar la API
Usa Postman, Insomnia o curl en la terminal:
bash
curl -H "Accept: application/json" http://localhost:8000/api/tareas
Deberías obtener:
json
{
"status": "success",
"data": [
{"id":1,"nombre":"Comprar pan"},
{"id":2,"nombre":"Estudiar Laravel"},
{"id":3,"nombre":"Hacer ejercicio"}
]
}
Y para una tarea específica:
bash
curl -H "Accept: application/json" http://localhost:8000/api/tareas/1
Respuesta:
json
{
"status": "success",
"data": {"id":1,"nombre":"Comprar pan"}
}
Si pruebas con un ID inexistente (ej. /api/tareas/99), obtendrás un error 404 con el mensaje correspondiente.
8. Depuración con dump() y dd()
Ambos controladores incluyen dump($this->tareas). Esto te permite ver el contenido del arreglo en la barra de depuración de Laravel (si tienes el paquete laravel/debugbar instalado) o en la salida de la página. Si no ves nada, instala Debugbar:
bash
composer require barryvdh/laravel-debugbar --dev
Luego, si quieres detener la ejecución para inspeccionar un punto específico, descomenta dd($this->tareas) en cualquiera de los controladores. Por ejemplo, en el controlador API:
php
public function index()
{
dd($this->tareas); // Muestra el arreglo y detiene todo
// ...
}
Al hacer una petición a la API, verás el dump y no se devolverá JSON, pero es útil para depurar.
En la vista, también puedes usar @dd($tareas) en lugar de @dump para detener la renderización y mostrar el contenido.
9. ¿Qué pasa si queremos compartir los datos entre controladores?
En el ejemplo duplicamos el arreglo en ambos controladores. Para evitar duplicación, podríamos:
Crear un servicio (clase) que gestione las tareas y lo inyectar en ambos controladores.
Usar un modelo con base de datos (lo más común).
Usar un trait o una clase base.
Por simplicidad, para este tutorial lo dejamos así, pero en la práctica avanzada se recomienda una capa de servicio.
10. Conclusión: ¿Es buena práctica separar controladores?
Sí, es la práctica recomendada y la más común en proyectos Laravel. Separar controladores para web y API te da:
Código más organizado y fácil de leer.
Menos riesgo de romper una parte al modificar la otra.
Posibilidad de aplicar middlewares específicos (ej. autenticación para API con Sanctum, y sesiones para web).
Escalabilidad: si necesitas versionar la API (v1, v2), es más sencillo.
Los principiantes suelen empezar con un solo controlador por simplicidad, pero a medida que el proyecto crece, la separación se vuelve necesaria. Este tutorial te muestra el camino correcto desde el inicio.
Ahora ya sabes cómo estructurar tu aplicación para que tenga tanto interfaz web como API, manteniendo cada parte en su lugar.
11. Extras: Mejoras sugeridas
Validación: Agrega validación en los métodos de creación/actualización.
Eloquent: Reemplaza el arreglo por un modelo Tarea y una base de datos.
API Resources: Usa TareaResource para formatear la salida JSON de manera más controlada.
Autenticación: Protege la API con Laravel Sanctum o Passport.
Comentarios
Publicar un comentario