1. Conceptos básicos
  2. Plantillas Blade

Únete a nuestra comunidad de Telegram @webblend!

Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.

Introducción

Blade es el motor de plantillas simple pero potente incluido con Laravel. A diferencia de algunos motores de plantillas PHP, Blade no te restringe a usar código PHP simple en tus plantillas. De hecho, todas las plantillas de Blade se compilan en código PHP simple y se almacenan en caché hasta que se modifican, lo que significa que Blade agrega prácticamente cero sobrecarga a tu aplicación. Los archivos de plantilla de Blade usan la extensión de archivo .blade.php y generalmente se almacenan en el directorio resources/views.

Las vistas de Blade se pueden devolver desde rutas o controladores utilizando el ayudante global view. Por supuesto, como se menciona en la documentación sobre vistas, los datos se pueden pasar a la vista de Blade utilizando el segundo argumento del ayudante view:

Route::get('/', function () {
return view('greeting', ['name' => 'Finn']);
});

Potenciando Blade con Livewire

¿Quieres llevar tus plantillas de Blade al siguiente nivel y construir interfaces dinámicas con facilidad? Echa un vistazo a Laravel Livewire. Livewire te permite escribir componentes de Blade que se complementan con funcionalidades dinámicas que normalmente solo serían posibles mediante frameworks frontend como React o Vue, proporcionando un enfoque excelente para construir frontends modernos y reactivos sin las complejidades, representación del lado del cliente o pasos de compilación de muchos frameworks de JavaScript.

Visualización de Datos

Puedes mostrar datos que se pasan a tus vistas de Blade envolviendo la variable entre 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:

Hola, {{ $name }}.

Nota Las declaraciones {{ }} de eco de Blade se envían automáticamente a través de la función htmlspecialchars de PHP para evitar ataques XSS.

No estás limitado a mostrar el contenido de las variables que se pasan a la vista. También puedes hacer echo de los resultados de cualquier función de PHP. De hecho, puedes poner cualquier código PHP que desees dentro de una declaración de echo de Blade:

La marca de tiempo UNIX actual es {{ time() }}.

Codificación de Entidades HTML

De forma predeterminada, Blade (y la función e de Laravel) codificarán las entidades HTML dos veces. Si deseas deshabilitar la doble codificación, 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
{
/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::withoutDoubleEncoding();
}
}

Visualización de Datos No Escapados

Por defecto, las declaraciones Blade {{ }} se envían automáticamente a través de la función htmlspecialchars de PHP para evitar ataques XSS. Si no deseas que tus datos se escapen, puedes usar la siguiente sintaxis:

Hola, {!! $name !!}.

Advertencia Ten mucho cuidado al hacer echo de contenido proporcionado por los usuarios de tu aplicación. Por lo general, debes usar la sintaxis de llaves dobles escapadas para evitar ataques XSS al mostrar datos proporcionados por el usuario.

Blade y Frameworks de JavaScript

Dado que muchos marcos de trabajo de JavaScript también utilizan llaves "curly" para indicar que una expresión determinada debe mostrarse en el navegador, puedes usar el símbolo @ para informar al motor de renderización de Blade que una expresión debe permanecer sin cambios. Por ejemplo:

<h1>Laravel</h1>
 
Hola, @{{ name }}.

En este ejemplo, el símbolo @ será eliminado por Blade; sin embargo, la expresión {{ name }} permanecerá sin cambios por el motor de Blade, lo que permitirá que sea renderizada por tu marco de trabajo de JavaScript.

El símbolo @ también se puede usar para escapar de las directivas de Blade:

{{-- Blade template --}}
@@if()
 
<!-- HTML output -->
@if()

Renderizado de 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 Illuminate\Support\Js::from. El método from acepta los mismos argumentos que la función json_encode de PHP; sin embargo, asegurará que el JSON resultante esté correctamente escapado para su inclusión dentro de las comillas HTML. El método from devolverá una cadena de declaración JavaScript JSON.parse que convertirá el objeto o array dado en un objeto JavaScript válido:

<script>
var app = {{ Illuminate\Support\Js::from($array) }};
</script>

Las versiones más recientes del esqueleto de aplicación de Laravel incluyen un facade Js, que proporciona un acceso conveniente a esta funcionalidad dentro de tus plantillas de Blade:

<script>
var app = {{ Js::from($array) }};
</script>

Advertencia Solo debes usar el método Js::from para renderizar variables existentes como JSON. La plantilla de Blade se basa en expresiones regulares y intentar pasar una expresión compleja a la directiva puede causar fallos inesperados.

La Directiva @verbatim

Una vez que se haya definido tu manejador de echo personalizado, simplemente puedes hacer eco del objeto en tu plantilla Blade:

@verbatim
<div class="container">
Hola, {{ name }}.
</div>
@endverbatim

Directivas de Blade

Además de la herencia de plantillas y la visualización de datos, Blade también proporciona atajos convenientes para estructuras de control PHP comunes, como declaraciones condicionales y bucles. Estos atajos ofrecen una forma muy limpia y concisa de trabajar con estructuras de control PHP y siguen siendo familiares a sus contrapartes de PHP.

Sentencias If

Puedes construir declaraciones if usando las directivas @if, @elseif, @else y @endif. Estas directivas funcionan de manera idéntica a sus contrapartes en PHP:

@if (count($records) === 1)
¡Tengo un registro!
@elseif (count($records) > 1)
¡Tengo varios registros!
@else
¡No tengo ningún registro!
@endif

Para mayor comodidad, Blade también proporciona una directiva @unless:

@unless (Auth::check())
No has iniciado sesión.
@endunless

Además de las directivas condicionales ya mencionadas, las directivas @isset y @empty se pueden usar como atajos convenientes para sus respectivas funciones de PHP:

@isset($records)
// $records está definido y no es nulo...
@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
// El usuario está autenticado...
@endauth
 
@guest
// El usuario no está autenticado...
@endguest

Si es necesario, puedes especificar la guarda de autenticación que se debe verificar al usar las directivas @auth y @guest:

@auth('admin')
// El usuario está autenticado...
@endauth
 
@guest('admin')
// El usuario no está autenticado...
@endguest

Directivas de Entorno

Puedes verificar si la aplicación se está ejecutando en el entorno de producción mediante la directiva @production:

@production
// Contenido específico de producción...
@endproduction

O puedes determinar si la aplicación se está ejecutando en un entorno específico mediante la directiva @env:

@env('staging')
// La aplicación se está ejecutando en "staging"...
@endenv
 
@env(['staging', 'production'])
// La aplicación se está ejecutando en "staging" o "production"...
@endenv

Directivas de Sección

Puedes determinar si una sección de herencia de plantillas tiene contenido usando 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

Sentencias Switch

Las declaraciones switch se pueden construir mediante las directivas @switch, @case, @break, @default y @endswitch:

@switch($i)
@case(1)
Primer caso...
@break
 
@case(2)
Segundo caso...
@break
 
@default
Caso predeterminado...
@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++)
El valor actual es {{ $i }}
@endfor
 
@foreach ($users as $user)
<p>Este es el usuario {{ $user->id }}</p>
@endforeach
 
@forelse ($users as $user)
<li>{{ $user->name }}</li>
@empty
<p>Ningún usuario</p>
@endforelse
 
@while (true)
<p>Estoy haciendo un bucle infinito.</p>
@endwhile

Nota Mientras iteras a través de un bucle foreach, puedes usar la variable del bucle para obtener información valiosa sobre el bucle, como si estás en la primera o última iteración a través del bucle.

Cuando usas bucles, también puedes omitir la iteración actual o finalizar el bucle usando 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 del Bucle

Mientras iteras a través de un bucle foreach, una variable $loop estará disponible dentro de tu bucle. Esta variable proporciona acceso a información útil 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)
Esta es la primera iteración.
@endif
 
@if ($loop->last)
Esta es la última iteración.
@endif
 
<p>Este es el usuario {{ $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)
Esta es la primera iteración del bucle principal.
@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 la matriz 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 anidamiento del bucle actual.
$loop->parent Cuando estás en un bucle anidado, la variable de 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 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:

@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>

Asimismo, la directiva @style se puede utilizar para agregar 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 un checkbox de entrada HTML dado está "checked". Esta directiva imprimirá checked si la condición proporcionada se evalúa como true:

<input type="checkbox"
name="active"
value="active"
@checked(old('active', $user->active)) />

De manera similar, la directiva @selected se puede utilizar para indicar si una opción de selección debe estar "selected":

<select name="version">
@foreach ($product->versions as $version)
<option value="{{ $version }}" @selected(old('version') == $version)>
{{ $version }}
</option>
@endforeach
</select>

Además, la directiva @disabled se puede utilizar para indicar si un elemento dado debe estar "disabled":

<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>

Además, la directiva @readonly se puede utilizar para indicar si un elemento dado debe estar "readonly":

<input type="email"
name="email"
@readonly($user->isNotAdmin()) />

Además, la directiva @required se puede utilizar para indicar si un elemento dado debe estar "required":

<input type="text"
name="title"
value="title"
@required($user->isAdmin()) />

Inclusión de Subvistas

Nota Aunque eres libre de usar la directiva @include, los componentes de Blade ofrecen funcionalidad similar y brindan varias ventajas 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 disponibles para la vista principal 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 array de datos adicionales que se deben poner a disposición de 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 estar presente o no, debes usar la directiva @includeIf:

@includeIf('view.name', ['status' => 'complete'])

Si deseas @include una vista si una expresión booleana dada se evalúa como 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 de un conjunto dado de vistas, puedes usar la directiva includeFirst:

@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])

Advertencia Debes evitar el uso de las constantes __DIR__ y __FILE__ en tus vistas de Blade, ya que se referirán a la ubicación de la vista compilada y en caché.

Renderizado de Vistas para Colecciones

Puedes combinar bucles e inclusiones en una sola línea con la directiva @each de Blade:

@each('view.name', $jobs, 'job')

El primer argumento de la directiva @each es la vista que se va a renderizar para cada elemento en el array o colección. El segundo argumento es el array o colección que deseas recorrer, mientras que el tercer argumento es el nombre de la variable que se asignará a la iteración actual dentro de la vista. Entonces, 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')

Advertencia Las vistas renderizadas mediante @each no heredan las variables de la vista principal. Si la vista secundaria requiere estas variables, debes utilizar las directivas @foreach y @include en su lugar.

La Directiva @once

La directiva @once te permite definir una parte de la plantilla que solo se evaluará una vez por ciclo de renderizado. Esto puede ser útil para insertar una determinada pieza de JavaScript en el encabezado de la página usando stacks. Por ejemplo, si estás renderizando un componente específico dentro de un bucle, es posible que desees empujar el JavaScript al encabezado solo la primera vez que se renderiza el componente:

@once
@push('scripts')
<script>
// Tu JavaScript personalizado...
</script>
@endpush
@endonce

Dado que la directiva @once se usa a menudo en conjunción con las directivas @push o @prepend, las directivas @pushOnce y @prependOnce están disponibles para tu conveniencia:

@pushOnce('scripts')
<script>
// Tu JavaScript personalizado...
</script>
@endPushOnce

PHP Sin Procesar

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 simple dentro de tu plantilla:

@php
$counter = 1;
@endphp

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:

{{-- Este comentario no estará presente en el HTML renderizado --}}

Componentes

Los componentes y slots brindan beneficios similares a las secciones, layouts e inclusiones; sin embargo, algunos pueden encontrar que el modelo mental de componentes y slots es 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 clases, puedes usar el comando Artisan make:component. Para ilustrar cómo usar componentes, crearemos un componente simple llamado 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. Cuando escribes 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 generalmente no se requiere más registro 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 solo con una plantilla de Blade y sin clase), puedes usar la bandera --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 />.

Registro Manual de Componentes de Paquete

Cuando escribes componentes para tu propia aplicación, los componentes se descubren automáticamente dentro del directorio app/View/Components y el directorio resources/views/components.

Sin embargo, si estás construyendo un paquete que utiliza componentes de Blade, deberás registrar manualmente la clase de tu componente y su alias de etiqueta HTML. Por lo general, debes registrar tus componentes en el método boot del proveedor de servicios de tu paquete:

use Illuminate\Support\Facades\Blade;
 
/**
* Inicializa los servicios de tu paquete.
*/
public function boot(): void
{
Blade::component('package-alert', Alert::class);
}

Una vez que tu componente ha sido registrado, se puede renderizar utilizando su alias de etiqueta:

<x-package-alert/>

Alternativamente, puedes usar el método componentNamespace para cargar automáticamente las 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;
 
/**
* Inicializa los servicios de tu paquete.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

Esto permitirá el uso de componentes de paquete por su espacio de nombres de proveedor utilizando la sintaxis nombre-paquete:::

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade detectará automáticamente la clase vinculada a este componente poniendo la primera letra en mayúscula. Los subdirectorios también son compatibles utilizando la notación "punto".

Renderizado de Componentes

Para mostrar un componente, puedes usar una etiqueta de componente de Blade dentro de una de tus plantillas de Blade. Las etiquetas de componente de 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 está ubicado en app/View/Components/Inputs/Button.php, podemos renderizarlo así:

<x-inputs.button/>

Si deseas renderizar tu componente de forma condicional, puedes definir un método shouldRender en la clase de tu componente. Si el método shouldRender devuelve false, el componente no se renderizará:

use Illuminate\Support\Str;
 
/**
* Determina si el componente debe renderizarse.
*/
public function shouldRender(): bool
{
return Str::length($this->message) > 0;
}

Pasar Datos a Componentes

Puedes pasar datos a los componentes de Blade usando atributos HTML. Los valores primitivos codificados se pueden pasar al componente mediante cadenas de atributos HTML simples. Las expresiones y variables de PHP deben pasarse al componente a través de atributos que usan el carácter : como prefijo:

<x-alert type="error" :message="$message"/>

Debes definir todos los atributos de datos del componente en el constructor de su clase. Todas las propiedades públicas en un componente se pondrán automáticamente a disposición de 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
{
/**
* Crea la instancia del componente.
*/
public function __construct(
public string $type,
public string $message,
) {}
 
/**
* Obtiene la vista o el contenido que representa el componente.
*/
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 un echo de las variables por nombre:

<div class="alert alert-{{ $type }}">
{{ $message }}
</div>

Mayúsculas

Los argumentos del constructor del componente deben especificarse utilizando camelCase, mientras que kebab-case se debe usar al hacer referencia a los nombres de argumento en tus atributos HTML. Por ejemplo, dado el siguiente constructor de componente:

/**
* Crea la instancia del componente.
*/
public function __construct(
public string $alertType,
) {}

El argumento $alertType se puede proporcionar al componente de la siguiente manera:

<x-alert alert-type="danger" />

Sintaxis Corta de Atributos

Al pasar atributos a componentes, también puedes usar una sintaxis de "atributo corto". Esto es 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" />

Renderizado de Atributos de Escapado

Dado que algunos marcos de JavaScript, como Alpine.js, también utilizan atributos con dos puntos como prefijo, puedes usar un doble dos puntos (::) como prefijo para informar a Blade que el atributo no es una expresión de PHP. Por ejemplo, dada el siguiente componente:

<x-button ::class="{ danger: isDeleting }">
Submit
</x-button>

El siguiente HTML se renderizará con Blade:

<button :class="{ danger: isDeleting }">
Submit
</button>

Métodos de Componentes

Además de que las variables públicas estén disponibles para la plantilla de tu componente, también se pueden invocar cualquier método público en el componente. Por ejemplo, imagina un componente que tiene un método isSelected:

/**
* Determina si la opción dada es la opción actualmente seleccionada.
*/
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>

Acceso a Atributos y Slots Dentro de Clases de Componentes

Los componentes de Blade también te permiten acceder al nombre del componente, a los atributos y al slot dentro del método render de la clase. Sin embargo, para acceder a estos datos, debes devolver un cierre desde el método render de tu componente. El cierre recibirá un array $data como su único argumento. Este array contendrá varios elementos que proporcionan información sobre el componente:

use Closure;
 
/**
* Obtiene la vista o el contenido que representa el componente.
*/
public function render(): Closure
{
return function (array $data) {
// $data['componentName'];
// $data['attributes'];
// $data['slot'];
 
return 'modify_10x/blade.return_text_856';
};
}

El componentName es igual al nombre utilizado en la etiqueta HTML después del prefijo x-. Entonces, el componentName de <x-alert /> será alert. El elemento attributes contendrá todos los atributos que estaban presentes en la etiqueta HTML. El elemento slot es una instancia de Illuminate\Support\HtmlString con el contenido del slot del componente.

El cierre 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 enumerarlas antes que cualquiera de los atributos de datos del componente y se inyectarán automáticamente mediante el contenedor:

use App\Services\AlertCreator;
 
/**
* Crea la instancia del componente.
*/
public function __construct(
public AlertCreator $creator,
public string $type,
public string $message,
) {}

Ocultar Atributos / Métodos

Si deseas evitar que algunos métodos o propiedades públicas se expongan como variables en la plantilla de tu componente, puedes agregarlos a una propiedad de array $except en tu componente:

<?php
 
namespace App\View\Components;
 
use Illuminate\View\Component;
 
class Alert extends Component
{
/**
* Las propiedades / métodos que no deben exponerse en la plantilla del componente.
*
* @var array
*/
protected $except = ['type'];
 
/**
* Crea la instancia del componente.
*/
public function __construct(
public string $type,
) {}
}

Atributos de Componentes

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 forman parte de los datos necesarios para que funcione un componente. Normalmente, deseas pasar estos atributos adicionales hacia abajo al elemento raíz de la plantilla del componente. Por ejemplo, imagina que quieres renderizar un componente alert de la siguiente manera:

<x-alert type="error" :message="$message" class="mt-4"/>

Todos los atributos que no forman parte del constructor del componente se agregarán automáticamente a la "bolsa de atributos" del componente. Esta bolsa de atributos está automáticamente disponible para el componente a través de la variable $attributes. Todos los atributos se pueden renderizar dentro del componente haciendo un echo de esta variable:

<div {{ $attributes }}>
<!-- Component content -->
</div>

Advertencia En este momento, no se admite el uso de directivas como @env dentro de las etiquetas de los componentes. Por ejemplo, <x-alert :live=\"@env('production')\"/> no se compilará.

Atributos Predeterminados / Fusionados

A veces es posible que necesites especificar valores predeterminados para atributos o combinar 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 particularmente útil para definir un conjunto de clases CSS predeterminadas que siempre se deben aplicar a un componente:

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
{{ $message }}
</div>

Si asumimos que este componente se utiliza de la siguiente manera:

<x-alert type="error" :message="$message" class="mb-4"/>

El HTML final, renderizado del componente, aparecerá de la siguiente manera:

<div class="alert alert-error mb-4">
<!-- Contenido de la variable $message -->
</div>

Fusión Condicional de Clases

A veces puede ser necesario combinar clases si una condición dada es true. Puedes lograr esto mediante el método class, que acepta un array de clases donde la clave del array contiene la clase o 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 condicionalmente clases en otros elementos HTML que no deben recibir atributos fusionados, puedes usar la directiva @class.

Fusión No Clase de Atributos

Cuando combines 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 combinarán con los valores de atributos inyectados. En su lugar, serán sobrescritos. Por ejemplo, la implementación de un componente button podría ser así:

<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 usará 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 distinto de class tenga su valor predeterminado y los valores inyectados se unan, puedes usar el método prepends. En este ejemplo, el atributo data-controller siempre comenzará con profile-controller y cualquier valor adicional inyectado de data-controller se colocará después de este valor predeterminado:

<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}>
{{ $slot }}
</div>

Recuperación y Filtrado de Atributos

Puedes filtrar atributos usando el método filter. Este método acepta un cierre que debe devolver true si deseas retener el atributo en la bolsa de atributos:

{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}

Por conveniencia, puedes usar el método whereStartsWith para recuperar todos los atributos cuyas claves comienzan con una cadena dada:

{{ $attributes->whereStartsWith('wire:model') }}

Conversamente, el método whereDoesntStartWith se puede utilizar para excluir todos los atributos cuyas claves comienzan con una cadena dada:

{{ $attributes->whereDoesntStartWith('wire:model') }}

Usando el método first, puedes renderizar el primer atributo en una bolsa de atributos dada:

{{ $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>El atributo de clase está presente</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>Todos los atributos están presentes</div>
@endif

El método hasAny se puede utilizar para determinar si alguno de los atributos dados está presente en el componente:

@if ($attributes->hasAny(['href', ':href', 'v-bind:href']))
<div>Uno de los atributos está presente</div>
@endif

Puedes recuperar el valor de un atributo específico usando 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 se pueden definir 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 de componente se representan haciendo un eco de 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>¡Vaya!</strong> Algo salió mal.
</x-alert>

A veces, un componente puede necesitar renderizar múltiples slots diferentes en diferentes ubicaciones dentro del componente. Modifiquemos nuestro componente de alerta para permitir la inyección de un slot 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 usando 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>¡Vaya!</strong> Algo salió mal.
</x-alert>

Slots con Ámbito

Si has utilizado un marco de trabajo de JavaScript como Vue, es posible que estés familiarizado con los "scoped slots", que te permiten acceder a datos o métodos desde el componente dentro de tu slot. Puedes lograr un comportamiento similar en Laravel definiendo métodos o propiedades públicas 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('Error del servidor') }}
</x-slot>
 
<strong>¡Vaya!</strong> Algo salió mal.
</x-alert>

Atributos de Slots

Al igual que los componentes de Blade, puedes asignar atributos adicionales a los slots, como nombres de clases CSS:

<x-card class="shadow-sm">
<x-slot:heading class="font-bold">
Encabezado
</x-slot>
 
Contenido
 
<x-slot:footer class="text-sm">
Pie de página
</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 en Línea de Componentes

Para componentes muy pequeños, puede sentirse engorroso administrar 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:

/**
* Obtiene la vista o el contenido que representa el componente.
*/
public function render(): string
{
return <<<'blade'
<div class="alert alert-danger">
{{ $slot }}
</div>
blade;
}

Generación de Componentes de Vista en Línea

Para crear un componente que represente 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 necesitarás renderizar un componente pero no sabrás qué componente se debe renderizar hasta en tiempo de ejecución. En esta situación, puedes usar el componente incorporado de Laravel dynamic-component 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" />

Registro Manual de Componentes

Advertencia La siguiente documentación sobre el registro manual de componentes es principalmente aplicable a aquellos que están escribiendo paquetes de Laravel que incluyen componentes de vista. Si no estás escribiendo un paquete, esta parte de la documentación de componentes puede no ser relevante para ti.

Cuando escribes componentes para tu propia aplicación, los componentes se descubren automáticamente dentro del directorio app/View/Components y el directorio resources/views/components.

Sin embargo, si estás construyendo un paquete que utiliza componentes de Blade o colocando componentes en directorios no convencionales, deberás registrar manualmente la clase de tu componente y su alias de etiqueta HTML para que Laravel sepa dónde encontrar el componente. Por lo general, debes registrar tus componentes en el método boot del proveedor de servicios de tu paquete:

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;
 
/**
* Inicializa los servicios de tu paquete.
*/
public function boot(): void
{
Blade::component('package-alert', AlertComponent::class);
}

Una vez que tu componente haya sido registrado, se puede renderizar usando su alias de etiqueta:

<x-package-alert/>

Autocarga de Componentes de Paquete

Alternativamente, puedes usar el método componentNamespace para cargar automáticamente las clases de componentes por convención. Por ejemplo, un paquete Nightshade podría tener componentes Calendar y ColorPicker que residen en el espacio de nombres Package\Views\Components:

use Illuminate\Support\Facades\Blade;
 
/**
* Inicializa los servicios de tu paquete.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

Esto permitirá el uso de componentes de paquetes mediante su espacio de nombres de proveedor utilizando la sintaxis package-name:::

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade detectará automáticamente la clase vinculada a este componente utilizando pascal-case en el nombre del componente. Los subdirectorios también son compatibles utilizando la notación "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 de Blade dentro de tu directorio resources/views/components. Por ejemplo, asumiendo que has definido un componente en resources/views/components/alert.blade.php, simplemente puedes renderizarlo así:

<x-alert/>

Puedes usar el carácter . para indicar si un componente está anidado más profundamente dentro del directorio components. Por ejemplo, suponiendo que el componente está definido en resources/views/components/inputs/button.blade.php, puedes renderizarlo así:

<x-inputs.button/>

Componentes Anónimos de Índice

A veces, cuando un componente está compuesto por muchas plantillas de Blade, es posible que desees agrupar las plantillas dadas del componente 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 directorio te permite renderizar el componente de acordeón y su ítem de la siguiente manera:

<x-accordion>
<x-accordion.item>
...
</x-accordion.item>
</x-accordion>

Sin embargo, para 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 anidarla 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 "raíz" del componente. Así que podemos seguir usando 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 de Datos / Atributos

Dado que los componentes anónimos no tienen ninguna clase asociada, puede que te preguntes cómo 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 de Blade de tu componente. Todos los demás atributos en el componente estarán disponibles a través de la bolsa de atributos del componente. Si deseas asignar un valor predeterminado a una variable de datos, 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"/>

Acceso a Datos Padres

A veces, es posible que desees acceder a datos de un componente principal dentro de un componente secundario. En estos casos, puedes usar la directiva @aware. Por ejemplo, imagina que estás construyendo un componente de menú complejo que consta de un componente principal <x-menu> y un componente secundario <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>

Dado que el atributo color solo se pasó al componente principal (<x-menu>), no estará disponible dentro de <x-menu.item>. Sin embargo, si usamos la directiva @aware, podemos hacer que esté disponible también dentro de <x-menu.item>:

<!-- /resources/views/components/menu/item.blade.php -->
 
@aware(['color' => 'gray'])
 
<li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>
{{ $slot }}
</li>

Advertencia La directiva @aware no puede acceder a datos padres que no se pasan explícitamente al componente padre a través de atributos HTML. Los valores predeterminados de @props que no se pasan explícitamente al componente padre no pueden ser accedidos por la directiva @aware.

Rutas de Componentes Anónimos

Como se discutió anteriormente, los componentes anónimos generalmente se definen colocando una plantilla de Blade dentro de tu directorio resources/views/components. Sin embargo, ocasionalmente querrás registrar 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:

/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::anonymousComponentPath(__DIR__.'/../components');
}

Cuando las rutas de los componentes se registran sin un prefijo especificado como en el ejemplo anterior, también se pueden renderizar en tus componentes de Blade sin un prefijo correspondiente. Por ejemplo, si existe un componente panel.blade.php en la ruta registrada anteriormente, se puede renderizar así:

<x-panel />

Los "espacios de nombres" de prefijo se pueden proporcionar 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 renderizarse prefiriendo el espacio de nombres del componente al nombre del componente cuando se renderiza el componente:

<x-dashboard::panel />

Construcción de Diseños

Diseños con 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 de 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.

Definición del Componente de Diseño

Por ejemplo, imagina que estamos construyendo una aplicación de lista de tareas. Podríamos definir un componente layout que se ve así:

<!-- resources/views/components/layout.blade.php -->
 
<html>
<head>
<title>{{ $title ?? 'Gestor de tareas pendientes' }}</title>
</head>
<body>
<h1>Tarea pendiente</h1>
<hr/>
{{ $slot }}
</body>
</html>

Aplicación del Componente de Diseño

Una vez que se ha definido el componente layout, podemos crear una vista de 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)
{{ $task }}
@endforeach
</x-layout>

Recuerda que el contenido que se inyecta en un componente se suministrará al variable $slot predeterminado dentro de nuestro componente layout. Como habrás notado, nuestro layout también respeta un espacio $title si se proporciona; de lo contrario, se muestra un título predeterminado. Podemos inyectar un título personalizado desde nuestra vista de lista de tareas usando la sintaxis de ranura estándar discutida en la documentación de componentes:

<!-- resources/views/tasks.blade.php -->
 
<x-layout>
<x-slot:title>
Título personalizado
</x-slot>
 
@foreach ($tasks as $task)
{{ $task }}
@endforeach
</x-layout>

Ahora que hemos definido nuestro diseño y vistas de 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 con Herencia de Plantillas

Definición de un Diseño

Los diseños también se pueden crear mediante "herencia de plantillas". Esta fue la forma principal de construir aplicaciones antes de la introducción de componentes.

Para empezar, veamos 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 única vista de Blade:

<!-- resources/views/layouts/app.blade.php -->
 
<html>
<head>
<title>Nombre de la aplicación - @yield('title')</title>
</head>
<body>
@section('sidebar')
Este es la barra lateral principal.
@show
 
<div class="container">
@yield('content')
</div>
</body>
</html>

Como puedes ver, este archivo contiene marcas HTML típicas. Sin embargo, ten en cuenta 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 secundaria que herede el diseño.

Extensión de un Diseño

Al definir una vista secundaria, utiliza la directiva de Blade @extends para especificar qué diseño debe "heredar" la vista secundaria. Las vistas que extienden un diseño de Blade pueden inyectar contenido en las secciones del diseño mediante directivas @section. Recuerda, como se ve en el ejemplo anterior, el contenido de estas secciones se mostrará en el diseño mediante @yield:

<!-- resources/views/child.blade.php -->
 
@extends('layouts.app')
 
@section('title', 'Page Title')
 
@section('sidebar')
@parent
 
<p>Esto se añadirá a la barra lateral principal.</p>
@endsection
 
@section('content')
<p>Este es el contenido de mi cuerpo.</p>
@endsection

En este ejemplo, la sección sidebar utiliza la directiva @parent para agregar (en lugar de sobrescribir) contenido a la barra lateral del diseño. La directiva @parent se reemplazará 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 rendirá 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 está indefinida:

@yield('content', 'Contenido predeterminado')

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 de Blade @csrf para generar el campo de token:

<form method="POST" action="/profile">
@csrf
 
...
</form>

Campo de Método

Dado que los formularios HTML no pueden realizar solicitudes PUT, PATCH o DELETE, deberás agregar un campo oculto _method para simular estos verbos HTTP. La directiva de Blade @method 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 imprimir la variable $message para mostrar el mensaje de error:

<!-- /resources/views/post/create.blade.php -->
 
<label for="title">Título de la publicación</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">Dirección de correo electrónico</label>
 
<input id="email"
type="email"
class="@error('email') is-invalid @else is-valid @enderror">

Puedes pasar el nombre de una bolsa de errores específica 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">Dirección de correo electrónico</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 agregar a pilas con nombres que se pueden renderizar en otro lugar, 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 se evalúa como true, puedes usar la directiva @pushIf:

@pushIf($shouldPush, 'scripts')
<script src="/example.js"></script>
@endPushIf

Puedes agregar contenido a una pila tantas veces como sea necesario. Para renderizar el contenido completo de la pila, pasa el nombre de la pila a la directiva @stack:

<head>
<!-- Contenidos de la cabeza -->
 
@stack('scripts')
</head>

Si deseas agregar contenido al principio de una pila, debes usar la directiva @prepend:

@push('scripts')
Esto será segundo...
@endpush
 
// Esto será primero...
 
@prepend('scripts')
Esto será primero...
@endprepend

Inyección de Servicios

La directiva @inject se puede utilizar 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 la clase o nombre de interfaz del servicio que deseas resolver:

@inject('metrics', 'App\Services\MetricsService')
 
<div>
Ingresos mensuales:: {{ $metrics->monthlyRevenue() }}.
</div>

Renderizado de Plantillas Blade en Línea

A veces, es posible que necesites transformar una cadena de plantilla Blade sin procesar en HTML válido. Puedes lograr esto usando el método render proporcionado por el facade 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('Hola, {{ $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(
'Hola, {{ $name }}',
['name' => 'Julian Bashir'],
deleteCachedView: true
);

Renderizado de Fragmentos Blade

Cuando usas frameworks frontend como Turbo y htmx, a veces necesitarás devolver solo una parte de una plantilla Blade en tu respuesta HTTP. Los "fragmentos" de Blade te permiten hacer precisamente eso. Para empezar, coloca una parte 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

Luego, 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 según 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 varios 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']
);

Extensión de Blade

Blade te permite definir tus propias directivas personalizadas mediante el método directive. Cuando el compilador 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 una directiva @datetime($var) que formatea un $var dado, que debería ser una instancia de DateTime:

<?php
 
namespace App\Providers;
 
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
/**
* Registra cualquier servicio de la aplicación.
*/
public function register(): void
{
// ...
}
 
/**
* Inicializa cualquier servicio de la aplicación.
*/
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 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'); ?>

Advertencia Después de actualizar la lógica de una directiva de Blade, deberás eliminar todas las vistas de Blade en caché. Las vistas de Blade en caché se pueden eliminar utilizando el comando view:clear de Artisan.

Manejadores de Eco Personalizados

Si intentas "hacer eco" de un objeto usando 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 es posible que no tengas control sobre el método __toString de una clase determinada, 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 echo personalizado para ese tipo particular de objeto. Para lograr esto, debes invocar el método stringable de Blade. El método stringable acepta un cierre. Este cierre debe hacer una sugerencia de tipo del tipo de objeto del que es responsable de renderizar. Normalmente, 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;
 
/**
* Inicializa cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::stringable(function (Money $money) {
return $money->formatTo('en_GB');
});
}

Programar una directiva personalizada a veces es más complejo de lo necesario al definir declaraciones condicionales personalizadas simples. Por esa razón, Blade proporciona un método Blade::if que te permite definir rápidamente directivas condicionales personalizadas utilizando cierres. Por ejemplo, definamos una condición personalizada que verifique el "disco" predeterminado configurado para la aplicación. Podemos hacer esto en el método boot de nuestro AppServiceProvider:

Cost: {{ $money }}

Sentencias If Personalizadas

Programar una directiva personalizada a veces es más complejo de lo necesario al definir declaraciones condicionales simples. Por esa razón, Blade proporciona un método Blade::if que te permite definir rápidamente directivas condicionales personalizadas mediante cierres. Por ejemplo, veamos cómo definir una condición personalizada que verifica el "disco" predeterminado configurado para la aplicación. Podemos hacer esto en el método boot de nuestro AppServiceProvider:

use Illuminate\Support\Facades\Blade;
 
/**
* Inicializa cualquier servicio de la aplicación.
*/
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 en tus plantillas:

@disk('local')
<!-- La aplicación está utilizando el disco local... -->
@elsedisk('s3')
<!-- La aplicación está utilizando el disco s3... -->
@else
<!-- La aplicación está utilizando algún otro disco... -->
@enddisk
 
@unlessdisk('local')
<!-- La aplicación no está utilizando el disco local... -->
@enddisk