Laravel 6

En esta lección 13 de nuestro curso Primeros Pasos con Laravel 6 veremos cómo crear registros desde un formulario utilizando Laravel 6 y el ORM Eloquent. Además nos enfrentaremos a 2 protecciones de Laravel (CSRF y asignación masiva), veremos de qué se tratan y cómo trabajar con ellas.

Esta lección incluye un video premium

Regístrate para ver este video y cientos de lecciones exclusivas.

Mira el código en GitHub: actual, resultado, comparación.

Para crear o editar registros a través de formularios utilizamos 2 rutas: una ruta de tipo «GET» para mostrar el formulario y una ruta de tipo «POST» a donde se enviarán y procesarán los datos de dicho formulario.

Comencemos definiendo la ruta de tipo «POST»:

<?php

Route::post('notas', function () {
    return 'Aquí procesaremos el formulario'; 
})->name('notes.store');

No podremos acceder a esta ruta a menos que enviemos una petición de tipo POST a través de un formulario o utilicemos JavaScript para enviar dicha petición de tipo POST.

Ahora vamos a resources/views/add-note.blade.php e indiquemos que el formulario debe ser de tipo POST y que la acción debe apuntar a la ruta notes.store:

<form method="POST" action="{{ url('notas') }}">
    <!-- Campos aqui -->

    <button type="submit" class="btn btn-primary">Crear nota</button>
</form>

Esto es casi lo que necesitamos para acceder a esta nueva ruta, puesto que si presionamos el botón «Crear nota» obtendremos el error «419 | Page expired».

Laravel y la protección para ataques de tipo CSRF

Laravel provee una protección para ataques de tipo CSRF, lo cual previene que un sitio malicioso de terceros se haga pasar por nuestra aplicación, enviando por ejemplo peticiones para crear notas o, en casos más graves, para retirar dinero de nuestra cuenta bancaria.

Para protegernos de esto, frameworks como Laravel o Symfony nos piden que agreguemos un token a los formularios o peticiones de tipo POST y luego el framework se encarga de comprobar el token enviado con el token almacenado, si ambos coinciden la petición tiene éxito, de lo contrario no. Esto funciona porque sitios de terceros no dispondrán de dicho token, solo nuestra app.

Agregar el token es extremadamente simple, solo agrega la directiva @csrf en algún lugar dentro de las etiquetas del formulario:

<form method="POST" action="{{ url('notas') }}">
    @csrf

    <button type="submit" class="btn btn-primary">Crear nota</button>
</form>

Esta directiva generará un campo oculto similar a esto:

<input type="hidden" name="_token" value="3st335unT0k3nD3ej3mpl0">

Ahora al presionar «Crear nota» podremos ver el mensaje «Aquí procesaremos el formulario».

Ahora reemplacemos este mensaje por la lógica para crear las notas. Sabemos que podemos crear una nota de esta forma:

<?php

Route::post('notas', function () {
    Note::create([
        'title' => 'Titulo de la nota creada desde la ruta',
        'content' => 'Contenido de la nota creada desde la ruta',
    ]);
})->name('notes.store');

Sin embargo esto producirá el siguiente error:

Error de MassAssignnment en Laravel

Solucionando MassAssignmentException en Laravel

MassAssignmentException es una excepción molesta que produce Laravel cuando intentamos asignar varios atributos a un modelo mediante un array, utilizando métodos como fill o create.

La solución que provee Ignition: la nueva página de error de Laravel es agregar la propiedad $fillable al modelo de notas, con los atributos que queremos permitir cargar mediante un arreglo:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Note extends Model
{
    protected $fillable = ['title', 'content'];
}

Hay otras opciones para desactivar o cambiar esta protección como discutimos en la lección avanzada Asignación masiva en Eloquent ORM a fondo (uso de fillable, guarded, fill, forceFill y atributos dinámicos).

Ahora intenta nuevamente y verifica que la nota fue creada.

Crear registros con datos provenientes de un formulario

Por supuesto nosotros queremos crear nuestra nota con los datos que el usuario envíe a través del formulario, no con datos arbitrarios. Esto lo podemos lograr de diversas maneras:

Utilizando el Facade Request

Importa la clase Illuminate\Support\Facades\Request al principio del archivo, ahora cambia el código de la ruta por lo siguiente:

<?php

Route::post('notas', function () {
    Note::create([
        'title' => Request::input('title'),
        'content' => Request::input('content'),
    ]);
})->name('notes.store');

El método input nos permite obtener el contenido proveniente del formulario, similar a como lo lograríamos con $_POST si trabajáramos con PHP sin framework.

Inyectando el objeto Request

También podemos importar la clase Illuminate\Http\Request en vez del Facade, luego obtener el objeto Request a través de la función anónima y usarlo de esta forma:

<?php

Route::post('notas', function (Request $request) {
    Note::create([
        'title' => $request->input('title'),
        'content' => $request->input('content'),
    ]);
})->name('notes.store');

Nota que en vez de llamar al método estático del Facade, ahora estamos llamando al método input desde la instancia de la clase Illuminate\Http\Request directamente.

No olvides importar la clase correcta de lo contrario obtendrás un error.

Ahora podemos crear notas correctamente; sin embargo para evitar la pantalla en blanco vamos a redirigir a otra URL luego de que creemos la nota.

Crear redirecciones en Laravel

Laravel -una vez más- nos brinda varias maneras de crear redirecciones:

<?php

return back(); // Nos retorna a la URL anterior

return redirect('/'); // Retorna a la URL indicada

return redirect()->route('notes'); // Retorna a la ruta indicada

Coloca uno de estos return luego de crear la nota y así evitarás la pantalla en blanco.

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

Lección anterior Introducción a Eloquent ORM en Laravel 6 Lección siguiente Validación de datos en Laravel 6