- Introducción
- Herencia de plantillas
- Componentes y slots
- Mostrando datos
- Estructuras de control
- Formularios
- Incluyendo sub-vistas
- Pilas
- Inyección de servicios
- Extendiendo Blade
Introducción
Blade es un motor de plantillas simple y a la vez poderoso proporcionado por Laravel. A diferencia de otros motores de plantillas populares de PHP, Blade no te impide utilizar código PHP plano en tus vistas. De hecho, todas las vistas de Blade son compiladas en código PHP plano y almacenadas en caché hasta que sean modificadas, lo que significa que Blade no añade sobrecarga a tu aplicación. Los archivos de las vistas de Blade tienen la extensión .blade.php
y son usualmente almacenados en el directorio resources/views
.
En Styde.net contamos con una completa lección sobre Blade totalmente gratuita.
Herencia de plantillas
Definir un layout
Dos de los principales beneficios de usar Blade son la herencia de plantillas y las secciones. Para empezar, veamos un ejemplo simple. Primero, vamos a examinar una página de layout «master». Ya que la mayoría de las aplicaciones web mantienen el mismo layout general a través de varias páginas, es conveniente definir este layout como una sola vista de Blade:
<!-- Stored in resources/views/layouts/app.blade.php --> <html> <head> <title>App Name - @yield('title')</title> </head> <body> @section('sidebar') This is the master sidebar. @show <div class="container"> @yield('content') </div> </body> </html>
Como puedes ver, este archivo contiene el marcado típico de HTML. Sin embargo, toma nota de las directivas @section
y @yield
. La directiva @section
, como su nombre lo indica, define una sección de contenido, mientras que la directiva @yield
es utilizada para mostrar el contenido en una sección determinada.
Ahora que hemos definido un layout para nuestra aplicación, vamos a definir una página hija que herede el layout.
Extender un layout
Al definir una vista hija, utiliza la directiva de Blade @extends
para indicar el layout que deberá «heredarse» en la vista hija. Las vistas que extiendan un layout de Blade pueden inyectar contenido en la secciones del layout usando directivas @section
. Recuerda, como vimos en el ejemplo anterior, los contenidos de estas secciones se mostrarán en el layout usando @yield
:
<!-- Stored in resources/views/child.blade.php --> @extends('layouts.app') @section('title', 'Page Title') @section('sidebar') @parent <p>This is appended to the master sidebar.</p> @endsection @section('content') <p>This is my body content.</p> @endsection
En este ejemplo, la sección sidebar
está utilizando la directiva @parent
para adjuntar (en lugar de sobrescribir) contenido al sidebar del layout. La directiva @parent
será reemplazada por el contenido del layout cuando la vista sea renderizada.
Contrario al ejemplo anterior, esta sección sidebar
termina con @endsection
en lugar de @show
. La directiva @endsection
sólo definirá una sección mientras que @show
definirá y automáticamente creará un yield de la sección.
La directiva @yield
también acepta un valor por defecto como segundo parámetro. Este valor será renderizado si la sección que está siendo generada es indefinida:
@yield('content', View::make('view.name'))
Las vistas de Blade se pueden retornar desde las rutas usando el helper global view
:
Route::get('blade', function () { return view('child'); });
En Styde.net contamos con una lección sobre layouts con Blade totalmente gratuita.
Componentes y slots
Los componentes y slots proporcionan beneficios similares a secciones y layouts; sin embargo, algunos encontrarán el modelo mental de componentes y slots más fácil de comprender. Primero, imaginemos un componente «alert» reutilizable que queremos que se reutilice en toda nuestra aplicación:
<!-- /resources/views/alert.blade.php --> <div class="alert alert-danger"> {{ $slot }} </div>
La variable {{ $slot }}
tendrá el contenido que deseamos inyectar en el componente. Ahora, para construir el componente, podemos usar la directiva de Blade @component
:
@component('alert') <strong>Whoops!</strong> Something went wrong! @endcomponent
Para instruir a Laravel para que cargue la primera vista que existe desde un arreglo de posibles vistas para el componente, puedes usar la directiva componentFirst
:
@componentfirst(['custom.alert', 'alert']) <strong>Whoops!</strong> Something went wrong! @endcomponentfirst
A veces es útil definir múltiples slots para un componente. Vamos a modificar nuestro componente de alerta para permitir la inyección de un «título». Los slots nombrados podrán desplegarse al hacer «echo» a la variable que coincida con sus nombres:
<!-- /resources/views/alert.blade.php --> <div class="alert alert-danger"> <div class="alert-title">{{ $title }}</div> {{ $slot }} </div>
Ahora, podemos inyectar contenido en el slot nombrado usando la directiva @slot
. Cualquier contenido que no esté en la directiva @slot
será pasado al componente en la variable $slot
:
@component('alert') @slot('title') Forbidden @endslot You are not allowed to access this resource! @endcomponent
Pasando información adicional a los componentes
En ocasiones puedes necesitar pasar información adicional al componente. Por esta razón, puedes pasar un arreglo de información como segundo argumento a la directiva @component
. Toda la información se hará disponible para la plantilla del componente como variables:
@component('alert', ['foo' => 'bar']) ... @endcomponent
Agregando alias a componentes
Si tus componentes de Blade están almacenados en un subdirectorio, puedes querer agregarles un alias para tener un acceso más fácil. Por ejemplo, imagina un componente de Blade que está almacenado en resources/views/components/alert.blade.php
. Puedes usar el método component
para agregar un alias al componente de components.alert
a alert
. Típicamente, esto debe ser realizado en el método boot
de tu AppServiceProvider
:
use Illuminate\Support\Facades\Blade; Blade::component('components.alert', 'alert');
Una vez que el alias ha sido agregado al componente, puedes renderizarlo usando una directiva:
@alert(['type' => 'danger']) You are not allowed to access this resource! @endalert
Puedes omitir los parámetros del componente si éste no tiene slots adicionales:
@alert You are not allowed to access this resource! @endalert
Mostrando datos
Puedes mostrar datos pasados a tu vista de Blade al envolver la variable entre llaves. Por ejemplo, dada la siguiente ruta:
Route::get('greeting', function () { return view('welcome', ['name' => 'Samantha']); });
Puedes mostrar el contenido de la variable name
de la siguiente manera:
Hello, {{ $name }}.
Las declaraciones de Blade {{ }}
son enviadas automáticamente mediante la función htmlspecialchars
de PHP para prevenir ataques XSS.
No estás limitado a mostrar sólo el contenido de las variables pasadas a la vista. También puedes hacer echo al resultado de cualquier función de PHP. De hecho, puedes poner cualquier código PHP que desees dentro de la declaración echo de Blade:
The current UNIX timestamp is {{ time() }}.
Mostrar datos no escapados
De manera predeterminada, las declaraciones {{ }}
de Blade son enviadas mediante la función htmlspecialchars
de PHP para prevenir ataques XSS. Si no deseas que tu información sea escapada, puedes utilizar la siguiente sintaxis:
Hello, {!! $name !!}.
Se muy cuidadoso cuando muestres contenido que sea suministrado por los usuarios de tu aplicación. Usa siempre las sentencias escapadas, ya que éstas previenen ataques XSS cuando se muestran datos suministrados por los usuarios.
Renderizar JSON
En ocasiones puedes pasar un arreglo a tu vista con la intención de renderizarla como JSON para inicializar una variable JavaScript. Por ejemplo:
<script> var app = <?php echo json_encode($array); ?>; </script>
Sin embargo, en lugar de llamar manualmente a json_encode
, puedes usar la directiva de Blade @json
. La directiva @json
acepta los mismos argumentos que la función json_encode
de PHP:
<script> var app = @json($array); var app = @json($array, JSON_PRETTY_PRINT); </script>
Sólo debes usar la directiva @json
para renderizar variables existentes como JSON. Las plantillas Blade están basadas en expresiones regulares e intentar pasar una expresión compleja a la directiva podría causar fallos inesperados.
La directiva @json
es también útil para trabajar con componentes de Vue o atributos data-*
:
<example-component :some-prop='@json($array)'></example-component>
El uso de @json
en atributos de elementos requiere que esté rodeado por comillas simples.
Codificación de entidades HTML
Por defecto, Blade (y el helper e
de Laravel) codificarán doblemente las entidades HTML. Si te gustaría deshabilitar la codificación doble, llama al método Blade::withoutDoubleEncoding
desde el método boot
de tu AppServiceProvider
:
<?php namespace App\Providers; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Blade::withoutDoubleEncoding(); } }
Frameworks de Blade Y JavaScript
Dado que muchos frameworks de JavaScript también usan llaves para indicar que una expresión dada debe mostrarse en el navegador, puedes utilizar el símbolo @
para informar al motor de renderizado de Blade que una expresión debe permanecer intacta. Por ejemplo:
<h1>Laravel</h1> Hello, @{{ name }}.
En este ejemplo, el símbolo @
será removido por Blade; sin embargo, la expresión {{ name }}
permanecerá intacta por el motor de Blade, lo que permitirá que pueda ser procesada por tu framework de JavaScript.
La directiva @verbatim
Si estás mostrando variables de JavaScript en una gran parte de tu plantilla, puedes ajustar el HTML en la directiva @verbatim
para que no tengas que poner un prefijo en cada instrucción echo de Blade con un símbolo @
:
@verbatim <div class="container"> Hello, {{ name }}. </div> @endverbatim
Estructuras de control
Además de la herencia de plantillas y la visualización de datos, Blade también proporciona accesos directos y convenientes para las estructuras de control comunes de PHP, tales como sentencias condicionales y bucles. Estos accesos directos proporcionan una manera muy limpia y concisa de trabajar con estructuras de control de PHP, al tiempo que permanecen familiares para sus contrapartes de PHP.
Sentencias if
Puede construir sentencias if
usando las directivas @if
, @elseif
, @else
y @endif
. Estas directivas funcionan idénticamente a sus contrapartes PHP:
@if (count($records) === 1) I have one record! @elseif (count($records) > 1) I have multiple records! @else I don't have any records! @endif
Por conveniencia, Blade también proporciona una directiva @unless
:
@unless (Auth::check()) You are not signed in. @endunless
Además de las directivas condicionales previamente mencionadas, las directivas @isset
y @empty
pueden ser usadas como accesos directos convenientes para sus respectivas funciones PHP:
@isset($records) // $records is defined and is not null... @endisset @empty($records) // $records is "empty"... @endempty
Directivas de autenticación
Las directivas @auth
y @guest
pueden ser utilizadas para determinar rápidamente si el usuario actual está autenticado o si es un invitado:
@auth // The user is authenticated... @endauth @guest // The user is not authenticated... @endguest
Si es necesario, puede especificar el guard de autenticación que debe verificarse al usar las directivas @auth
y @guest
:
@auth('admin') // The user is authenticated... @endauth @guest('admin') // The user is not authenticated... @endguest
Directivas de sección
Puede verificar si una sección tiene contenido usando la directiva @hasSection
:
@hasSection('navigation') <div class="pull-right"> @yield('navigation') </div> <div class="clearfix"></div> @endif
Sentencias switch
Las sentencias switch pueden ser construidas usando las directivas @switch
, @case
, @break
, @default
y @endswitch
:
@switch($i) @case(1) First case... @break @case(2) Second case... @break @default Default case... @endswitch
Bucles
Además de las sentencias condicionales, Blade proporciona directivas simples para trabajar con estructuras en bucle de PHP. De nuevo, cada una de estas directivas funciona idénticamente a sus contrapartes PHP:
@for ($i = 0; $i < 10; $i++) The current value is {{ $i }} @endfor @foreach ($users as $user) <p>This is user {{ $user->id }}</p> @endforeach @forelse ($users as $user) <li>{{ $user->name }}</li> @empty <p>No users</p> @endforelse @while (true) <p>I'm looping forever.</p> @endwhile
Cuando estés dentro del bucle, puedes usar la variable loop para obtener información valiosa acerca del bucle, como puede ser saber si estás en la primera o última iteración a través del bucle.
Al usar bucles puedes finalizarlo u omitir la iteración actual:
@foreach ($users as $user) @if ($user->type == 1) @continue @endif <li>{{ $user->name }}</li> @if ($user->number == 5) @break @endif @endforeach
También puedes incluir la condición con la declaración en una línea:
@foreach ($users as $user) @continue($user->type == 1) <li>{{ $user->name }}</li> @break($user->number == 5) @endforeach
La variable loop
Al ejecutar un ciclo, una variable $loop
estará disponible dentro del ciclo. Esta variable proporciona acceso a un poco de información útil, como el índice del ciclo actual y si es la primera o la última iteración del ciclo:
@foreach ($users as $user) @if ($loop->first) This is the first iteration. @endif @if ($loop->last) This is the last iteration. @endif <p>This is user {{ $user->id }}</p> @endforeach
Si estás en un bucle anidado, puedes acceder a la variable $loop
del bucle padre a través de la propiedad parent
:
@foreach ($users as $user) @foreach ($user->posts as $post) @if ($loop->parent->first) This is first iteration of the parent loop. @endif @endforeach @endforeach
La variable $loop
también contiene una variedad de otras propiedades útiles:
Propiedad | Descripción |
---|---|
$loop->index |
El índice de la iteración del ciclo actual (comienza en 0). |
$loop->iteration |
Iteración del ciclo actual (comienza en 1). |
$loop->remaining |
Iteraciones restantes en el ciclo. |
$loop->count |
La cantidad total de elementos en el arreglo que se itera. |
$loop->first |
Si esta es la primera iteración a través del ciclo. |
$loop->last |
Si esta es la última iteración a través del ciclo. |
$loop->even |
Si esta es una iteración par a través del ciclo. |
$loop->odd |
Si esta es una iteración impar a través del ciclo. |
$loop->depth |
El nivel de anidamiento del bucle actual. |
$loop->parent |
Cuando está en un bucle anidado, la variable de bucle del padre. |
Comentarios
Blade también te permite definir comentarios en tus vistas. Sin embargo, a diferencia de los comentarios HTML, los comentarios de Blade no son incluidos en el HTML retornado por la aplicación:
{{-- This comment will not be present in the rendered HTML --}}
PHP
En algunas situaciones, es útil insertar código PHP en tus vistas. Puedes usar la directiva de Blade @php
para ejecutar un bloque de PHP plano en tu plantilla:
@php // @endphp
A pesar que Blade proporciona esta función, usarla con frecuencia puede ser una señal de que tienes demasiada lógica incrustada dentro de tu plantilla.
Formularios
Campo CSRF
Cada vez que defines un formulario HTML en tu aplicación, debes incluir un campo de token CSRF oculto en el formulario para que el middleware de protección CSRF pueda validar la solicitud. Puedes usar la directiva @csrf
de Blade para generar el campo de token:
<form method="POST" action="/profile"> @csrf ... </form>
Campo method
Dado que los formularios HTML no pueden hacer solicitudes PUT
, PATCH
o DELETE
necesitarás agregar un campo _method
oculto para suplantar estos verbos HTTP. La directiva @method
de Blade puede crear este campo por ti:
<form action="/foo/bar" method="POST"> @method('PUT') ... </form>
Errores de validación
La directiva @error
puede ser usada para comprobar rápidamente si existen mensajes de error de validación para un atributo dado. Para una directiva @error
, puedes imprimir la variable $message
para mostrar el mensaje de error:
<!-- /resources/views/post/create.blade.php --> <label for="title">Post Title</label> <input id="title" type="text" class="@error('title') is-invalid @enderror"> @error('title') <div class="alert alert-danger">{{ $message }}</div> @enderror
Puedes pasar el nombre de un paquete de error específico como segundo parámetro de la directiva @error
para retornar los mensajes de error en páginas que contienen múltiples formularios:
<!-- /resources/views/auth.blade.php --> <label for="email">Email address</label> <input id="email" type="email" class="@error('email', 'login') is-invalid @enderror"> @error('email', 'login') <div class="alert alert-danger">{{ $message }}</div> @enderror
Incluyendo sub-vistas
La directiva @include
de Blade te permite incluir una vista de Blade desde otra vista. Todas las variables que estén disponibles en la vista padre estarán disponibles para la vista incluida:
<div> @include('shared.errors') <form> <!-- Form Contents --> </form> </div>
Aunque la vista incluida heredará todos los datos disponibles en la vista principal, también puedes pasar un arreglo de datos adicionales a la vista incluida:
@include('view.name', ['some' => 'data'])
Si utilizas @include
en una vista que no existe, Laravel lanzará un error. Si deseas incluir una vista que puede o no estar presente, deberás utilizar la directiva @includeIf
:
@includeIf('view.name', ['some' => 'data'])
Si te gustaría incluir (@include
) una vista si una condición booleana dada se evalúa como true
, puedes utilizar la directiva @includeWhen
:
@includeWhen($boolean, 'view.name', ['some' => 'data'])
Si te gustaría incluir (@include
) una vista si una condición booleana dada se evalúa como false
, puedes usar la directiva @includeUnless
:
@includeUnless($boolean, 'view.name', ['some' => 'data'])
Para incluir la primera vista que exista para un arreglo dado de vistas, puedes usar la directiva @includeFirst
:
@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])
Debes evitar usar las constantes __DIR__
y __FILE__
en tus vistas de Blade, ya que se referirán a la ubicación de la vista compilada en caché.
Alias de includes
Si tus includes de Blade (sub-vistas incluidas) están almacenados en un subdirectorio, puedes desear crear un alias de ellos para un acceso más fácil. Por ejemplo, imagina un include de Blade que está almacenado en resources/views/includes/input.blade.php
con el siguiente contenido:
<input type="{{ $type ?? 'text' }}">
Puedes usar el método include
para crear un alias al include de includes.input
a input
. Normalmente, esto debería hacerse en el método boot
de tu AppServiceProvider
:
use Illuminate\Support\Facades\Blade; Blade::include('includes.input', 'input');
Una vez que el include tiene un alias asignado, puedes renderizalo usando el nombre del alias como una directiva de Blade:
@input(['type' => 'email'])
Renderizar vistas para colecciones
Puedes combinar bucles e includes en una sola línea con la directiva @each
de Blade:
@each('view.name', $jobs, 'job')
El primer argumento es la vista parcial a renderizar por cada elemento en el arreglo o colección. El segundo argumento es el arreglo o colección que deseas iterar, mientras que el tercer argumento es el nombre de la variable que será asignada a la iteración actual dentro de la vista. Así que, por ejemplo, si está iterando en un arreglo jobs
, típicamente querrás tener acceso a cada trabajo como una variable job
en tu vista parcial. La llave de la iteración actual estará disponible como la variable key
en tu vista parcial.
También puedes pasar un cuarto argumento a la directiva @each
. Este argumento determina la vista que se va a renderizar si el arreglo dado está vacío.
@each('view.name', $jobs, 'job', 'view.empty')
Las vistas renderizadas via @each
no heredan las variables de la vista padre. Si la vista hija requiere de estas variables, deberás usar @foreach
y @include
en su lugar.
Pilas
Blade te permite agregar a pilas nombradas que pueden ser renderizados en otra parte de otra vista o layout. Esto es particularmente útil para especificar cualquier librería JavaScript requerida por las vistas hijas:
@push('scripts') <script src="/example.js"></script> @endpush
Puedes agregar a una pila tantas veces como lo necesites. Para renderizar el contenido completo de la pila, pasa el nombre de la pila a la directiva @stack
:
<head> <!-- Head Contents --> @stack('scripts') </head>
Si te gustaría agregar contenido al inicio de una pila, debes usar la directiva @prepend
:
@push('scripts') This will be second... @endpush // Later... @prepend('scripts') This will be first... @endprepend
Inyección de servicios
La directiva @inject
puede ser utilizada para recuperar un servicio del contenedor de servicios de Laravel. El primer argumento pasado a @inject
es el nombre de la variable en la que se colocará el servicio, mientras que el segundo argumento es el nombre de la clase o interfaz del servicio que deseas resolver:
@inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}. </div>
Extendiendo Blade
Blade te permite definir tus propias directivas personalizadas utilizando el método directive
. Cuando el compilador Blade encuentra la directiva personalizada, llamará al callback con la expresión que contiene la directiva.
El siguiente ejemplo crea una directiva @datetime($var)
que le da formato a la variable $var
, la cual es una instancia de DateTime
:
<?php namespace App\Providers; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { Blade::directive('datetime', function ($expression) { return "<?php echo ($expression)->format('m/d/Y H:i'); ?>"; }); } }
Como podrás ver, vamos a encadenar el método format
en cualquier expresión que se pase a la directiva. Entonces, en este ejemplo, el PHP final generado por esta directiva será:
<?php echo ($var)->format('m/d/Y H:i'); ?>
Después de actualizar la lógica de la directiva de Blade, vas a necesitar eliminar todas las vistas de Blade guardadas en caché. Las vistas de Blade en caché pueden ser eliminadas con el comando de Artisan view:clear
.
Sentencias if personalizadas
Programar una directiva personalizada algunas veces es más complejo de lo necesario al momento de definir sentencias condicionales simples personalizadas. Por esa razón, Blade proporciona un método Blade::if
que le permitirá rápidamente definir directivas condicionales utilizando Closures. Por ejemplo, vamos a definir un condicional personalizado que verifica el entorno actual de la aplicación. Podemos hacer esto en el método boot
de nuestro AppServiceProvider
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap any application services. * * @return void */ public function boot() { Blade::if('env', function ($environment) { return app()->environment($environment); }); }
Una vez que el condicional personalizado haya sido definido, podremos usarlo fácilmente en nuestros templates:
@env('local') // The application is in the local environment... @elseenv('testing') // The application is in the testing environment... @else // The application is not in the local or testing environment... @endenv @unlessenv('production') // The application is not in the production environment... @endenv
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.
Lección anterior Registro (Logging) - Documentación de Laravel 6 Lección siguiente Configuración Regional - Documentación de Laravel 6