Herramientas de usuario

Herramientas del sitio


informatica:programacion:php:frameworks:laravel:uso_de_vistas

¡Esta es una revisión vieja del documento!


Trabajando con vistas en Laravel

Laravel

Las vistas se sitúan en la carpeta resources/views. Los ficheros que hacen de vistas terminan en .blade.php. Esto es porque utilizan el motor plantillas Blade que viene incluido con Laravel.

Creación de vistas

Podemos crearla manualmente guardando el fichero terminado en .blade.php en la carpeta resources/views o utilizando artisan:

php artisan make:view home

Una vista puede ser un fichero tan simple como:

<!-- Vista almacenada en resources/views/home.blade.php -->
 
<html>
    <body>
        <h1>Hola, {{ $nombre }}</h1>
    </body>
</html>

Usando vistas en los controladores

namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class HomeController extends Controller {
    public function __invoke() {
        return view('home'); // 'view' es un "helper" de Laravel para llamar a una vista
    }
}

El fichero routes/web.php lo tenemos así:

<?php
 
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\PostController;
 
Route::get('/', [HomeController::class, 'index']);

Una práctica recomendable, por convención, es nombrar a las vistas como el método del controlador que la llama. Por ejemplo, supongamos que tenemos el siguiente controlador:

namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class PostController extends Controller
{
    public function index() {
        return "Aquí irán los posts";
    }
 
    public function create() {
        return "Aquí se mostrará un formulario para crear un post";
    }
 
    public function show($post) {
        return "Aquí se mostrará el post {$post}";
    }
}

Entonces crearíamos las vistas index.blade.php, create.blade.php, show.blade.php y show.blade.php. Por organización, queremos que las cree en una carpeta llamada posts ya que todas tienen que ver con lo mismo:

php artisan make:view posts.index
php artisan make:view posts.create
php artisan make:view posts.show

Ahora haría modificaciones en el controlador para llamar a las vistas creadas:

namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class PostController extends Controller
{
    public function index() {
        return view("posts.index");
    }
 
    public function create() {
        return view("posts.create");
    }
 
    public function show($post) {
    // Para pasarle variables a un vista, la añadimos a un array
    // como segundo argumento del "helper" 'view'
        return view("posts.show", [
            'post' => $post
        ]);
    }
}

La vista show.blade.php es un poco especial porque muestra información variable:

<p>Aquí se mostrará el post {{ $post }}</p>

Si no usásemos las etiquetas de Blade, mostraríamos el contenido de esa variable como hacemos en PHP:

<p>Aquí se mostrará el post <?php echo $post; ?></p>

Para pasarle argumentos a una vista desde un controlador, también podemos usar la función compact():

// ... código
    public function show($post) {
        return view("posts.show", compact('post'));

La función compact() genera un array con la clave llamada como el argumento y el dato también, pero con el símbolo de dólar, que indica que se trata de una variable. Es decir, compact('post') creará el siguiente array:

['post' => $post];

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

Componentes

Cuando queramos definir código que se repite en varios puntos de nuestro proyecto, Blade nos permite la creación de componentes.

Para organizarlo, creamos una carpeta resources/views/components y creamos un fichero con un nombre significativo. Por ejemplo, si queremos crear un componente para las alertas, creamos un fichero alert.blade.php:

<div class="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400" role="alert">
    <span class="font-medium">Info alert!</span> Change a few things up and try submitting again.
</div>
</html>

A partir de este momento, cada vez que queramos llamar a ese componente, utilizaríamos la etiqueta <x-nombre-del-archivo>:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="https://unpkg.com/@tailwindcss/browser@4"></script>  
    </head>
    <body>
        <!-- Breathing in, I calm body and mind. Breathing out, I smile. - Thich Nhat Hanh -->
         <div class="max-w-4xl mx-auto px-4">
            <x-alert></x-alert>
        </div>
    </body>
</html>

Para tener un contenido variable en un componente, tenemos que crear una variable en el lugar que va a cambiar:

<div class="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400" role="alert">
    <span class="font-medium">Info alert!</span> {{ $slot }}
</div>
</html>

Y le pasaríamos el contenido en la etiqueta de la vista donde la usamos:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="https://unpkg.com/@tailwindcss/browser@4"></script>  
    </head>
    <body>
        <!-- Breathing in, I calm body and mind. Breathing out, I smile. - Thich Nhat Hanh -->
         <div class="max-w-4xl mx-auto px-4">
            <x-alert>
                Contenido de la alerta
            </x-alert>
        </div>
    </body>
</html>

Cuando queremos usar más de una variable, tenemos que utilizar la etiqueta <x-slot>:

<div class="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400" role="alert">
    <span class="font-medium">{{ $title }}</span> {{ $slot }}
</div>
</html>

Y en la vista:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="https://unpkg.com/@tailwindcss/browser@4"></script>  
    </head>
    <body>
        <!-- Breathing in, I calm body and mind. Breathing out, I smile. - Thich Nhat Hanh -->
         <div class="max-w-4xl mx-auto px-4">
            <x-alert>
                <x-slot name="title">
                Título de la alerta
                </x-slot>
                Contenido de la alerta
            </x-alert>
        </div>
    </body>
</html>

También podríamos añadir atributos:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="https://unpkg.com/@tailwindcss/browser@4"></script>  
    </head>
    <body>
        <!-- Breathing in, I calm body and mind. Breathing out, I smile. - Thich Nhat Hanh -->
         <div class="max-w-4xl mx-auto px-4">
            <x-alert type="info">
                <x-slot name="title">
                Título de la alerta
                </x-slot>
                Contenido de la alerta
            </x-alert>
        </div>
    </body>
</html>

En el componente (alert.blade.php):

@props (['type'])
 
@php
    switch ($type) {
        case 'info':
            $class = "text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400";
            break;
        case 'danger':
            $class = "text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400";        
            break;
        case 'success':
            $class = "text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400";                
            break;                        
        case 'warning':
            $class = "text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-400";                        
            break;            
        case 'dark':
            $class = "text-gray-800 rounded-lg bg-gray-50 dark:bg-gray-800 dark:text-gray-400";                                
            break;
        default:
            break;
    }
@endphp
<div class="p-4 mb-4 text-sm {{ $class }}" role="alert">
    <span class="font-medium">{{ $title }}</span> {{ $slot }}
</div>
</html>

Componentes de clase

Con los componentes de clase podremos separar la lógica de la vista. En el apartado anterior, en resources/views/components/alert.blade.php hemos colocado lógica para establecer un estilo CSS según ciertas variables.

php artisan make:component Alert2

Se creará `app/View/Component/Alert2.php`. Esta clase está renderizando una vista que está en resources/views/components/alert2.blade.php.

Ahora moveremos la lógica de resources/views/components/alert.blade.php a app/View/Component/Alert2.php:

 

Y en la vista (resources/views/components/alert2.blade.php) tendremos:

<div {{ $attributes->merge(['class' => 'p-4 text-sm ]
    <span class="font-medium">{{ $title ?? 'Info Alert'

En la vista home.blade.php, podríamos llamar al componente Alert2 de la siguiente manera:

// ...
<x-alert2 type="danger" class="mb-4">
    <x-slot name="title">
        Título de la alerta
    </x-slot>
 
    Contenido de la alerta
</x-alert2>   

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

Crear componentes para las vistas

Con el propósito de centralizar información, podemos crear trozos de código / texto que luego recuperaremos desde las vistas de Blade.

Creamos un fichero en resources/views/components/product-card.blade.php. Este fichero contendrá:

<h1>{{ $product->title }} ({{ $product->id }})</h1>
<p>{{ $product->description }}</p>
<p>{{ $product->price}}</p>
<p>{{ $product->stock}}</p>
<p>{{ $product->status}}</p>

Para utilizar este componente en una plantilla de blade:

<div class="row">
    @foreach ($products as $product)
        <div class="col-3">
            @include("components.product-card")
        </div>
    @endforeach
</div>

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 ({{ }}).

informatica/programacion/php/frameworks/laravel/uso_de_vistas.1741007331.txt.gz · Última modificación: por tempwin