Parte 4: Cómo crear formularios para validar nuestros datos con Laravel 8
¡Hola! Estamos casi finalizando el año pero yo no paro asi que vamos a empezar fuerte con la cuarta parte de esta serie de tutoriales sobre Laravel 8 😁. En el tutorial de hoy vamos a aprender cosas nuevas como permitir a los usuarios logueados, escribir comentarios en nuestros posts. Para ello utilizaremos formularios y validaremos la información enviada gracias a los custom requests 💪.
Antes de empezar con los comentarios y, ya que vamos a necesitar hacer login para hacer las pruebas, vamos a realizar una pequeña corrección. Si ahora mismo hacemos login, nos enviará a la página http://127.0.0.1:8000/home y ya que no tenemos esa página, tendremos un error. Para solucionarlo, debemos ir al archivo app/Providers/RouteServiceProvider.php y modificar la constante HOME de tal forma que ahora quedará así:
public const HOME = '/';
De esta forma, cada vez que un usuario realice el login, le reenviará a nuestra página de inicio.
Solucionado esto, empezamos con los comentarios 🚀.
Cómo crear comentarios
Para crear comentarios, lo primero que necesitaremos será crear un custom request. Los custom request son clases que extienden de la clase FormRequest y los utilizamos para validar la información enviada por un usuario. Para utilizarlos, los sustituiremos por el objeto general que pasamos por parámetro en los métodos de los controladores. La forma de crearlo, es lanzando el siguiente comando:
php artisan make:request CommentRequest
Ahora deberíamos tener un archivo llamado CommentRequest.php dentro de la carpeta app/Http/Requests/. Lo abrimos y sustituimos su código por el que muestro a continuación:
<?php
namespace App\Http\Requests;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class CommentRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'comment' => 'required|max:1000',
'post_id' => 'exists:App\Models\Post,id',
];
}
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
{
return [
'comment.required' => 'A comment is required',
'comment.max' => 'A comment cannot exceed 1000 characters',
'post_id.exists' => 'You must sent a valid post'
];
}
protected function failedAuthorization()
{
throw new AuthorizationException('You must be logged in to write comments');
}
}
El método authorize() retornará true si el usuario puede realizar la acción o false si no. Para ello, utiliza el método Auth::check() que comprueba si un usuario está logueado o no. Si devuelve false, no validará la petición y podremos enviar un error al usuario avisando que es necesario estar logueado para realizarla.
El segundo método que tenemos es el método rules(). En este método añadiremos los campos que podemos recibir y que tendrán unas reglas especiales. En este caso es obligatorio recibir un parámetro llamado comment y que además tendrá un tamaño máximo de 1000 caracteres. También vamos a recibir un id de post así que validaremos que exista en la base de datos. Para ver todas las reglas que podéis utilizar, os dejo el enlace a la doc.
Gracias al método messages(), podremos customizar los mensajes que mostraremos al usuario. Como veis, debemos añadir el nombre del parámetro junto con la regla y como valor podremos añadir nuestro mensaje customizado.
Por último, reescribimos el método failedAuthorization() para añadir nuestro mensaje personalizado.
Lo siguiente que debemos hacer es crear un controlador para administrar los comentarios. Para ello, al igual que cuando lo hicimos para los posts, lanzamos el siguiente comando:
php artisan make:controller CommentController
Ahora vamos al archivo app/Http/Controllers/CommentController.php y reemplazamos el código existente por el siguiente:
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CommentRequest;
use App\Models\Comment;
use App\Models\Post;
use Illuminate\Support\Facades\Auth;
class CommentController extends Controller
{
/**
* Store a newly created resource in storage.
*
* @param App\Http\Requests\CommentRequest $request
* @return \Illuminate\Http\Response
*/
public function store(CommentRequest $request)
{
$request->validated();
$user = Auth::user();
$post = Post::find($request->input('post_id'));
$comment = new Comment;
$comment->comment = $request->input('comment');
$comment->user()->associate($user);
$comment->post()->associate($post);
$res = $comment->save();
if ($res) {
return back()->with('status', 'Comment has been created sucessfully');
}
return back()->withErrors(['msg', 'There was an error saving the comment, please try again later']);
}
}
El método store() se encargará de guardar los datos. Recibirá por parámetro nuestro custom request y lo primero que haremos es ejecutar el método $request->validated() que lanzará los controles de validación que creamos en CommentRequest.php. Si no cumple los parámetros de validación, enviará los mensajes de error que creamos.
Si todo está bien, realizaremos una búsqueda del post y crearemos el comentario. Una vez hecho esto, utilizaremos la función back() para volver a la página del post donde hemos escrito nuestro comentario. También utilizamos with() para crear una variable de sesión llamada status y con el mensaje para avisar al usuario de que su comentario se ha creado correctamente. Si hubiese algún fallo, utilizaremos back() pero en vez de with(), usaremos withErrors() y añadiremos un mensaje con el error.
Ahora iremos a la template resources/views/posts/post.blade.php que es la que se encarga de mostrar el detalle de un post. Ahí añadiremos un bloque de código para mostrar a un usuario logueado el formulario para crear comentarios. Para ello, vamos a la línea 20 y después de esta, añadimos el siguiente código:
@guest
<p>You must be logged in to write comments</p>
@else
<form action="{{ route('comments.store') }}" method="post">
@csrf
<textarea class="w-full h-28 resize-none border rounded focus:outline-none focus:shadow-outline p-2" name="comment" placeholder="Write your comment here" required>{{ old('comment') }}</textarea>
<input type="hidden" name="post_id" value="{{$post->id}}">
<input type="submit" value="SEND" class="px-4 py-2 bg-orange-300 cursor-pointer hover:bg-orange-500 font-bold w-full border rounded border-orange-300 hover:border-orange-500 text-white">
@if (session('status'))
<div class="w-full bg-green-500 p-2 text-center my-2 text-white">
{{ session('status') }}
</div>
@endif
@if($errors->any())
<div class="w-full bg-red-500 p-2 text-center my-2 text-white">
{{$errors->first()}}
</div>
@endif
</form>
@endguest
Comprobamos si el usuario está logueado. Si no es así, mostramos el mensaje avisando de que para escribir comentarios debe realizar login primero.
Si está logueado, mostramos un formulario que contiene @csrf para generar el token que valide el formulario.
También tenemos un textarea para que el usuario escriba su comentario.
Nota: Dentro del textarea se encuentra el siguiente código: {{ old('comment') }}. Si el usuario escribe un comentario y por ejemplo no cumple el tamaño máximo, al reenviar al usuario a la página de detalle, seguirá conservando el comentario que ha escrito. De esta forma si tiene que modificarlo no lo tendrá que escribir completamente de nuevo.
También enviamos con un input hidden el id del post, ya que lo necesitaremos para saber a qué post debemos asignar el comentario.
Para finalizar, tenemos un botón de tipo submit que se encargará de enviar el formulario.
Aparte del formulario, en la línea 29 tenemos @if (session('status')). Esto significa, que si tenemos una variable de sesión llamada status, mostrará el div que contiene esta condición y mostraremos el valor de status. Este valor lo asignamos en el controlador de comentarios. Si todo ha ido bien a la hora de generar un comentario, se asignará un valor a status y le mostrará el mensaje de éxito al usuario.
Si por el contrario, tenemos algún error al crear un comentario, en la línea 34 controlaremos si existen errores con @if($errors->any()). Si es así, mostraremos el mensaje del error al usuario.
Por último, añadiremos la ruta para generar los comentarios. Para ello, vamos al archivo routes/web.php y añadimos la siguiente línea:
Route::post('/comment', [\App\Http\Controllers\CommentController::class, 'store'])->name('comments.store');
De esta forma cuando la url /comment reciba una petición de tipo post, la enviará a CommentController y al método store que se encargará de realizar el proceso de guardado.
Conclusiones
Y con esto ya sería todo por este tutorial. Como habréis podido observar, gracias a los custom requests, podemos validar fácilmente nuestros formularios, lo que nos ayudará enormemente a la hora de trabajar con estos y ahorrarnos algún dolor de cabeza 🤯.
Os espero en el próximo tutorial, donde seguiremos trabajando en este blog y en él veremos como crear un panel para que un usuario con permisos de admin o staff pueda administar los posts (Disponible el 14 de enero de 2021).
Como siempre os dejo el enlace al proyecto.
Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.
Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.
Nos leemos 👋.