Plantillas Blade
- Introducción
- Mostrando Datos
- Directivas de Blade
- Componentes
- Componentes Anónimos
- Construyendo Diseños
- Formularios
- Pilas
- Inyección de Servicios
- Renderizando Plantillas Blade en Línea
- Renderizando Fragmentos Blade
- Extendiendo Blade
Introducción
Blade es el motor de plantillas simple pero poderoso que se incluye con Laravel. A diferencia de algunos motores de plantillas PHP, Blade no te restringe de usar código PHP en tus plantillas. De hecho, todas las plantillas de Blade se compilan en código PHP puro y se almacenan en caché hasta que sean modificadas, lo que significa que Blade añade esencialmente cero sobrecarga a tu aplicación. Los archivos de plantilla Blade utilizan la extensión de archivo .blade.php
y se almacenan típicamente en el directorio resources/views
.
Las vistas de Blade pueden ser devueltas desde rutas o controladores utilizando el helper global view
. Por supuesto, como se menciona en la documentación sobre vistas, se pueden pasar datos a la vista de Blade utilizando el segundo argumento del helper view
:
Route::get('/', function () { return view('greeting', ['name' => 'Finn']);});
Potenciando Blade con Livewire
¿Quieres llevar tus plantillas Blade al siguiente nivel y construir interfaces dinámicas con facilidad? Echa un vistazo a Laravel Livewire. Livewire te permite escribir componentes Blade que están potenciados con funcionalidades dinámicas que típicamente solo serían posibles a través de frameworks frontend como React o Vue, proporcionando un gran enfoque para construir frontends modernos y reactivos sin las complejidades, el renderizado del lado del cliente o los pasos de construcción de muchos frameworks de JavaScript.
Mostrando Datos
Puedes mostrar los datos que se pasan a tus vistas Blade envolviendo la variable en llaves. Por ejemplo, dada la siguiente ruta:
Route::get('/', function () { return view('welcome', ['name' => 'Samantha']);});
Puedes mostrar el contenido de la variable name
de la siguiente manera:
Hello, {{ $name }}.
[!NOTA] Las declaraciones de eco
{{ }}
de Blade se envían automáticamente a través de la funciónhtmlspecialchars
de PHP para prevenir ataques XSS. No estás limitado a mostrar solo el contenido de las variables pasadas a la vista. También puedes mostrar los resultados de cualquier función PHP. De hecho, puedes colocar cualquier código PHP que desees dentro de una declaración de eco de Blade:
The current UNIX timestamp is {{ time() }}.
Codificación de Entidades HTML
Por defecto, Blade (y la función e
de Laravel) codificarán las entidades HTML de forma doble. Si deseas desactivar 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. */ public function boot(): void { Blade::withoutDoubleEncoding(); }}
Mostrando Datos No Escapados
Por defecto, las instrucciones Blade {{ }}
se envían automáticamente a través de la función htmlspecialchars
de PHP para prevenir ataques XSS. Si no deseas que tus datos sean escapados, puedes usar la siguiente sintaxis:
Hello, {!! $name !!}.
[!WARNING] Ten mucho cuidado al mostrar contenido que es proporcionado por los usuarios de tu aplicación. Debes utilizar típicamente la sintaxis de llaves dobles escapadas para prevenir ataques XSS al mostrar datos proporcionados por el usuario.
Blade y Frameworks de JavaScript
Dado que muchos frameworks de JavaScript también usan llaves "curly" para indicar que una expresión dada debe mostrarse en el navegador, puedes usar el símbolo @
para informar al motor de renderizado Blade que una expresión debe permanecer sin cambios. Por ejemplo:
<h1>Laravel</h1> Hello, @{{ name }}.
En este ejemplo, el símbolo @
será eliminado por Blade; sin embargo, la expresión {{ name }}
permanecerá intacta por el motor Blade, lo que permitirá que sea renderizada por tu framework de JavaScript.
El símbolo @
también se puede usar para escapar directivas de Blade:
{{-- Blade template --}}@@if() <!-- HTML output -->@if()
Renderizando JSON
A veces puedes pasar un array a tu vista con la intención de renderizarlo como JSON para inicializar una variable de JavaScript. Por ejemplo:
<script> var app = <?php echo json_encode($array); ?>;</script>
Sin embargo, en lugar de llamar manualmente a json_encode
, puedes usar el método directo Illuminate\Support\Js::from
. El método from
acepta los mismos argumentos que la función json_encode
de PHP; sin embargo, se asegurará de que el JSON resultante esté escapado correctamente para su inclusión dentro de comillas HTML. El método from
devolverá una cadena con la declaración JSON.parse
de JavaScript que convertirá el objeto o array dado en un objeto JavaScript válido:
<script> var app = {{ Illuminate\Support\Js::from($array) }};</script>
Las últimas versiones del esqueleto de la aplicación Laravel incluyen un facade Js
, que proporciona un acceso conveniente a esta funcionalidad dentro de tus plantillas Blade:
<script> var app = {{ Js::from($array) }};</script>
[!WARNING] Debes usar el método
Js::from
solo para representar variables existentes como JSON. La plantilla Blade se basa en expresiones regulares y intentar pasar una expresión compleja a la directiva puede causar fallos inesperados.
La Directiva @verbatim
Si estás mostrando variables de JavaScript en una gran parte de tu plantilla, puedes envolver el HTML en la directiva @verbatim
para que no tengas que prefijar cada declaración de eco de Blade con un símbolo @
:
@verbatim <div class="container"> Hello, {{ name }}. </div>@endverbatim
Directivas de Blade
Además de la herencia de plantillas y la visualización de datos, Blade también ofrece atajos convenientes para estructuras de control PHP comunes, como declaraciones condicionales y bucles. Estos atajos proporcionan una forma muy limpia y concisa de trabajar con estructuras de control PHP, al mismo tiempo que permanecen familiares para sus contrapartes en PHP.
Sentencias If
Puedes construir declaraciones if
utilizando las directivas @if
, @elseif
, @else
y @endif
. Estas directivas funcionan de manera idéntica a sus contrapartes en 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 ya discutidas, se pueden usar las directivas @isset
y @empty
como atajos 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
se pueden usar para determinar rápidamente si el usuario actual está autenticado o es un invitado:
@auth // The user is authenticated...@endauth @guest // The user is not authenticated...@endguest
Si es necesario, puedes especificar el guardia de autenticación que se debe comprobar al usar las directivas @auth
y @guest
:
@auth('admin') // The user is authenticated...@endauth @guest('admin') // The user is not authenticated...@endguest
Directivas de Entorno
Puedes verificar si la aplicación se está ejecutando en el entorno de producción utilizando la directiva @production
:
@production // Production specific content...@endproduction
O, puedes determinar si la aplicación se está ejecutando en un entorno específico utilizando la directiva @env
:
@env('staging') // The application is running in "staging"...@endenv @env(['staging', 'production']) // The application is running in "staging" or "production"...@endenv
Directivas de Sección
Puedes determinar si una sección de herencia de plantilla tiene contenido utilizando la directiva @hasSection
:
@hasSection('navigation') <div class="pull-right"> @yield('navigation') </div> <div class="clearfix"></div>@endif
Puedes usar la directiva sectionMissing
para determinar si una sección no tiene contenido:
@sectionMissing('navigation') <div class="pull-right"> @include('default-navigation') </div>@endif
Directivas de Sesión
La directiva @session
se puede usar para determinar si existe un valor de sesión. Si el valor de la sesión existe, el contenido de la plantilla dentro de las directivas @session
y @endsession
se evaluará. Dentro del contenido de la directiva @session
, puedes usar la variable $value
para mostrar el valor de la sesión:
@session('status') <div class="p-4 bg-green-100"> {{ $value }} </div>@endsession
Declaraciones Switch
Las declarativas de Switch se pueden construir utilizando 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 declaraciones condicionales, Blade proporciona directivas simples para trabajar con las estructuras de bucle de PHP. Nuevamente, cada una de estas directivas funciona de manera idéntica a sus contrapartes de 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
[!NOTA] Mientras iteras a través de un bucle
foreach
, puedes usar la variable de bucle para obtener información valiosa sobre el bucle, como si estás en la primera o la última iteración del bucle. Al usar bucles, también puedes omitir la iteración actual o finalizar el bucle utilizando las directivas@continue
y@break
:
@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 de continuación o de ruptura dentro de la declaración de la directiva:
@foreach ($users as $user) @continue($user->type == 1) <li>{{ $user->name }}</li> @break($user->number == 5)@endforeach
La Variable de Bucle
Mientras iteras a través de un bucle foreach
, una variable $loop
estará disponible dentro de tu bucle. Esta variable proporciona acceso a algunos bits útiles de información, como el índice actual del bucle y si esta es la primera o última iteración a través del bucle:
@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 te encuentras 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 the 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 actual del bucle (comienza en 0). |
$loop->iteration |
La iteración actual del bucle (comienza en 1). |
$loop->remaining |
Las iteraciones restantes en el bucle. |
$loop->count |
El número total de elementos en el array que se está iterando. |
$loop->first |
Si esta es la primera iteración a través del bucle. |
$loop->last |
Si esta es la última iteración a través del bucle. |
$loop->even |
Si esta es una iteración par a través del bucle. |
$loop->odd |
Si esta es una iteración impar a través del bucle. |
$loop->depth |
El nivel de anidación del bucle actual. |
$loop->parent |
Cuando se está en un bucle anidado, la variable del bucle del padre. |
Clases y Estilos Condicionales
La directiva @class
compila condicionalmente una cadena de clases CSS. La directiva acepta un array de clases donde la clave del array contiene la clase o las clases que deseas añadir, mientras que el valor es una expresión booleana. Si el elemento del array tiene una clave numérica, siempre será incluido en la lista de clases renderizadas:
@php $isActive = false; $hasError = true;@endphp <span @class([ 'p-4', 'font-bold' => $isActive, 'text-gray-500' => ! $isActive, 'bg-red' => $hasError,])></span> <span class="p-4 text-gray-500 bg-red"></span>
Del mismo modo, se puede utilizar la directiva @style
para añadir condicionalmente estilos CSS en línea a un elemento HTML:
@php $isActive = true;@endphp <span @style([ 'background-color: red', 'font-weight: bold' => $isActive,])></span> <span style="background-color: red; font-weight: bold;"></span>
Atributos Adicionales
Para mayor comodidad, puedes usar la directiva @checked
para indicar fácilmente si una entrada de casilla de verificación HTML dada está "marcada". Esta directiva devolverá checked
si la condición proporcionada evalúa a true
:
<input type="checkbox" name="active" value="active" @checked(old('active', $user->active)) />
Del mismo modo, se puede usar la directiva @selected
para indicar si una opción de selección dada debe estar "seleccionada":
<select name="version"> @foreach ($product->versions as $version) <option value="{{ $version }}" @selected(old('version') == $version)> {{ $version }} </option> @endforeach</select>
Además, se puede usar la directiva @disabled
para indicar si un elemento dado debería estar "deshabilitado":
<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>
Además, la directiva @readonly
se puede utilizar para indicar si un elemento dado debe ser "solo lectura":
<input type="email" name="email" value="email@laravel.com" @readonly($user->isNotAdmin()) />
Además, se puede usar la directiva @required
para indicar si un elemento dado debe ser "requerido":
<input type="text" name="title" value="title" @required($user->isAdmin()) />
Incluyendo Subvistas
[!NOTA] Aunque puedes usar la directiva
@include
, los componentes de Blade ofrecen una funcionalidad similar y presentan varios beneficios sobre la directiva@include
, como la vinculación de datos y atributos. La directiva@include
de Blade te permite incluir una vista de Blade desde otra vista. Todas las variables que están disponibles para 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 padre, también puedes pasar un array de datos adicionales que deberían estar disponibles para la vista incluida:
@include('view.name', ['status' => 'complete'])
Si intentas @include
una vista que no existe, Laravel lanzará un error. Si deseas incluir una vista que puede o no estar presente, debes usar la directiva @includeIf
:
@includeIf('view.name', ['status' => 'complete'])
Si deseas @include
una vista si una expresión booleana dada evalúa a true
o false
, puedes usar las directivas @includeWhen
y @includeUnless
:
@includeWhen($boolean, 'view.name', ['status' => 'complete']) @includeUnless($boolean, 'view.name', ['status' => 'complete'])
Para incluir la primera vista que existe a partir de un array dado de vistas, puedes usar la directiva includeFirst
:
@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])
[!WARNING] Debes evitar usar las constantes
__DIR__
y__FILE__
en tus vistas Blade, ya que se referirán a la ubicación de la vista compilada en caché.
Renderizando Vistas para Colecciones
Puedes combinar bucles e inclusiones en una sola línea con el directorio @each
de Blade:
@each('view.name', $jobs, 'job')
El primer argumento de laDirectiva @each
es la vista que se renderizará para cada elemento en el array o la colección. El segundo argumento es el array o la colección que deseas iterar, mientras que el tercer argumento es el nombre de la variable que se asignará a la iteración actual dentro de la vista. Así que, por ejemplo, si estás iterando sobre un array de jobs
, típicamente querrás acceder a cada trabajo como una variable job
dentro de la vista. La clave del array para la iteración actual estará disponible como la variable key
dentro de la vista.
También puedes pasar un cuarto argumento a la directiva @each
. Este argumento determina la vista que se renderizará si el array dado está vacío.
@each('view.name', $jobs, 'job', 'view.empty')
[!WARNING] Las vistas renderizadas a través de
@each
no heredan las variables de la vista padre. Si la vista hija requiere estas variables, debes usar las directivas@foreach
y@include
en su lugar.
La Directiva @once
La directiva @once
te permite definir una porción de la plantilla que solo se evaluará una vez por ciclo de renderizado. Esto puede ser útil para insertar una pieza dada de JavaScript en el encabezado de la página usando stacks. Por ejemplo, si estás renderizando un componente dado dentro de un bucle, es posible que desees insertar el JavaScript en el encabezado solo la primera vez que se renderiza el componente:
@once @push('scripts') <script> // Your custom JavaScript... </script> @endpush@endonce
Dado que la directiva @once
se utiliza a menudo junto con las directivas @push
o @prepend
, las directivas @pushOnce
y @prependOnce
están disponibles para tu conveniencia:
@pushOnce('scripts') <script> // Your custom JavaScript... </script>@endPushOnce
PHP en Raw
En algunas situaciones, es útil incrustar código PHP en tus vistas. Puedes usar la directiva @php
de Blade para ejecutar un bloque de PHP puro dentro de tu plantilla:
@php $counter = 1;@endphp
O, si solo necesitas usar PHP para importar una clase, puedes usar la directiva @use
:
@use('App\Models\Flight')
Se puede proporcionar un segundo argumento a laDirectiva @use
para alias la clase importada:
@use('App\Models\Flight', 'FlightModel')
Comentarios
Blade también te permite definir comentarios en tus vistas. Sin embargo, a diferencia de los comentarios HTML, los comentarios de Blade no se incluyen en el HTML devuelto por tu aplicación:
{{-- This comment will not be present in the rendered HTML --}}
Componentes
Los componentes y slots proporcionan beneficios similares a secciones, diseños e inclusiones; sin embargo, algunos pueden encontrar el modelo mental de componentes y slots más fácil de entender. Hay dos enfoques para escribir componentes: componentes basados en clases y componentes anónimos.
Para crear un componente basado en una clase, puedes usar el comando Artisan make:component
. Para ilustrar cómo usar componentes, crearemos un simple componente Alert
. El comando make:component
colocará el componente en el directorio app/View/Components
:
php artisan make:component Alert
El comando make:component
también creará una plantilla de vista para el componente. La vista se colocará en el directorio resources/views/components
. Al escribir componentes para tu propia aplicación, los componentes se descubren automáticamente dentro del directorio app/View/Components
y el directorio resources/views/components
, por lo que normalmente no se requiere un registro adicional de componentes.
También puedes crear componentes dentro de subdirectorios:
php artisan make:component Forms/Input
El comando anterior creará un componente Input
en el directorio app/View/Components/Forms
y la vista se colocará en el directorio resources/views/components/forms
.
Si deseas crear un componente anónimo (un componente con solo una plantilla Blade y sin clase), puedes usar la opción --view
al invocar el comando make:component
:
php artisan make:component forms.input --view
El comando anterior creará un archivo Blade en resources/views/components/forms/input.blade.php
, que se puede renderizar como un componente a través de <x-forms.input />
.
Registrando Componentes del Paquete Manualmente
Sin embargo, si estás construyendo un paquete que utiliza componentes Blade, necesitarás registrar manualmente tu clase de componente y su alias de etiqueta HTML. Típicamente, debes registrar tus componentes en el método boot
del proveedor de servicios de tu paquete:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. */public function boot(): void{ Blade::component('package-alert', Alert::class);}
Renderizando Componentes
Para mostrar un componente, puedes usar una etiqueta de componente Blade dentro de una de tus plantillas Blade. Las etiquetas de componente Blade comienzan con la cadena x-
seguida del nombre en kebab case de la clase del componente:
<x-alert/> <x-user-profile/>
Si la clase del componente está anidada más profundamente dentro del directorio app/View/Components
, puedes usar el carácter .
para indicar la anidación de directorios. Por ejemplo, si asumimos que un componente se encuentra en app/View/Components/Inputs/Button.php
, podemos renderizarlo de la siguiente manera:
Si deseas renderizar tu componente de manera condicional, puedes definir un método shouldRender
en la clase de tu componente. Si el método shouldRender
devuelve false
, el componente no será renderizado:
use Illuminate\Support\Str; /** * Whether the component should be rendered */public function shouldRender(): bool{ return Str::length($this->message) > 0;}
Pasando Datos a Componentes
Puedes pasar datos a componentes Blade utilizando atributos HTML. Los valores primitivos fijos pueden pasarse al componente utilizando cadenas de atributos HTML simples. Las expresiones y variables de PHP deben pasarse al componente a través de atributos que usen el carácter :
como prefijo:
<x-alert type="error" :message="$message"/>
Debes definir todos los atributos de datos del componente en su constructor de clase. Todas las propiedades públicas en un componente estarán disponibles automáticamente para la vista del componente. No es necesario pasar los datos a la vista desde el método render
del componente:
<?php namespace App\View\Components; use Illuminate\View\Component;use Illuminate\View\View; class Alert extends Component{ /** * Create the component instance. */ public function __construct( public string $type, public string $message, ) {} /** * Get the view / contents that represent the component. */ public function render(): View { return view('components.alert'); }}
Cuando se renderiza tu componente, puedes mostrar el contenido de las variables públicas de tu componente haciendo eco de las variables por nombre:
<div class="alert alert-{{ $type }}"> {{ $message }}</div>
Mayúsculas y minúsculas
Los argumentos del constructor del componente deben especificarse utilizando camelCase
, mientras que se debe usar kebab-case
al referirse a los nombres de los argumentos en tus atributos HTML. Por ejemplo, dado el siguiente constructor de componente:
/** * Create the component instance. */public function __construct( public string $alertType,) {}
El argumento $alertType
puede proporcionarse al componente de la siguiente manera:
<x-alert alert-type="danger" />
Sintaxis de Atributo Corto
Al pasar atributos a los componentes, también puedes usar una sintaxis de "atributo corto". Esto es a menudo conveniente ya que los nombres de los atributos a menudo coinciden con los nombres de las variables a las que corresponden:
{{-- Short attribute syntax... --}}<x-profile :$userId :$name /> {{-- Is equivalent to... --}}<x-profile :user-id="$userId" :name="$name" />
Escapeando la Renderización de Atributos
Dado que algunos frameworks de JavaScript como Alpine.js también utilizan atributos con prefijo de dos puntos, puedes usar un prefijo de doble dos puntos (::
) para informar a Blade que el atributo no es una expresión PHP. Por ejemplo, dado el siguiente componente:
<x-button ::class="{ danger: isDeleting }"> Submit</x-button>
El siguiente HTML será renderizado por Blade:
<button :class="{ danger: isDeleting }"> Submit</button>
Métodos de Componente
Además de que las variables públicas estén disponibles en la plantilla de tu componente, se pueden invocar cualquier método público en el componente. Por ejemplo, imagina un componente que tiene un método isSelected
:
/** * Determine if the given option is the currently selected option. */public function isSelected(string $option): bool{ return $option === $this->selected;}
Puedes ejecutar este método desde la plantilla de tu componente invocando la variable que coincide con el nombre del método:
<option {{ $isSelected($value) ? 'selected' : '' }} value="{{ $value }}"> {{ $label }}</option>
Accediendo a Atributos y Slots Dentro de Clases de Componentes
Los componentes Blade también te permiten acceder al nombre del componente, los atributos y el slot dentro del método render de la clase. Sin embargo, para acceder a estos datos, debes devolver una función anónima desde el método render
de tu componente:
use Closure; /** * Get the view / contents that represent the component. */public function render(): Closure{ return function () { return '<div {{ $attributes }}>Components content</div>'; };}
La función anónima devuelta por el método render
de tu componente también puede recibir un array $data
como su único argumento. Este array contendrá varios elementos que proporcionan información sobre el componente:
return function (array $data) { // $data['componentName']; // $data['attributes']; // $data['slot']; return '<div {{ $attributes }}>Components content</div>';}
[!WARNING] Los elementos en el array
$data
nunca deben ser incrustados directamente en la cadena Blade devuelta por tu métodorender
, ya que hacerlo podría permitir la ejecución remota de código a través del contenido de atributos maliciosos. ElcomponentName
es igual al nombre utilizado en la etiqueta HTML después del prefijox-
. Así que elcomponentName
de<x-alert />
seráalert
. El elementoattributes
contendrá todos los atributos que estaban presentes en la etiqueta HTML. El elementoslot
es una instancia deIlluminate\Support\HtmlString
con el contenido de la ranura del componente. La función anónima debe devolver una cadena. Si la cadena devuelta corresponde a una vista existente, esa vista se renderizará; de lo contrario, la cadena devuelta se evaluará como una vista Blade en línea.
Dependencias Adicionales
Si tu componente requiere dependencias del contenedor de servicios de Laravel, puedes listarlas antes de cualquiera de los atributos de datos del componente y serán inyectadas automáticamente por el contenedor:
use App\Services\AlertCreator; /** * Create the component instance. */public function __construct( public AlertCreator $creator, public string $type, public string $message,) {}
Ocultando Atributos / Métodos
Si deseas evitar que algunos métodos o propiedades públicas se expongan como variables a la plantilla de tu componente, puedes añadirlos a un array de propiedad $except
en tu componente:
<?php namespace App\View\Components; use Illuminate\View\Component; class Alert extends Component{ /** * The properties / methods that should not be exposed to the component template. * * @var array */ protected $except = ['type']; /** * Create the component instance. */ public function __construct( public string $type, ) {}}
Atributos de Componente
Ya hemos examinado cómo pasar atributos de datos a un componente; sin embargo, a veces es posible que necesites especificar atributos HTML adicionales, como class
, que no son parte de los datos requeridos para que un componente funcione. Típicamente, deseas pasar estos atributos adicionales al elemento raíz de la plantilla del componente. Por ejemplo, imagina que queremos renderizar un componente de alerta
así:
<x-alert type="error" :message="$message" class="mt-4"/>
Todos los atributos que no son parte del constructor del componente se añadirán automáticamente al "atributo bag" del componente. Este atributo bag se pone a disposición del componente mediante la variable $attributes
. Todos los atributos pueden ser renderizados dentro del componente al echo de esta variable:
<div {{ $attributes }}> <!-- Component content --></div>
[!WARNING] Usar directivas como
@env
dentro de etiquetas de componente no es compatible en este momento. Por ejemplo,<x-alert :live="@env('production')"/>
no será compilado.
Atributos Predeterminados / Combinados
A veces es posible que necesites especificar valores predeterminados para atributos o fusionar valores adicionales en algunos de los atributos del componente. Para lograr esto, puedes usar el método merge
de la bolsa de atributos. Este método es especialmente útil para definir un conjunto de clases CSS predeterminadas que deben aplicarse siempre a un componente:
<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}> {{ $message }}</div>
Si asumimos que este componente se utiliza de la siguiente manera: El HTML final renderizado del componente aparecerá como el siguiente:
<div class="alert alert-error mb-4"> <!-- Contents of the $message variable --></div>
Merging Clases de Forma Condicional
A veces es posible que desees combinar clases si una condición dada es true
. Puedes lograr esto a través del método class
, que acepta un array de clases donde la clave del array contiene la clase o las clases que deseas agregar, mientras que el valor es una expresión booleana. Si el elemento del array tiene una clave numérica, siempre se incluirá en la lista de clases renderizadas:
<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}> {{ $message }}</div>
Si necesitas combinar otros atributos en tu componente, puedes encadenar el método merge
al método class
:
<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}> {{ $slot }}</button>
[!NOTA] Si necesitas compilar clases de forma condicional en otros elementos HTML que no deberían recibir atributos combinados, puedes usar la directiva
@class
.
Fusión de Atributos No de Clase
Al fusionar atributos que no son atributos class
, los valores proporcionados al método merge
se considerarán los "valores predeterminados" del atributo. Sin embargo, a diferencia del atributo class
, estos atributos no se fusionarán con los valores de atributo inyectados. En su lugar, serán sobrescritos. Por ejemplo, la implementación de un componente button
puede verse como la siguiente:
<button {{ $attributes->merge(['type' => 'button']) }}> {{ $slot }}</button>
Para renderizar el componente de botón con un type
personalizado, se puede especificar al consumir el componente. Si no se especifica ningún tipo, se utilizará el tipo button
:
<x-button type="submit"> Submit</x-button>
El HTML renderizado del componente button
en este ejemplo sería:
<button type="submit"> Submit</button>
Si deseas que un atributo diferente de class
tenga su valor predeterminado y los valores inyectados juntos, puedes usar el método prepends
. En este ejemplo, el atributo data-controller
siempre comenzará con profile-controller
y cualquier valor data-controller
inyectado adicional se colocará después de este valor predeterminado:
<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}> {{ $slot }}</div>
Recuperando y Filtrando Atributos
Puedes filtrar atributos utilizando el método filter
. Este método acepta una función anónima que debe devolver true
si deseas mantener el atributo en la bolsa de atributos:
{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}
Para conveniencia, puedes usar el método whereStartsWith
para recuperar todos los atributos cuyas claves comienzan con una cadena dada:
{{ $attributes->whereStartsWith('wire:model') }}
Por el contrario, el método whereDoesntStartWith
se puede utilizar para excluir todos los atributos cuyos keys comiencen con una cadena dada:
{{ $attributes->whereDoesntStartWith('wire:model') }}
Usando el método first
, puedes renderizar el primer atributo en un paquete de atributos dado:
{{ $attributes->whereStartsWith('wire:model')->first() }}
Si deseas verificar si un atributo está presente en el componente, puedes usar el método has
. Este método acepta el nombre del atributo como su único argumento y devuelve un booleano que indica si el atributo está presente o no:
@if ($attributes->has('class')) <div>Class attribute is present</div>@endif
Si se pasa un array al método has
, el método determinará si todos los atributos dados están presentes en el componente:
@if ($attributes->has(['name', 'class'])) <div>All of the attributes are present</div>@endif
El método hasAny
se puede utilizar para determinar si cualquiera de los atributos dados está presente en el componente:
@if ($attributes->hasAny(['href', ':href', 'v-bind:href'])) <div>One of the attributes is present</div>@endif
Puedes recuperar el valor de un atributo específico utilizando el método get
:
{{ $attributes->get('class') }}
Palabras Clave Reservadas
Por defecto, algunas palabras clave están reservadas para el uso interno de Blade con el fin de renderizar componentes. Las siguientes palabras clave no pueden definirse como propiedades públicas o nombres de métodos dentro de tus componentes:
-
data
-
render
-
resolveView
-
shouldRender
-
view
-
withAttributes
-
withName
Slots
A menudo necesitarás pasar contenido adicional a tu componente a través de "slots". Los slots del componente se renderizan mediante la variable $slot
. Para explorar este concepto, imaginemos que un componente alert
tiene el siguiente marcado:
<!-- /resources/views/components/alert.blade.php --> <div class="alert alert-danger"> {{ $slot }}</div>
Podemos pasar contenido al slot
inyectando contenido en el componente:
<x-alert> <strong>Whoops!</strong> Something went wrong!</x-alert>
A veces un componente puede necesitar renderizar múltiples ranuras diferentes en diferentes ubicaciones dentro del componente. Modifiquemos nuestro componente de alerta para permitir la inyección de una ranura de "título":
<!-- /resources/views/components/alert.blade.php --> <span class="alert-title">{{ $title }}</span> <div class="alert alert-danger"> {{ $slot }}</div>
Puedes definir el contenido del slot nombrado utilizando la etiqueta x-slot
. Cualquier contenido que no esté dentro de una etiqueta x-slot
explícita se pasará al componente en la variable $slot
:
<x-alert> <x-slot:title> Server Error </x-slot> <strong>Whoops!</strong> Something went wrong!</x-alert>
Puedes invocar el método isEmpty
de un slot para determinar si el slot contiene contenido:
<span class="alert-title">{{ $title }}</span> <div class="alert alert-danger"> @if ($slot->isEmpty()) This is default content if the slot is empty. @else {{ $slot }} @endif</div>
Además, se puede usar el método hasActualContent
para determinar si el espacio contiene algún contenido "real" que no sea un comentario HTML:
@if ($slot->hasActualContent()) The scope has non-comment content.@endif
Slots Con Alcance
Si has utilizado un framework de JavaScript como Vue, es posible que estés familiarizado con los "scoped slots", que te permiten acceder a datos o métodos del componente dentro de tu slot. Puedes lograr un comportamiento similar en Laravel definiendo métodos o propiedades públicos en tu componente y accediendo al componente dentro de tu slot a través de la variable $component
. En este ejemplo, asumiremos que el componente x-alert
tiene un método público formatAlert
definido en su clase de componente:
<x-alert> <x-slot:title> {{ $component->formatAlert('Server Error') }} </x-slot> <strong>Whoops!</strong> Something went wrong!</x-alert>
Atributos de Slot
Al igual que con los componentes Blade, puedes asignar atributos adicionales a los slots, como nombres de clases CSS:
<x-card class="shadow-sm"> <x-slot:heading class="font-bold"> Heading </x-slot> Content <x-slot:footer class="text-sm"> Footer </x-slot></x-card>
Para interactuar con los atributos del slot, puedes acceder a la propiedad attributes
de la variable del slot. Para obtener más información sobre cómo interactuar con los atributos, consulta la documentación sobre atributos de componente:
@props([ 'heading', 'footer',]) <div {{ $attributes->class(['border']) }}> <h1 {{ $heading->attributes->class(['text-lg']) }}> {{ $heading }} </h1> {{ $slot }} <footer {{ $footer->attributes->class(['text-gray-700']) }}> {{ $footer }} </footer></div>
Vistas de Componente en Línea
Para componentes muy pequeños, puede resultar engorroso gestionar tanto la clase del componente como la plantilla de vista del componente. Por esta razón, puedes devolver el marcado del componente directamente desde el método render
:
/** * Get the view / contents that represent the component. */public function render(): string{ return <<<'blade' <div class="alert alert-danger"> {{ $slot }} </div> blade;}
Generando Componentes de Vista En línea
Para crear un componente que renderice una vista en línea, puedes usar la opción inline
al ejecutar el comando make:component
:
php artisan make:component Alert --inline
Componentes Dinámicos
A veces puede que necesites renderizar un componente pero no sepas qué componente debe ser renderizado hasta el tiempo de ejecución. En esta situación, puedes usar el componente dynamic-component
incorporado de Laravel para renderizar el componente en función de un valor o variable en tiempo de ejecución:
// $componentName = "secondary-button"; <x-dynamic-component :component="$componentName" class="mt-4" />
Registrando Componentes Manualmente
[!WARNING] La siguiente documentación sobre el registro manual de componentes se aplica principalmente a aquellos que están escribiendo paquetes Laravel que incluyen componentes de vista. Si no estás escribiendo un paquete, esta parte de la documentación del componente puede no ser relevante para ti. Al escribir componentes para tu propia aplicación, los componentes se descubren automáticamente en el directorio
app/View/Components
y en el directorioresources/views/components
. Sin embargo, si estás creando un paquete que utiliza componentes Blade o colocando componentes en directorios no convencionales, necesitarás registrar manualmente tu clase de componente y su alias de etiqueta HTML para que Laravel sepa dónde encontrar el componente. Normalmente, deberías registrar tus componentes en el métodoboot
del proveedor de servicios de tu paquete:
use Illuminate\Support\Facades\Blade;use VendorPackage\View\Components\AlertComponent; /** * Bootstrap your package's services. */public function boot(): void{ Blade::component('package-alert', AlertComponent::class);}
Una vez que tu componente haya sido registrado, puede ser renderizado utilizando su alias de etiqueta:
<x-package-alert/>
Autoloading Package Components
Alternativamente, puedes usar el método componentNamespace
para autoload de clases de componentes por convención. Por ejemplo, un paquete Nightshade
podría tener componentes Calendar
y ColorPicker
que residen dentro del espacio de nombres Package\Views\Components
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. */public function boot(): void{ Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');}
Esto permitirá el uso de componentes del paquete por su espacio de nombres de vendedor utilizando la sintaxis package-name::
:
<x-nightshade::calendar /><x-nightshade::color-picker />
Blade detectará automáticamente la clase que está vinculada a este componente utilizando la notación Pascal para el nombre del componente. También se admiten subdirectorios utilizando la notación de "punto".
Componentes Anónimos
Similar a los componentes en línea, los componentes anónimos proporcionan un mecanismo para gestionar un componente a través de un solo archivo. Sin embargo, los componentes anónimos utilizan un solo archivo de vista y no tienen una clase asociada. Para definir un componente anónimo, solo necesitas colocar una plantilla Blade dentro de tu directorio resources/views/components
. Por ejemplo, suponiendo que has definido un componente en resources/views/components/alert.blade.php
, puedes renderizarlo de la siguiente manera:
<x-alert/>
Puedes usar el carácter .
para indicar si un componente está anidado más profundamente dentro del directorio components
. Por ejemplo, asumiendo que el componente se define en resources/views/components/inputs/button.blade.php
, puedes renderizarlo así:
<x-inputs.button/>
Componentes de Índice Anónimos
A veces, cuando un componente se compone de muchas plantillas Blade, es posible que desees agrupar las plantillas del componente dado dentro de un solo directorio. Por ejemplo, imagina un componente "accordion" con la siguiente estructura de directorio:
/resources/views/components/accordion.blade.php/resources/views/components/accordion/item.blade.php
Esta estructura de directorios te permite renderizar el componente de acordeón y su elemento así:
<x-accordion> <x-accordion.item> ... </x-accordion.item></x-accordion>
Sin embargo, para poder renderizar el componente de acordeón a través de x-accordion
, nos vimos obligados a colocar la plantilla del componente de acordeón "index" en el directorio resources/views/components
en lugar de anidrarla dentro del directorio accordion
con las otras plantillas relacionadas con el acordeón.
Afortunadamente, Blade te permite colocar un archivo index.blade.php
dentro del directorio de plantillas de un componente. Cuando existe una plantilla index.blade.php
para el componente, se renderizará como el nodo "root" del componente. Así que podemos continuar utilizando la misma sintaxis de Blade dada en el ejemplo anterior; sin embargo, ajustaremos nuestra estructura de directorios de la siguiente manera:
/resources/views/components/accordion/index.blade.php/resources/views/components/accordion/item.blade.php
Propiedades / Atributos de Datos
Dado que los componentes anónimos no tienen ninguna clase asociada, es posible que te preguntes cómo puedes diferenciar qué datos deben pasarse al componente como variables y qué atributos deben colocarse en la bolsa de atributos del componente.
Puedes especificar qué atributos deben considerarse variables de datos utilizando la directiva @props
en la parte superior de la plantilla Blade de tu componente. Todos los demás atributos del componente estarán disponibles a través de la bolsa de atributos del componente. Si deseas dar a una variable de datos un valor predeterminado, puedes especificar el nombre de la variable como la clave del array y el valor predeterminado como el valor del array:
<!-- /resources/views/components/alert.blade.php --> @props(['type' => 'info', 'message']) <div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}> {{ $message }}</div>
Dada la definición del componente anterior, podemos renderizar el componente de la siguiente manera:
<x-alert type="error" :message="$message" class="mb-4"/>
Accediendo a los Datos del Padre
A veces es posible que desees acceder a datos de un componente padre dentro de un componente hijo. En estos casos, puedes usar la directiva @aware
. Por ejemplo, imagina que estamos construyendo un componente de menú complejo que consiste en un padre <x-menu>
y un hijo <x-menu.item>
:
<x-menu color="purple"> <x-menu.item>...</x-menu.item> <x-menu.item>...</x-menu.item></x-menu>
El componente <x-menu>
puede tener una implementación como la siguiente:
<!-- /resources/views/components/menu/index.blade.php --> @props(['color' => 'gray']) <ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}> {{ $slot }}</ul>
Debido a que la prop color
solo se pasó al padre (<x-menu>
), no estará disponible dentro de <x-menu.item>
. Sin embargo, si usamos la directiva @aware
, podemos hacer que esté disponible dentro de <x-menu.item>
también:
<!-- /resources/views/components/menu/item.blade.php --> @aware(['color' => 'gray']) <li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}> {{ $slot }}</li>
[!WARNING] La directiva
@aware
no puede acceder a los datos del padre que no se pasan explícitamente al componente padre a través de atributos HTML. Los valores predeterminados@props
que no se pasan explícitamente al componente padre no pueden ser accesibles por la directiva@aware
.
Rutas de Componentes Anónimos
Como se discutió anteriormente, los componentes anónimos suelen definirse colocando una plantilla Blade dentro de tu directorio resources/views/components
. Sin embargo, es posible que desees registrar ocasionalmente otras rutas de componentes anónimos con Laravel además de la ruta predeterminada.
El método anonymousComponentPath
acepta la "ruta" a la ubicación del componente anónimo como su primer argumento y un "espacio de nombres" opcional bajo el cual se deben colocar los componentes como su segundo argumento. Típicamente, este método debe ser llamado desde el método boot
de uno de los proveedores de servicios de tu aplicación:
/** * Bootstrap any application services. */public function boot(): void{ Blade::anonymousComponentPath(__DIR__.'/../components');}
Cuando las rutas de componentes se registran sin un prefijo especificado, como en el ejemplo anterior, se pueden renderizar en tus componentes Blade sin un prefijo correspondiente también. Por ejemplo, si existe un componente panel.blade.php
en la ruta registrada arriba, se puede renderizar así:
<x-panel />
El prefijo "namespaces" puede proporcionarse como segundo argumento al método anonymousComponentPath
:
Blade::anonymousComponentPath(__DIR__.'/../components', 'dashboard');
Cuando se proporciona un prefijo, los componentes dentro de ese "espacio de nombres" pueden ser renderizados añadiendo el espacio de nombres del componente al nombre del componente cuando se renderiza el componente:
<x-dashboard::panel />
Construyendo Diseños
Diseños Usando Componentes
La mayoría de las aplicaciones web mantienen el mismo diseño general en varias páginas. Sería increíblemente engorroso y difícil de mantener nuestra aplicación si tuviéramos que repetir todo el HTML del diseño en cada vista que creamos. Afortunadamente, es conveniente definir este diseño como un solo componente Blade y luego usarlo en toda nuestra aplicación.
Definiendo el Componente de Layout
Por ejemplo, imagina que estamos construyendo una aplicación de lista de "tareas". Podríamos definir un componente layout
que se vea de la siguiente manera:
<!-- resources/views/components/layout.blade.php --> <html> <head> <title>{{ $title ?? 'Todo Manager' }}</title> </head> <body> <h1>Todos</h1> <hr/> {{ $slot }} </body></html>
Aplicando el Componente de Layout
Una vez que se ha definido el componente layout
, podemos crear una vista Blade que utilice el componente. En este ejemplo, definiremos una vista simple que muestra nuestra lista de tareas:
<!-- resources/views/tasks.blade.php --> <x-layout> @foreach ($tasks as $task) <div>{{ $task }}</div> @endforeach</x-layout>
Recuerda que el contenido que se inyecta en un componente se suministrará a la variable $slot
predeterminada dentro de nuestro componente layout
. Como habrás notado, nuestro layout
también respeta un slot $title
si se proporciona uno; de lo contrario, se muestra un título predeterminado. Podemos inyectar un título personalizado desde nuestra vista de lista de tareas utilizando la sintaxis de slot estándar discutida en la documentación de componentes:
<!-- resources/views/tasks.blade.php --> <x-layout> <x-slot:title> Custom Title </x-slot> @foreach ($tasks as $task) <div>{{ $task }}</div> @endforeach</x-layout>
Ahora que hemos definido nuestras vistas de diseño y lista de tareas, solo necesitamos devolver la vista task
desde una ruta:
use App\Models\Task; Route::get('/tasks', function () { return view('tasks', ['tasks' => Task::all()]);});
Diseños Usando Herencia de Plantillas
Definiendo un Layout
Los layouts también pueden ser creados a través de "herencia de plantillas". Esta fue la principal forma de construir aplicaciones antes de la introducción de componentes. Para empezar, echemos un vistazo a un ejemplo simple. Primero, examinaremos un diseño de página. Dado que la mayoría de las aplicaciones web mantienen el mismo diseño general en varias páginas, es conveniente definir este diseño como una sola vista de Blade:
<!-- 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 un marcado HTML típico. Sin embargo, toma nota de las directivas @section
y @yield
. La directiva @section
, como su nombre indica, define una sección de contenido, mientras que la directiva @yield
se utiliza para mostrar el contenido de una sección dada.
Ahora que hemos definido un diseño para nuestra aplicación, definamos una página hija que herede el diseño.
Extendiendo un Layout
Al definir una vista hija, utiliza la directiva @extends
de Blade para especificar qué diseño debería "heredar" la vista hija. Las vistas que extienden un diseño Blade pueden inyectar contenido en las secciones del diseño utilizando directivas @section
. Recuerda que, como se vio en el ejemplo anterior, el contenido de estas secciones se mostrará en el diseño utilizando @yield
:
<!-- 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 añadir (en lugar de sobrescribir) contenido a la barra lateral del diseño. La directiva @parent
será reemplazada por el contenido del diseño cuando se renderice la vista.
[!NOTA] A diferencia del ejemplo anterior, esta sección
sidebar
termina con@endsection
en lugar de@show
. La directiva@endsection
solo definirá una sección, mientras que@show
definirá y cederá inmediatamente la sección. La directiva@yield
también acepta un valor predeterminado como su segundo parámetro. Este valor se renderizará si la sección que se está cediendo es indefinida:
@yield('content', 'Default content')
Formularios
Campo CSRF
Siempre que definas 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 de Método
Dado que los formularios HTML no pueden hacer solicitudes PUT
, PATCH
o DELETE
, necesitarás añadir un campo oculto _method
para simular 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
se puede usar para verificar rápidamente si existen mensajes de error de validación para un atributo dado. Dentro de una directiva @error
, puedes mostrar 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
Dado que la directiva @error
se compila a una declaración "if", puedes usar la directiva @else
para renderizar contenido cuando no hay un error para un atributo:
<!-- /resources/views/auth.blade.php --> <label for="email">Email address</label> <input id="email" type="email" class="@error('email') is-invalid @else is-valid @enderror">
Puedes pasar el nombre de un grupo de errores específico como segundo parámetro a la directiva @error
para recuperar mensajes de error de validación 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
Pilas
Blade te permite añadir a pilas nombradas que pueden ser renderizadas en otra vista o diseño. Esto puede ser particularmente útil para especificar cualquier biblioteca de JavaScript requerida por tus vistas secundarias:
@push('scripts') <script src="/example.js"></script>@endpush
Si deseas @push
contenido si una expresión booleana dada evalúa a true
, puedes usar la directiva @pushIf
:
@pushIf($shouldPush, 'scripts') <script src="/example.js"></script>@endPushIf
Puedes apilar tantas veces como sea necesario. 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 deseas añadir 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 Servicio
La directiva @inject
se puede usar 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 la interfaz del servicio que deseas resolver:
@inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}.</div>
Renderizando Plantillas Blade en Línea
A veces puede que necesites transformar una cadena de plantilla Blade sin procesar en HTML válido. Puedes lograr esto usando el método render
proporcionado por la fachada Blade
. El método render
acepta la cadena de plantilla Blade y un array opcional de datos para proporcionar a la plantilla:
use Illuminate\Support\Facades\Blade; return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
Laravel renderiza plantillas Blade en línea escribiéndolas en el directorio storage/framework/views
. Si deseas que Laravel elimine estos archivos temporales después de renderizar la plantilla Blade, puedes proporcionar el argumento deleteCachedView
al método:
return Blade::render( 'Hello, {{ $name }}', ['name' => 'Julian Bashir'], deleteCachedView: true);
Renderizando Fragmentos de Blade
Al utilizar frameworks frontend como Turbo y htmx, es posible que en ocasiones necesites devolver solo una porción de una plantilla Blade dentro de tu respuesta HTTP. Los "fragmentos" de Blade te permiten hacer exactamente eso. Para comenzar, coloca una porción de tu plantilla Blade dentro de las directivas @fragment
y @endfragment
:
@fragment('user-list') <ul> @foreach ($users as $user) <li>{{ $user->name }}</li> @endforeach </ul>@endfragment
Entonces, al renderizar la vista que utiliza esta plantilla, puedes invocar el método fragment
para especificar que solo el fragmento especificado debe incluirse en la respuesta HTTP saliente:
return view('dashboard', ['users' => $users])->fragment('user-list');
El método fragmentIf
te permite devolver condicionalmente un fragmento de una vista basado en una condición dada. De lo contrario, se devolverá la vista completa:
return view('dashboard', ['users' => $users]) ->fragmentIf($request->hasHeader('HX-Request'), 'user-list');
Los métodos fragments
y fragmentsIf
te permiten devolver múltiples fragmentos de vista en la respuesta. Los fragmentos se concatenarán:
view('dashboard', ['users' => $users]) ->fragments(['user-list', 'comment-list']); view('dashboard', ['users' => $users]) ->fragmentsIf( $request->hasHeader('HX-Request'), ['user-list', 'comment-list'] );
Extendiendo Blade
Blade te permite definir tus propias directivas personalizadas utilizando el método directive
. Cuando el compilador de Blade encuentra la directiva personalizada, llamará a la devolución de llamada proporcionada con la expresión que contiene la directiva.
El siguiente ejemplo crea un directive @datetime($var)
que formatea un $var
dado, que debe ser 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. */ public function register(): void { // ... } /** * Bootstrap any application services. */ public function boot(): void { Blade::directive('datetime', function (string $expression) { return "<?php echo ($expression)->format('m/d/Y H:i'); ?>"; }); }}
Como puedes ver, encadenaremos el método format
a cualquier expresión que se pase a la directiva. Así que, en este ejemplo, el PHP final generado por esta directiva será:
<?php echo ($var)->format('m/d/Y H:i'); ?>
[!WARNING] Después de actualizar la lógica de un directivo de Blade, necesitarás eliminar todas las vistas de Blade en caché. Las vistas de Blade en caché pueden ser eliminadas utilizando el comando Artisan
view:clear
.
Controladores Echo Personalizados
Si intentas "echo" un objeto utilizando Blade, se invocará el método __toString
del objeto. El método __toString
es uno de los "métodos mágicos" integrados de PHP. Sin embargo, a veces puede que no tengas control sobre el método __toString
de una clase dada, como cuando la clase con la que estás interactuando pertenece a una biblioteca de terceros.
En estos casos, Blade te permite registrar un manejador de eco personalizado para ese tipo particular de objeto. Para lograr esto, debes invocar el método stringable
de Blade. El método stringable
acepta una función anónima. Esta función anónima debe indicar el tipo de objeto que es responsable de renderizar. Típicamente, el método stringable
debe invocarse dentro del método boot
de la clase AppServiceProvider
de tu aplicación:
use Illuminate\Support\Facades\Blade;use Money\Money; /** * Bootstrap any application services. */public function boot(): void{ Blade::stringable(function (Money $money) { return $money->formatTo('en_GB'); });}
Una vez que tu manejador de eco personalizado haya sido definido, simplemente puedes hacer eco del objeto en tu plantilla Blade:
Cost: {{ $money }}
Declaraciones If Personalizadas
Programar una directiva personalizada a veces es más complejo de lo necesario al definir declaraciones condicionales personalizadas simples. Por esa razón, Blade ofrece un método Blade::if
que te permite definir rápidamente directivas condicionales personalizadas utilizando funciones anónimas
. Por ejemplo, definamos una condicional personalizada que verifique el "disk" predeterminado configurado para la aplicación. Podemos hacer esto en el método boot
de nuestro AppServiceProvider
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap any application services. */public function boot(): void{ Blade::if('disk', function (string $value) { return config('filesystems.default') === $value; });}
Una vez que se haya definido la condición personalizada, puedes usarla dentro de tus plantillas:
@disk('local') <!-- The application is using the local disk... -->@elsedisk('s3') <!-- The application is using the s3 disk... -->@else <!-- The application is using some other disk... -->@enddisk @unlessdisk('local') <!-- The application is not using the local disk... -->@enddisk