Laravel

Laravel

Tutorial Laravel: Formularios y validación

Laravel y Blade facilitan la creación de formularios seguros con validación y gestión de datos. Aprende a utilizar directivas y mensajes de error.

Aprende Laravel GRATIS y certifícate

Creación de formularios con Blade

En Laravel, la creación de formularios se simplifica gracias al motor de plantillas Blade, que permite integrar código PHP dentro de las vistas de forma elegante. Para empezar a construir formularios, se puede utilizar la sintaxis HTML estándar dentro de un archivo Blade:

<form action="/ruta" method="POST">
    <!-- Campos del formulario -->
</form>

Es fundamental incluir el token CSRF en todos los formularios que envíen datos mediante métodos POST, PUT, PATCH o DELETE. Laravel proporciona la directiva @csrf para insertar automáticamente este token y proteger la aplicación contra ataques CSRF:

<form action="/ruta" method="POST">
    @csrf
    <!-- Campos del formulario -->
</form>

Si se necesita utilizar un método HTTP distinto de POST, como PUT o DELETE, se emplea la directiva @method para especificarlo:

<form action="/ruta" method="POST">
    @csrf
    @method('PUT')
    <!-- Campos del formulario -->
</form>

Para añadir campos al formulario, se pueden utilizar las etiquetas HTML correspondientes. Por ejemplo, un campo de texto para el nombre:

<input type="text" name="nombre" value="{{ old('nombre') }}">

La función old('campo') permite repoblar el valor del campo con la entrada anterior del usuario, facilitando la experiencia en caso de errores de validación.

Los selects y checkboxes también se crean de forma similar, aprovechando las directivas de Blade para manejar datos dinámicos. Por ejemplo, para un campo de selección de país:

<select name="pais">
    <option value="es" {{ old('pais') == 'es' ? 'selected' : '' }}>España</option>
    <option value="mx" {{ old('pais') == 'mx' ? 'selected' : '' }}>México</option>
    <option value="ar" {{ old('pais') == 'ar' ? 'selected' : '' }}>Argentina</option>
</select>

En este caso, se utiliza una expresión condicional para marcar como selected la opción previamente elegida por el usuario.

Para mostrar mensajes de error asociados a cada campo, se utiliza la directiva @error de Blade:

<input type="email" name="correo" value="{{ old('correo') }}">
@error('correo')
    <div class="error">{{ $message }}</div>
@enderror

Esta directiva verifica si existe un mensaje de error para el campo especificado y, en caso afirmativo, lo muestra al usuario.

Es posible organizar y reutilizar componentes de formulario creando sub-vistas o componentes en Blade. Por ejemplo, se puede crear un componente para un campo de entrada:

<!-- resources/views/components/campo-texto.blade.php -->
<div>
    <label for="{{ $nombre }}">{{ $etiqueta }}</label>
    <input type="text" name="{{ $nombre }}" id="{{ $nombre }}" value="{{ old($nombre) }}">
    @error($nombre)
        <div class="error">{{ $message }}</div>
    @enderror
</div>

Y luego incluirlo en las vistas donde se requiera:

<!-- En la vista -->
@component('components.campo-texto', ['nombre' => 'usuario', 'etiqueta' => 'Nombre de Usuario'])
@endcomponent

Al estructurar los formularios de esta manera, se mejora la reutilización de código y la mantenibilidad de la aplicación.

Además, se pueden aplicar estilos y clases CSS directamente en los elementos del formulario para mejorar la interfaz de usuario:

<input type="password" name="contraseña" class="form-control" value="{{ old('contraseña') }}">

Finalmente, para manejar la subida de archivos, es necesario añadir el atributo enctype al formulario y utilizar el campo de tipo file:

<form action="/subir" method="POST" enctype="multipart/form-data">
    @csrf
    <input type="file" name="documento">
    <button type="submit">Enviar</button>
</form>

Con estas prácticas, la creación de formularios con Blade en Laravel se vuelve eficiente y segura, aprovechando las potentes herramientas que el framework ofrece para el desarrollo web profesional.

Procesamiento de solicitudes y entrada del usuario

Una vez que se ha creado un formulario con Blade y el usuario lo ha enviado, es necesario procesar la solicitud HTTP en el servidor. En Laravel, esto se logra mediante la definición de rutas y la implementación de métodos en los controladores que manejan dichas solicitudes.

Para empezar, es esencial definir una ruta que apunte al método del controlador responsable de procesar la entrada del usuario. Por ejemplo:

// routes/web.php

use App\Http\Controllers\UsuarioController;

Route::post('/usuarios', [UsuarioController::class, 'store']);

En este caso, la ruta /usuarios acepta solicitudes POST y las dirige al método store del UsuarioController.

Dentro del controlador, se utiliza la instancia de Request para acceder a los datos enviados por el usuario:

// app/Http/Controllers/UsuarioController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UsuarioController extends Controller
{
    public function store(Request $request)
    {
        // Procesar la solicitud
    }
}

El objeto $request proporciona múltiples métodos para acceder y manipular la entrada del usuario. Por ejemplo, para obtener un valor específico:

$nombre = $request->input('nombre');

También es posible obtener todos los datos de la solicitud en forma de arreglo utilizando el método all():

$datos = $request->all();

Para una manipulación más segura, se recomienda utilizar el método only() o except() para seleccionar o excluir campos específicos:

$datos = $request->only(['nombre', 'email', 'contraseña']);

Al procesar solicitudes, es común necesitar almacenar registros en la base de datos. Esto se puede hacer creando una instancia de un modelo y asignando los datos del $request:

use App\Models\Usuario;

$usuario = new Usuario;
$usuario->nombre = $request->input('nombre');
$usuario->email = $request->input('email');
$usuario->contraseña = bcrypt($request->input('contraseña'));
$usuario->save();

En este ejemplo, se utiliza el método bcrypt() para cifrar la contraseña antes de almacenarla, lo cual es una buena práctica de seguridad.

Si en el formulario se envían archivos, Laravel facilita su manejo a través de métodos específicos. Para verificar si un archivo ha sido subido:

if ($request->hasFile('avatar')) {
    $archivo = $request->file('avatar');
}

Una vez obtenido el archivo, se puede almacenar utilizando el método store():

$ruta = $archivo->store('avatars');

Este método almacena el archivo en el directorio storage/app/avatars y devuelve la ruta donde se ha guardado.

Después de procesar la solicitud, es habitual redirigir al usuario a otra página o vista. Laravel proporciona el helper redirect() para ello:

return redirect()->route('usuarios.index');

También es posible redirigir al usuario de vuelta a la página anterior utilizando back():

return back();

Para enviar datos de sesión, como mensajes de éxito o información adicional, se utiliza el método with():

return redirect()->route('usuarios.index')->with('success', 'Usuario creado correctamente');

En la vista, se puede mostrar este mensaje comprobando la existencia de la variable de sesión:

@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif

Cuando se necesita mantener los datos introducidos por el usuario en caso de un error, se emplea el método withInput():

return back()->withInput();

Esto es útil para repoblar los campos del formulario con los valores previos, mejorando la experiencia de usuario.

Para acceder a métodos HTTP específicos o verificar alguna condición de la solicitud, el objeto $request ofrece métodos como isMethod(), has(), entre otros:

if ($request->isMethod('post')) {
    // La solicitud es de tipo POST
}

if ($request->has('email')) {
    // La solicitud contiene el campo 'email'
}

Además, se pueden obtener cabeceras y otros datos de la solicitud:

$userAgent = $request->header('User-Agent');
$ipAddress = $request->ip();

Estos datos pueden ser útiles para registro o análisis de la actividad del usuario.

Es importante gestionar adecuadamente la seguridad y la integridad de los datos al procesar la entrada del usuario. Aunque en esta sección no profundizamos en la validación de datos, es esencial considerar su implementación para asegurar que la aplicación funcione correctamente y de manera segura.

Finalmente, para una mejor organización del código, se pueden utilizar Form Requests, que son clases dedicadas a manejar la lógica de solicitud, aunque su uso y configuración se abordan en secciones posteriores.

Validación de datos de entrada

La validación de datos es un paso crucial al procesar entradas del usuario para garantizar la integridad y seguridad de la aplicación. Laravel ofrece múltiples formas de validar datos de forma sencilla y eficiente, utilizando el método validate() disponible en los controladores.

Para validar los datos enviados en una solicitud, se puede emplear el método validate() directamente sobre la instancia de Request:

public function store(Request $request)
{
    $datosValidados = $request->validate([
        'nombre' => 'required|string|max:255',
        'email' => 'required|email|unique:users,email',
        'contraseña' => 'required|min:8|confirmed',
    ]);

    // Procesar los datos validados
}

En este ejemplo, se definen reglas de validación para cada campo:

  • nombre: Obligatorio (required), de tipo cadena (string) y con un máximo de 255 caracteres.
  • email: Obligatorio, formato de correo electrónico válido (email) y único en la tabla users columna email.
  • contraseña: Obligatoria, mínimo 8 caracteres y debe confirmarse con un campo contraseña_confirmation.

Si la validación falla, Laravel redirigirá automáticamente de vuelta al formulario anterior con los errores de validación y la entrada previa del usuario. Los mensajes de error se almacenan en la variable $errors, accesible desde las vistas.

Para mostrar los mensajes de error en la vista, se utiliza la variable $errors y las directivas de Blade:

@if ($errors->any())
    <div class="alert alert-danger">
        <p><strong>Se han producido los siguientes errores:</strong></p>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Este fragmento muestra una lista de todos los errores generados durante la validación.

También es posible mostrar mensajes de error específicos para cada campo utilizando la directiva @error:

<div>
    <label for="nombre">Nombre</label>
    <input type="text" name="nombre" value="{{ old('nombre') }}" id="nombre">
    @error('nombre')
        <div class="error">{{ $message }}</div>
    @enderror
</div>

De esta manera, el usuario recibe una retroalimentación inmediata sobre los campos que necesitan corregirse.

Laravel proporciona una amplia variedad de reglas de validación predefinidas, que permiten verificar diferentes tipos de datos y condiciones. Algunas reglas comunes incluyen:

  • required: El campo es obligatorio.
  • email: Debe ser una dirección de correo electrónico válida.
  • max:min: El valor máximo permitido.
  • min:max: El valor mínimo requerido.
  • unique:table,column: El valor debe ser único en una tabla y columna específicas.
  • confirmed: El campo debe tener un campo de confirmación correspondiente (ejemplo: contraseña_confirmation).

Además de las reglas predefinidas, es posible crear reglas personalizadas utilizando funciones de cierre (closures) o clases de validación:

$request->validate([
    'edad' => [
        'required',
        function ($attribute, $value, $fail) {
            if ($value < 18) {
                $fail('El campo ' . $attribute . ' debe ser mayor o igual a 18.');
            }
        },
    ],
]);

En este ejemplo, se añade una regla personalizada que verifica que la edad sea mayor o igual a 18.

Para personalizar los mensajes de error, se puede pasar un arreglo adicional al método validate() con los mensajes especificados:

$request->validate([
    'nombre' => 'required',
    'email' => 'required|email',
], [
    'nombre.required' => 'El campo nombre es obligatorio.',
    'email.required' => 'El correo electrónico es necesario.',
    'email.email' => 'Debe proporcionar un correo electrónico válido.',
]);

Esto permite ofrecer mensajes de error más claros y adaptados a la aplicación.

Otra opción es definir los mensajes de validación en los archivos de localización dentro de resources/lang/es/validation.php, facilitando la gestión de mensajes en diferentes idiomas.

Para validaciones más complejas o para mantener el controlador limpio, es recomendable utilizar Form Request. Un Form Request es una clase dedicada a manejar la lógica de validación:

php artisan make:request StoreUsuarioRequest

Este comando crea una clase StoreUsuarioRequest donde se definen las reglas de validación:

// app/Http/Requests/StoreUsuarioRequest.php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUsuarioRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'nombre' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'contraseña' => 'required|min:8|confirmed',
        ];
    }
}

Luego, se inyecta el Form Request en el controlador:

// app/Http/Controllers/UsuarioController.php

use App\Http\Requests\StoreUsuarioRequest;

public function store(StoreUsuarioRequest $request)
{
    $datos = $request->validated();

    // Procesar los datos validados
}

El método validated() retorna solamente los campos que han sido validados, garantizando que solo se utilice información segura.

También es posible aplicar validación condicional utilizando el método sometimes() dentro de Form Requests o utilizando reglas condicionales en línea.

Para escenarios donde se requiere validar campos dependiendo de otros valores, se pueden emplear las reglas required_if, required_unless, required_with, entre otras.

Ejemplo de validación condicional:

$request->validate([
    'contraseña' => 'required|min:8|confirmed',
    'tipo_usuario' => 'required',
    'empresa' => 'required_if:tipo_usuario,empresa',
]);

En este caso, el campo empresa es obligatorio si el tipo_usuario es empresa.

Además, Laravel proporciona validación para arrays y campos anidados. Por ejemplo:

$request->validate([
    'productos.*.nombre' => 'required',
    'productos.*.precio' => 'required|numeric',
]);

Esta regla valida que cada elemento del array productos tenga los campos nombre y precio correctamente definidos.

Para validar archivos y subirlos de manera segura, se utilizan las reglas file, image, mimes, max, entre otras:

$request->validate([
    'avatar' => 'required|image|mimes:jpeg,png,jpg|size:2048',
]);

Aquí se valida que el avatar sea una imagen en formato JPEG o PNG y que su tamaño no exceda los 2 MB.

Cuando se requiere validar entradas basadas en la localización o formatos específicos, se pueden utilizar reglas como date, timezone, locale, asegurando que los datos cumplan con los estándares esperados.

Además, es posible extender el sistema de validación creando reglas personalizadas mediante clases que implementen la interfaz Rule:

php artisan make:rule EdadValida

Esto genera una clase donde se puede definir la lógica de validación:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class EdadValida implements Rule
{
    public function passes($attribute, $value)
    {
        return $value >= 18 && $value <= 65;
    }

    public function message()
    {
        return 'La edad debe estar entre 18 y 65 años.';
    }
}

Y se utiliza en la validación:

use App\Rules\EdadValida;

$request->validate([
    'edad' => ['required', new EdadValida],
]);

La validación de datos es esencial para prevenir errores y posibles vulnerabilidades en la aplicación, como inyección de SQL o ataques XSS. Al usar las herramientas que Laravel proporciona, se facilita el proceso y se garantiza que solo se procesen datos seguros y confiables.

Mensajes de error y retroalimentación al usuario

Proporcionar retroalimentación al usuario es esencial para mejorar la experiencia en una aplicación web. En Laravel, se pueden manejar los mensajes de error y éxito de forma eficiente utilizando las sesiones y las vistas Blade. Los mensajes flash son una herramienta poderosa para mostrar información temporal al usuario después de una operación, como la creación o actualización de un registro.

Uso de mensajes flash para retroalimentación

Los mensajes flash se almacenan en la sesión y persisten solo durante la siguiente solicitud. Para almacenar un mensaje flash, se utiliza el método with() al redirigir después de procesar una solicitud:

return redirect()->route('home')->with('success', 'Operación realizada exitosamente');

En este ejemplo, se almacena en la sesión un mensaje con la clave 'success'. En la vista, se puede verificar si existe este mensaje y mostrarlo al usuario:

@if (session('success'))
    <div class="alert alert-success">
        {{ session('success') }}
    </div>
@endif

De forma similar, se pueden manejar mensajes de diferentes tipos, como 'error', 'warning' o 'info', categorizándolos según la naturaleza de la información que se desea comunicar.

Mostrar múltiples mensajes de retroalimentación

Cuando es necesario mostrar múltiples mensajes, se pueden pasar como un arreglo asociativo en el método with():

return redirect()->back()->with([
    'error' => 'Hubo un problema al procesar su solicitud',
    'info' => 'Por favor, intente nuevamente más tarde'
]);

En la vista, se accede a cada mensaje utilizando su clave correspondiente:

@if (session('error'))
    <div class="alert alert-danger">
        {{ session('error') }}
    </div>
@endif

@if (session('info'))
    <div class="alert alert-info">
        {{ session('info') }}
    </div>
@endif

Esta práctica permite una comunicación clara con el usuario, brindándole información relevante sobre las acciones realizadas.

Utilización de componentes para mensajes

Para mantener un código limpio y evitar redundancias, es recomendable crear componentes Blade o parciales para los mensajes de retroalimentación. Por ejemplo, se puede crear un componente para las alertas:

<!-- resources/views/components/alerta.blade.php -->
<div class="alert alert-{{ $tipo }}">
    {{ $slot }}
</div>

Al utilizar el componente, se simplifica la inclusión de mensajes en las vistas:

<!-- En la vista -->
@if (session('success'))
    @component('components.alerta', ['tipo' => 'success'])
        {{ session('success') }}
    @endcomponent
@endif

Esta modularidad facilita la mantenibilidad y el reuso de código en la aplicación.

Mensajes de error personalizados

Además de los mensajes de éxito, es importante proporcionar mensajes de error detallados cuando ocurren problemas. Se pueden capturar excepciones específicas y mostrar mensajes personalizados:

try {
    // Operación que puede generar una excepción
} catch (\Exception $e) {
    return redirect()->back()->with('error', 'Ocurrió un error inesperado: ' . $e->getMessage());
}

Sin embargo, por razones de seguridad, es recomendable no exponer detalles técnicos al usuario final. En su lugar, se pueden registrar los errores y mostrar un mensaje genérico:

use Illuminate\Support\Facades\Log;

try {
    // Operación propensa a errores
} catch (\Exception $e) {
    Log::error('Error al procesar la solicitud: ' . $e->getMessage());
    return redirect()->back()->with('error', 'Hubo un problema al completar la operación');
}

Internacionalización de mensajes

Para aplicaciones que soportan múltiples idiomas, es esencial utilizar la internacionalización al manejar mensajes. Laravel proporciona funciones para traducir cadenas de texto utilizando archivos de localización:

return redirect()->back()->with('success', __('messages.operacion_exitosa'));

Donde 'messages.operacion_exitosa' es una entrada definida en los archivos de idioma dentro de resources/lang.

En la vista, los mensajes se muestran de la misma manera, asegurando que la experiencia del usuario sea consistente en todos los idiomas soportados.

Mantener la entrada del usuario con withInput()

Cuando una validación falla o ocurre un error, es útil mantener la entrada del usuario para que no tenga que volver a ingresar sus datos. Utilizando el método withInput(), se puede redirigir la solicitud y conservar los datos previos:

return redirect()->back()->withErrors($validator)->withInput();

En el formulario, los campos pueden repoblarse utilizando la función old():

<input type="text" name="nombre" value="{{ old('nombre') }}">

De esta forma, se mejora la usabilidad del formulario y se reduce la frustración del usuario.

Implementación de mensajes de validación en componentes

Para centralizar la presentación de errores de validación, es posible crear un componente para los mensajes de error:

<!-- resources/views/components/errores.blade.php -->
@if ($errors->any())
    <div class="alert alert-danger">
        <p><strong>Se han encontrado los siguientes errores:</strong></p>
        <ul>
            @foreach ($errors->all() as $mensaje)
                <li>{{ $mensaje }}</li>
            @endforeach
        </ul>
    </div>
@endif

En las vistas, se incluye el componente sin necesidad de repetir código:

<!-- En la vista del formulario -->
<x-errores />

<!-- Campos del formulario -->

Esto garantiza una gestión consistente de los mensajes de error en todas las partes de la aplicación.

Personalización de las clases CSS para mensajes

Para adaptar el estilo de los mensajes al diseño de la aplicación, se pueden personalizar las clases CSS utilizadas. Por ejemplo, si se trabaja con un framework CSS como Tailwind CSS, se ajustan las clases correspondientes:

<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
    {{ session('error') }}
</div>

Personalizar las clases permite que los mensajes se integren de manera coherente con la estética general de la interfaz.

Uso de paquetes y librerías para notificaciones

Existen paquetes y librerías que facilitan la gestión de notificaciones y mensajes al usuario, como Laravel Notify o SweetAlert. Estos permiten implementar notificaciones más atractivas e interactivas:

// Utilizando Laravel SweetAlert
alert()->success('Título', 'Mensaje de éxito');

Sin embargo, es importante evaluar si la incorporación de estas herramientas añade valor a la aplicación y considerar las dependencias adicionales que conllevan.

Feedback en tiempo real

Para mejorar aún más la interactividad, se pueden utilizar solicitudes HTTP para procesar formularios sin recargar la página. Al recibir la respuesta, se muestran los mensajes de retroalimentación directamente en la interfaz:

// En JavaScript utilizando Fetch API
fetch('/ruta', {
    method: 'POST',
    body: datosFormulario
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        mostrarMensajeExito(data.message);
    } else {
        mostrarErrores(data.errors);
    }
});

En el controlador, se devuelve una respuesta en formato JSON:

return response()->json([
    'success' => true,
    'message' => 'Datos guardados correctamente'
]);

Esta técnica proporciona una experiencia más fluida al usuario y puede mejorar la percepción de rendimiento de la aplicación.

Consideraciones de accesibilidad

Al mostrar mensajes de retroalimentación, es fundamental considerar la accesibilidad para usuarios con discapacidades. Utilizar atributos ARIA y asegurarse de que los mensajes sean detectables por lectores de pantalla contribuye a una aplicación más inclusiva:

<div class="alert alert-success" role="alert">
    {{ session('success') }}
</div>

El atributo role="alert" indica a las tecnologías asistivas que este elemento contiene información importante.

Seguir estas prácticas en la gestión de mensajes de error y retroalimentación mejora significativamente la experiencia del usuario y contribuye al éxito de la aplicación web desarrollada con Laravel.

Para seguir leyendo hazte Plus

¿Ya eres Plus? Accede a la app

Plan mensual

19.00 € /mes

Precio normal mensual: 19 €
47 % DE DESCUENTO

Plan anual

10.00 € /mes

Ahorras 108 € al año
Precio normal anual: 120 €
Aprende Laravel GRATIS online

Todas las lecciones de Laravel

Accede a todas las lecciones de Laravel y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Laravel y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el uso de Blade para formularios en Laravel.
  2. Implementar tokens CSRF y métodos HTTP con Blade.
  3. Manipular datos de entrada en controladores.
  4. Aplicar validación de datos en solicitudes.
  5. Personalizar experiencias de usuario con errores y mensajes flash.