Skip to content

3. Rutas y controladores en Laravel

En una aplicación Inertia.js, la integración entre Laravel y Vue se realiza a través de rutas y controladores que renderizan componentes Vue. Esta sección explica cómo configurar correctamente estas conexiones.

Inertia.js proporciona un método de ayuda Route::inertia() que simplifica la creación de rutas que renderizan componentes Vue. Este método es un atajo que combina la definición de la ruta y el renderizado del componente en una sola línea.

routes/web.php
Route::inertia('/about', 'About');

Este código hace dos cosas:

  1. Define una ruta GET para la URL /about
  2. Renderiza el componente Vue ubicado en resources/js/Pages/About.vue

Puedes pasar datos (props) directamente en la definición de la ruta:

routes/web.php
Route::inertia('/users', 'Users/Index', [
'users' => User::all()
]);

Las rutas de tipo resource son muy comunes en aplicaciones Laravel para operaciones CRUD. Con Inertia, puedes seguir usando este patrón y conectarlo con componentes Vue correspondientes.

routes/web.php
// Definir rutas resource
Route::resource('users', UserController::class);

Esto generará las siguientes rutas que deberán corresponder con métodos en tu controlador:

Controladores que retornan Inertia::render()

Section titled “Controladores que retornan Inertia::render()”

Para renderizar componentes Vue desde un controlador Laravel, usamos el método Inertia::render():

app/Http/Controllers/UserController.php
<?php
namespace AppHttpControllers;
use AppModelsUser;
use InertiaInertia;
use IlluminateHttpRequest;
class UserController extends Controller
{
public function index()
{
return Inertia::render('Users/Index', [
'users' => User::all()
]);
}
public function show(User $user)
{
return Inertia::render('Users/Show', [
'user' => $user
]);
}
public function create()
{
return Inertia::render('Users/Create');
}
public function edit(User $user)
{
return Inertia::render('Users/Edit', [
'user' => $user
]);
}
// Otros métodos del controlador...
}

El método Inertia::render() acepta dos parámetros:

  1. El nombre del componente Vue a renderizar (relativo a tu directorio de páginas)
  2. Un array asociativo de datos (props) que se pasarán al componente Vue

Una de las características más potentes de Inertia.js es la facilidad para pasar datos desde el backend (Laravel) al frontend (Vue). Estos datos se conocen como “props”.

app/Http/Controllers/DashboardController.php
return Inertia::render('Dashboard', [
'name' => 'John Doe',
'email' => 'john@example.com',
]);

Puedes pasar modelos Eloquent directamente. Inertia los convertirá automáticamente a arrays/objetos JSON:

app/Http/Controllers/UserController.php
return Inertia::render('Users/Show', [
'user' => User::find($id)
]);

Las colecciones también se serializan automáticamente:

return Inertia::render('Users/Index', [
'users' => User::all()
]);

La paginación funciona perfectamente con Inertia:

app/Http/Controllers/UserController.php
return Inertia::render('Users/Index', [
'users' => User::paginate(10)
]);

En tus componentes Vue con Composition API, puedes acceder a estas props fácilmente:

resources/js/Pages/Users/Show.vue
<script setup>
import { defineProps } from 'vue';
// Definir y acceder a las props
const props = defineProps({
user: Object,
});
console.log(props.user.name);
</script>
<template>
<div>
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
</div>
</template>

Inertia.js funciona perfectamente con Vue 3 y la Composition API, permitiéndote aprovechar todas sus características modernas. Aquí hay algunos conceptos clave para trabajar con componentes Vue 3 usando Composition API en aplicaciones Inertia:

Estructura básica de un componente con Composition API

Section titled “Estructura básica de un componente con Composition API”
resources/js/Pages/Users/Index.vue
<script setup>
import { ref, onMounted } from 'vue';
import Layout from '@/Layouts/MainLayout.vue';
import { Head } from '@inertiajs/vue3';
// Define props
const props = defineProps({
users: Array,
});
// Estado reactivo
const counter = ref(0);
// Métodos
const increment = () => {
counter.value++;
};
// Hooks de ciclo de vida
onMounted(() => {
console.log('Componente montado');
});
</script>
<template>
<Head title="Lista de usuarios" />
<Layout>
<h1>Usuarios ({{ users.length }})</h1>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
<div>
<p>Contador: {{ counter }}</p>
<button @click="increment">Incrementar</button>
</div>
</Layout>
</template>

Inertia recomienda usar layouts persistentes para mejorar la experiencia del usuario:

resources/js/Layouts/MainLayout.vue
<script setup>
import { Head } from '@inertiajs/vue3';
import Navbar from '@/Components/Navbar.vue';
import Footer from '@/Components/Footer.vue';
</script>
<template>
<div class="layout">
<Navbar />
<main>
<slot></slot>
</main>
<Footer />
</div>
</template>

Inertia proporciona un componente Link y una función router para la navegación entre páginas sin recargar completamente:

<script setup>
import { Link } from '@inertiajs/vue3';
</script>
<template>
<div>
<!-- Navegación con el componente Link -->
<Link href="/users" class="btn">Ver usuarios</Link>
<Link :href="`/users/${userId}`" class="btn">Ver usuario</Link>
<!-- Con parámetros adicionales -->
<Link
href="/users"
:data="{ search: 'John' }"
:only="['users']"
preserve-scroll
>
Buscar usuarios
</Link>
</div>
</template>

También puedes usar el router programáticamente:

<script setup>
import { router } from '@inertiajs/vue3';
const goToUsers = () => {
router.visit('/users');
};
const createUser = (userData) => {
router.post('/users', userData, {
onSuccess: () => {
alert('Usuario creado con éxito');
},
preserveScroll: true,
});
};
</script>

Inertia permite compartir datos globalmente en toda la aplicación usando la propiedad $page:

<script setup>
import { computed } from 'vue';
import { usePage } from '@inertiajs/vue3';
// Acceder a datos compartidos
const page = usePage();
const user = computed(() => page.props.auth.user);
const isAdmin = computed(() => user.value?.role === 'admin');
</script>
<template>
<div>
<p v-if="user">Bienvenido, {{ user.name }}</p>
<div v-if="isAdmin" class="admin-panel">
<!-- Panel de administración -->
</div>
</div>
</template>

En Laravel, puedes compartir estos datos en el middleware HandleInertiaRequests:

app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
return [
'auth' => [
'user' => $request->user() ? [
'id' => $request->user()->id,
'name' => $request->user()->name,
'email' => $request->user()->email,
'role' => $request->user()->role,
] : null,
],
'flash' => [
'message' => fn () => $request->session()->get('message'),
'error' => fn () => $request->session()->get('error'),
],
];
}
🐝