¡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"
Enviando y mostrando información en vistas
Sabemos cómo crear una vista, cómo mostrar información en esa vista, pero ahora queremos añadir en la vista información que recuperamos de la base de datos a través de un controlador.
Partimos de un método de nuestro ProductController:
// code public function show($product) { $product = Product::findOrFail($product); return view("products.show"); }
Para enviar información a la vista usamos with y definimos qué nos llevaremos a la vista.
// code public function show($product) { $product = Product::findOrFail($product); return view("products.show")->with([ "product" => $product, ]); }
A la vista estaremos enviando la variable product con el valor $product.
Si vamos a la vista (resources/views/products/show.blade.php:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Product</title> </head> <body> <h1>{{ $product->title }} ({{ $product->id }})</h1> <p>{{ $product->description }}</p> <p>{{ $product->price }}</p> <p>{{ $product->stock }}</p> <p>{{ $product->status }}</p> </body> </html>
Usando Blade, el motor de plantillas que incluye Laravel, interpretará las variables. Las encerramos entre llaves dobles ({{ }}).
Blade: motor de plantillas
Blade es el motor de plantillas que incluye Laravel
Variables
Para mostrar el contenido de una variable en Blade:
{{ $variable }}
Comentar para que no las procese ni las muestre:
{{-- $variable --}}
Si queremos que aparezca el texto tal cual (llaves incluidas), es decir, que Blade no evalúe nada:
@{{ $variable }}
Esto es útil si estamos trabajando con un framework para el frontend como Vuejs, React o Angular ya que también utilizan la sintaxis de las dobles llaves para las variables.
Estructuras de control
Por ejemplo, si tenemos en nuestro controlador:
public function index() { $products = Product::all(); return view("products.index")->with([ "products" => $products, ]); }
En la vista (resources/views/products.blade.php):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Product</title> </head> <body> <h1>List of Products</h1> @if (empty($products)) <div class="alert alert-warning"> This list of products is empty </div> @else <div class="table-responsive"> <table class="table table-striped"> <thead class="thead-light"> <tr> <th>ID</th> <th>Title</th> <th>Description</th> <th>Price</th> <th>Stock</th> <th>Status</th> </tr> </thead> <tbody> @foreach ($products as $product) <tr> <td>{{ $product->id }}</td> <td>{{ $product->title }}</td> <td>{{ $product->description }}</td> <td>{{ $product->price }}</td> <td>{{ $product->stock }}</td> <td>{{ $product->status }}</td> </tr> @endforeach </tbody> </table> </div> @endif </body> </html>
Para el caso de comprobar vacíos, existe otra estructura dedicada::
<h1>List of Products</h1> @empty ($products) <div class="alert alert-warning"> This list of products is empty </div> @else ... @endempty
Crear plantillas para las vistas
Para cuando tengamos componentes que se repitan.
Creamos, por ejemplo, reseources/views/layouts/master.blade.php:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Laravel Shop</title> </head> <body> @yield('content') </body> </html>
Con yield() marcamos una sección a la que podremos hacer luego referencia.
Las vistas que quieran utilizar esta plantilla tendrían que…
@extends("layouts.master")
@section("content")
<h1>List of Products</h1>
@if (empty($products))
<div class="alert alert-warning">
This list of products is empty
</div>
@else
<div class="table-responsive">
<table class="table table-striped">
<thead class="thead-light">
<tr>
<th>ID</th>
<th>Title</th>
<th>Description</th>
<th>Price</th>
<th>Stock</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach ($products as $product)
<tr>
<td>{{ $product->id }}</td>
<td>{{ $product->title }}</td>
<td>{{ $product->description }}</td>
<td>{{ $product->price }}</td>
<td>{{ $product->stock }}</td>
<td>{{ $product->status }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
@endsection
