¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Trabajando con formularios en Laravel
Crear formulario
Si queremos crear un formulario que nos permita añadir un producto, vamos al controlador y nos centramos en el método create:
public function create() { return view("products.create"); }
Crearemos una vista resources/views/products/create.blade.php:
@extends("layout.master")
@section("content")
<h1>Create a product</h1>
<form method="post" action="{{ route("products.store" }}">
<div class="form-row">
<label>Title</label>
<input class="form-control" type="text" name="title" required>
</div>
<div class="form-row">
<label>Description</label>
<input class="form-control" type="text" name="description" required>
</div>
<div class="form-row">
<label>Price</label>
<input class="form-control" type="number" min="1.00" step="0.01" name="price" required>
</div>
<div class="form-row">
<label>Stock</label>
<input class="form-control" type="number" min="0" name="stock" required>
</div>
<div class="form-row">
<label>Status</label>
<select class="custom-select" name="status" required>
<option value="" selected>Select...</option>
<option value="available">Available</option>
<option value="unavailable">Unavailable</option>
</select>
</div>
<div class="form-row">
<button type="submit" class="btn btn-primary btn-lg">Create product</button>
</div>
</form>
Recordemos que tenemos estas rutas en routes/web.php para este caso:
Route::get("products/create", "ProductController@create")->name("products.create"); Route::post("products", "ProductController@store")->name("products.store");
Por tanto, cuando se envíe el formulario, se llamará al método store del ProductController mediante POST:
public function store() { dd("Estamos en store"); }
Esto no nos funcionará porque, por defecto, Laravel tiene protección contra CSRF (Cross-site request forgery). Se asegura que las peticiones que se hagan a nuestra web, vengan realmente de nuestra web.
Para solucionarlo, en nuestros formularios debemos añadir un token CSRF:
@extends("layout.master")
@section("content")
<h1>Create a product</h1>
<form method="post" action="{{ route("products.store" }}">
@csrf
Esa instrucción de Blade incluye un campo HTML oculto en el formulario:
<form method="post" action=""> <input type="hidden" name="_token" value="123h4jkl123khxvbnasd12"
Datos provenientes de formularios
Vamos a crear (almacenar) un producto a partir de la información recibida desde un formulario:
public function store() { $product = Product::create([ 'title' => request()->title, 'description' => request()->description, 'price' => request()->price, 'stock' => request()->stock, 'status' => request()->status, ]); return $product; }
Veremos un string JSON con el producto creado a través del formulario.
Versión abreviada cogiendo todo lo que llegue de un formulario:
public function store() { $product = Product::create(request()->all()); return $product; }
Los atributos que se asignarán a nuestro modelo a partir del formulario serán los que hayamos indicado en el array de $fillable.
Editando desde un formulario
Los métodos que modificaremos en nuestro ProductController serán edit y update. Uno mostrará el formulario de edición del producto y el otro hará efectiva la actualización.
public function edit($product) { return view("products.edit")->with([ "product" => Product::findOrFail($product), ]); } public function update($product) { }
Recordemos las rutas:
Route::get("products/{$product}/edit", "ProductController@edit")->name("products.edit"); Route::match(["put", "patch"], "products/{$product}", "ProductController@update")->name("products.update");
Para el formulario de edición, creamos la vista resources/views/products/edit.blade.php:
@extends("layout.master")
@section("content")
<h1>Edit a product</h1>
<form method="post" action="{{ route("products.update", ["product" => $product->id]) }}">
@csrf
@method("PUT")
<div class="form-row">
<label>Title</label>
<input class="form-control" type="text" name="title" value="{{ $product->title }}" required>
</div>
<div class="form-row">
<label>Description</label>
<input class="form-control" type="text" name="description" value="{{ $product->description }} required>
</div>
<div class="form-row">
<label>Price</label>
<input class="form-control" type="number" min="1.00" step="0.01" name="price" value="{{ $product->price }} required>
</div>
<div class="form-row">
<label>Stock</label>
<input class="form-control" type="number" min="0" name="stock" value="{{ $product->stock }} required>
</div>
<div class="form-row">
<label>Status</label>
<select class="custom-select" name="status" required>
<option {{ $product->status == "available" ? "selected" : "" }} value="available">Available</option>
<option {{ $product->status == "unavailable" ? "selected" : "" }} value="unavailable">Unavailable</option>
</select>
</div>
<div class="form-row">
<button type="submit" class="btn btn-primary btn-lg">Edit product</button>
</div>
</form>
Los navegadores solo procesan GET y POST, así que para forzar un tipo de petición, usamos @method que añadirá una etiqueta input oculta con el valor que le pasemos.
Para realizar la actualización del producto, en el controlador:
public function update($product) { $product = Product::findOrFail($product); $product->update(request()->all()); return $product; }
