Cuando estamos desarrollando una aplicación, uno de los puntos más importantes que debemos tomar en cuenta son las validaciones de entrada de datos de los usuarios. Para estos casos Laravel nos ofrece un componente de validación bastante poderoso que nos ayuda a validar estas entradas y mostrar mensajes a los usuarios de los errores que hayan cometido. Sin embargo, hay ocasiones en que nos gustaría presentar mensajes más amigables en vez de los predeterminados o, como el caso particular, cuando en una aplicación multi-idioma nos encontramos con el problema que los mensajes de error de la validación de los formularios muestran por defecto los nombres de los campos en un idioma en específico que puede llegar a confundir al usuario. Todos estos detalles los podemos configurar de una forma sencilla como veremos a continuación:

Para este tutorial trabajaremos con un formulario como el siguiente:

Al que podemos acceder por medio de una ruta de tipo GET y también definimos una ruta tipo POST para procesar los datos recibidos a través del formulario. Estas rutas estarán ubicadas en el archivo /routes/web.php si estás usando Laravel 5.3 o en el archivo /app/Http/routes.php si usas Laravel 5.1/5.2:

Route::get('/form', 'FormController@index');
Route::post('/form', 'FormController@store');

Además, contamos con un controlador que podemos crear ejecutando:

php artisan make:controller FormController

Con los métodos index para mostrar el formulario y store para la validación y procesamiento de los datos introducidos:

public function index()
{
    return view('form');
}

public function store(Request $request)
{
    $rules = [
        'student' => 'required|max:20',
    	'score' => 'required|numeric|min:1|max:10',
    ];

    $this->validate($request, $rules);

    // aquí va el procesamiento de los datos

    return back()->with('status','Datos cargados correctamente');
}

Usaremos también una vista para el formulario que creamos en /resources/views/form.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<link href="/css/app.css" rel="stylesheet">
	<style>
		body {
                margin-top: 80px;
            }
	</style>
	<title>Formulario</title>
</head>
<body>
    <div class="container">
	<div class=" row">
	     <div class="col-md-8 col-md-offset-2">
	         <div class="panel panel-default">
	             <div class="panel-heading">Formulario</div>
	             <div class="panel-body">
			 @include('messages')
	                 <form class="form-horizontal" role="form" method="POST" action="{{ url('/form') }}">
	                     {{ csrf_field() }}

	                        <div class="form-group">
	                            <label for="student" class="col-md-4 control-label">Estudiante</label>

	                            <div class="col-md-6">
	                                <input id="student" type="text" class="form-control" name="student" value="{{ old('student') }}">
	                            </div>
	                        </div>

	                        <div class="form-group">
	                            <label for="score" class="col-md-4 control-label">Puntuación</label>

	                            <div class="col-md-6">
	                                <input id="score" class="form-control" name="score" value="{{ old('score') }}" >
	                            </div>
	                        </div>

	                        <div class="form-group">
	                            <div class="col-md-6 col-md-offset-4">
	                                <button type="submit" class="btn btn-primary">
	                                    Enviar
	                                </button>
	                            </div>
	                        </div>
	                    </form>
	                </div>
	            </div>
	        </div>
	    </div>
	</div>
   </body>
</html>

Cuando una validación de un formulario falla Laravel redirecciona automáticamente al usuario a su previa ubicación junto con los mensajes de error que han sido guardados en la variable $errors en los datos de la sesión para que estén disponibles en la siguiente petición HTTP. Esta variable es una instancia de Illuminate\Support\MessageBag, la cual tiene un conjunto de métodos con los que podemos obtener los errores. Como por ejemplo:
Obtener todos los mensajes de error de todos los campos con el método all así:

foreach ($errors->all() as $message) {
    //
}

Podemos también, obtener todos los mensajes relacionados a un campo con el método get:

foreach ($errors->get('email') as $message) {
    //
}

Así como, obtener el primer error de un campo dado:

echo $errors->first('email');

Para conocer todos los métodos disponibles para trabajar la variable $errors puedes verlos en el código fuente del framework: Illuminate/Support/MessageBag.php

Con esta información creamos una vista parcial para que muestre los mensajes de error (messages.blade.php) que hemos incluido en la vista del formulario:

@if (count($errors) > 0)
    <div class="alert alert-danger">
    	<p>Corrige los siguientes errores:</p>
        <ul>
            @foreach ($errors->all() as $message)
                <li>{{ $message }}</li>
            @endforeach
        </ul>
    </div>
@endif

Como el formulario que vamos a trabajar lo queremos en español se debe configurar el proyecto de Laravel para que tome en cuenta ese idioma, tal y como se explica en Cómo usar el componente de traducciones de Laravel y así se muestren los mensajes de validación en español presentes en el archivo resource/lang/es/validation.php según las reglas que tengan los campos del formulario.

En caso de ser una aplicación multi-idioma debes asegurarte que tengas en el directorio resource/lang/ una carpeta con los archivos correspondientes por cada idioma presente en la aplicación.

Ahora, si nos vamos a la ruta definida anteriormente http://proyecto.dev/form y hacemos clic en el botón enviar sin ingresar ningún valor en los campos para hacer fallar la validación nos mostrará los siguientes mensajes según las reglas que tenemos definidas:

Personalización de los mensajes

Puede darse el caso que las estructuras de los mensajes no satisface al cliente porque quiere algo más amigable o no quiere mostrar el nombre del campo directamente en el mensaje. Tenemos dos opciones para personalizar estos mensajes:

La primera forma es hacerlo de manera local, es decir que afecte solo el formulario que se está validando colocando directamente en el controlador un arreglo $messages con pares regla – mensajes personalizado y luego enviarlo como tercer argumento del método validate:

$rules = [
    'student' => 'required|max:20',
    'score' => 'required|numeric|min:1|max:10',
];

$messages = [
    'student.required' => 'Agrega el nombre del estudiante.',
    'student.max' =>'El nombre del estudiante no puede ser mayor a :max caracteres.',
    'score.required' => 'Agrega la puntuación al estudiante.',
    'score.numeric' => 'La puntuación debe ser un número',
    'score.between' => 'La puntuación debe estar entre :min y :max'
];

$this->validate($request, $rules, $messages);

En el array $messages se sigue la convención atributo.regla para solo modificar el mensaje de la regla para ese atributo, pues si se coloca solo la regla lo tomará para todas las veces que se use la regla.

También, en caso que estés usando un Form Request para controlar la validación debes agregar el método messages() con los mensajes personalizados que sobreescribirá dicho método de la clase Illuminate\Foundation\Http\FormRequest que extiende el form request:

public function messages()
{
    return [
        'student.required' => 'Agrega el nombre del estudiante.',
        'student.max' =>'El nombre del estudiante no puede ser mayor a :max caracteres.',
        'score.required' => 'Agrega la puntuación al estudiante.',
        'score.numeric' => 'La puntuación debe ser un número',
        'score.between' => 'La puntuación debe estar entre :min y :max'
    ];
}

La segunda forma es hacerlo de manera global modificando el archivo de validación del idioma correspondiente, en nuestro caso /resources/lang/es/validation.php de esta manera va afectar a todos los formularios y puedes centralizar los mensajes en un solo lugar. Opción recomendada si estás trabajando en una aplicación multi-idoma. En este archivo tenemos varias alternativas:

  • Puedes cambiar el mensaje de la regla de manera general (todos los formularios mostraran dicho mensaje):
    'required' => 'Este campo no puede quedar vacío.',
    

  • Puede cambiar el mensaje de una regla solo para un atributo en específico, en la opción custom:
    'custom' => [
        'student' => [
            'required' => 'Debes especificar el nombre del estudiante.',
        ],
    ],

    de esta manera sigue la convención atributo.regla (student.required) cómo se usó en el controlador.

  • Puedes también cambiar el placeholder de un atributo para hacer que sea más significativo con respecto al mensaje que se quiere dar. Esto a través de la opción attributes:
    'attributes' => [
        'student' => 'estudiante',
        'score' => 'puntuación'
    ]

    para luego poder trabajar con las reglas de esta manera:

    'custom' => [
        'student' => [
            'required' => 'No puedes dejar vacío el campo :attribute.',
        ],
        'score' =>[
            'required' =>'Todo estudiante debe tener una :attribute.'
        ]
    ],

Bien con esto ya tienes la idea para mostrar mensajes de error más amigables al usuario de tu aplicación. Espero que te haya gustado el tutorial y te parezca útil. Ayúdanos a compartirlo en las redes sociales y para cualquier duda abajo está la sección de comentarios.

Material relacionado

Únete a nuestra comunidad en Discord y comparte con los usuarios y autores de Styde, 100% gratis.

Únete hoy

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.