- Introducción
- Mostrando Datos
- Directivas Blade
- Componentes
- Componentes Anónimos
- Construyendo Layouts
- Formularios
- Stacks
- Inyección de Servicios
- Renderizando Plantillas Blade Inline
- Renderizando Fragmentos Blade
- Extendiendo Blade
#Introducción
Blade es el motor de plantillas simple pero potente que viene incluido con Laravel. A diferencia de algunos motores de plantillas PHP, Blade no le impide usar código PHP puro en sus plantillas. De hecho, todas las plantillas Blade se compilan en código PHP plano y se almacenan en caché hasta que se modifican, lo que significa que Blade añade prácticamente cero sobrecarga a su aplicación. Los archivos de plantilla Blade usan la extensión .blade.php y normalmente se almacenan en el directorio resources/views.
Las vistas Blade pueden ser retornadas desde rutas o controladores usando el helper global view. Por supuesto, como se menciona en la documentación sobre vistas, se pueden pasar datos a la vista Blade usando el segundo argumento del helper view:
Route::get('/', function () {
return view('greeting', ['name' => 'Finn']);
});
#Potenciando Blade con Livewire
¿Quiere llevar sus plantillas Blade al siguiente nivel y construir interfaces dinámicas con facilidad? Consulte Laravel Livewire. Livewire le permite escribir componentes Blade que se enriquecen con funcionalidad dinámica que normalmente solo sería posible mediante frameworks frontend como React o Vue, proporcionando un enfoque excelente para construir frontends modernos y reactivos sin las complejidades, renderizado del lado cliente o pasos de compilación de muchos frameworks JavaScript.
#Mostrando Datos
Puede mostrar datos que se pasan a sus vistas Blade envolviendo la variable entre llaves. Por ejemplo, dada la siguiente ruta:
Route::get('/', function () {
return view('welcome', ['name' => 'Samantha']);
});
Puede mostrar el contenido de la variable name así:
Hello, {{ $name }}.
Las sentencias de echo {{ }} de Blade se envían automáticamente a través de la función htmlspecialchars de PHP para prevenir ataques XSS.
No está limitado a mostrar solo el contenido de las variables pasadas a la vista. También puede hacer echo de los resultados de cualquier función PHP. De hecho, puede poner cualquier código PHP que desee dentro de una sentencia echo de Blade:
The current UNIX timestamp is {{ time() }}.
#Codificación de Entidades HTML
Por defecto, Blade (y la función e de Laravel) codifican doblemente las entidades HTML. Si desea desactivar la codificación doble, llame al método Blade::withoutDoubleEncoding desde el método boot de su AppServiceProvider:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::withoutDoubleEncoding();
}
}
#Mostrando Datos Sin Escapar
Por defecto, las sentencias Blade {{ }} se envían automáticamente a través de la función htmlspecialchars de PHP para prevenir ataques XSS. Si no desea que sus datos sean escapados, puede usar la siguiente sintaxis:
Hello, {!! $name !!}.
Tenga mucho cuidado al hacer echo de contenido suministrado por los usuarios de su aplicación. Normalmente debería usar la sintaxis escapada con doble llave para prevenir ataques XSS al mostrar datos proporcionados por usuarios.
#Blade y Frameworks de JavaScript
Dado que muchos frameworks de JavaScript también usan llaves "rizadas" para indicar que una expresión debe mostrarse en el navegador, puede usar el símbolo @ para informar al motor de renderizado Blade que una expresión debe permanecer intacta. 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 para que pueda ser renderizada por su framework de JavaScript.
El símbolo @ también puede usarse para escapar directivas Blade:
{{-- Plantilla Blade --}}
@@if()
<!-- Salida HTML -->
@if()
#Renderizando JSON
A veces puede pasar un array a su vista con la intención de renderizarlo como JSON para inicializar una variable JavaScript. Por ejemplo:
<script>
var app = <?php echo json_encode($array); ?>;
</script>
Sin embargo, en lugar de llamar manualmente a json_encode, puede 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, asegura que el JSON resultante esté correctamente escapado para su inclusión dentro de comillas HTML. El método from devolverá una cadena con una sentencia 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 últimas versiones del esqueleto de aplicación Laravel incluyen una fachada Js, que proporciona acceso conveniente a esta funcionalidad dentro de sus plantillas Blade:
<script>
var app = {{ Js::from($array) }};
</script>
Solo debe usar el método Js::from para renderizar variables existentes como JSON. El motor de plantillas Blade está basado en expresiones regulares y tratar de pasar una expresión compleja a la directiva puede causar fallos inesperados.
#La Directiva @verbatim
Si está mostrando variables JavaScript en una gran parte de su plantilla, puede envolver el HTML en la directiva @verbatim para no tener que prefijar cada sentencia echo de Blade con un símbolo @:
@verbatim
<div class="container">
Hello, {{ name }}.
</div>
@endverbatim
#Directivas Blade
Además de la herencia de plantillas y mostrar datos, Blade también proporciona atajos convenientes para estructuras comunes de control PHP, como sentencias condicionales y bucles. Estos atajos ofrecen una forma muy limpia y concisa de trabajar con estructuras de control PHP, manteniéndose familiares para quienes conocen PHP.
#Sentencias If
Puede construir sentencias if usando las directivas @if, @elseif, @else y @endif. Estas directivas funcionan idénticamente 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
Para mayor comodidad, Blade también proporciona una directiva @unless:
@unless (Auth::check())
You are not signed in.
@endunless
Además de las directivas condicionales ya mencionadas, las directivas @isset y @empty pueden usarse como atajos convenientes para sus respectivas funciones PHP:
@isset($records)
// $records está definido y no es null...
@endisset
@empty($records)
// $records está "vacío"...
@endempty
#Directivas de Autenticación
Las directivas @auth y @guest pueden usarse 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, puede especificar el guard de autenticación que debe verificarse 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
Puede verificar si la aplicación se está ejecutando en el entorno de producción usando la directiva @production:
@production
// Contenido específico para producción...
@endproduction
O puede determinar si la aplicación se está ejecutando en un entorno específico usando 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
Puede determinar si una sección de herencia de plantilla tiene contenido usando la directiva @hasSection:
@hasSection('navigation')
<div class="pull-right">
@yield('navigation')
</div>
<div class="clearfix"></div>
@endif
Puede 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 puede usarse para determinar si existe un valor de sesión. Si el valor de sesión existe, el contenido de la plantilla dentro de las directivas @session y @endsession será evaluado. Dentro del contenido de la directiva @session, puede hacer echo de la variable $value para mostrar el valor de la sesión:
@session('status')
<div class="p-4 bg-green-100">
{{ $value }}
</div>
@endsession
#Sentencias Switch
Las sentencias switch pueden construirse usando las directivas @switch, @case, @break, @default y @endswitch:
@switch($i)
@case(1)
First case...
@break
@case(2)
Second case...
@break
@default
Default case...
@endswitch
#Bucles
Además de las sentencias condicionales, Blade proporciona directivas simples para trabajar con las estructuras de bucle de PHP. Nuevamente, cada una de estas directivas funciona idénticamente a sus contrapartes en 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
Mientras itera a través de un bucle foreach, puede usar la variable loop para obtener información valiosa sobre el bucle, como si está en la primera o última iteración.
Al usar bucles también puede saltar la iteración actual o terminar 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 puede incluir la condición de continuación o 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 Loop
Mientras itera a través de un bucle foreach, una variable $loop estará disponible dentro de su 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:
@foreach ($users as $user)
@if ($loop->first)
This is the first iteration.
@endif
@if ($loop->last)
This is the last iteration.
@endif
<p>This is user {{ $user->id }}</p>
@endforeach
Si está en un bucle anidado, puede 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 itera. |
$loop->first |
Si esta es la primera iteración del bucle. |
$loop->last |
Si esta es la última iteración del bucle. |
$loop->even |
Si esta es una iteración par del bucle. |
$loop->odd |
Si esta es una iteración impar del bucle. |
$loop->depth |
El nivel de anidamiento del bucle actual. |
$loop->parent |
Cuando está en un bucle anidado, la variable del bucle 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 desea 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>
De igual forma, la directiva @style puede usarse para agregar condicionalmente estilos CSS inline 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, puede usar la directiva @checked para indicar fácilmente si un input checkbox HTML dado está "checked". Esta directiva hará echo de checked si la condición proporcionada evalúa a true:
<input type="checkbox"
name="active"
value="active"
@checked(old('active', $user->active)) />
De igual forma, la directiva @selected puede usarse para indicar si una opción select dada 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 puede usarse para indicar si un elemento dado debe estar "disabled":
<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>
Asimismo, la directiva @readonly puede usarse para indicar si un elemento dado debe estar "readonly":
<input type="email"
name="email"
value="email@laravel.com"
@readonly($user->isNotAdmin()) />
Además, la directiva @required puede usarse para indicar si un elemento dado debe estar "required":
<input type="text"
name="title"
value="title"
@required($user->isAdmin()) />
#Incluyendo Subvistas
Aunque puede usar la directiva @include, los componentes de Blade ofrecen funcionalidad similar y proporcionan varias ventajas sobre la directiva @include, como el enlace de datos y atributos.
La directiva @include de Blade le permite incluir una vista Blade dentro de otra vista. Todas las variables disponibles para la vista padre estarán disponibles para la vista incluida:
<div>
@include('shared.errors')
<form>
<!-- Contenido del formulario -->
</form>
</div>
Aunque la vista incluida heredará todos los datos disponibles en la vista padre, también puede pasar un array de datos adicionales que deberían estar disponibles para la vista incluida:
@include('view.name', ['status' => 'complete'])
Si intenta @include una vista que no existe, Laravel lanzará un error. Si desea incluir una vista que puede o no estar presente, debe usar la directiva @includeIf:
@includeIf('view.name', ['status' => 'complete'])
Si desea @include una vista si una expresión booleana dada evalúa a true o false, puede usar las directivas @includeWhen y @includeUnless:
@includeWhen($boolean, 'view.name', ['status' => 'complete'])
@includeUnless($boolean, 'view.name', ['status' => 'complete'])
Para incluir la primera vista que exista de un array dado de vistas, puede usar la directiva includeFirst:
@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])
Debe evitar usar las constantes __DIR__ y __FILE__ en sus vistas Blade, ya que se referirán a la ubicación de la vista compilada en caché.
#Renderizando Vistas para Colecciones
Puede combinar bucles e includes 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 renderizará para cada elemento en el array o colección. El segundo argumento es el array o colección que desea iterar, mientras que el tercer argumento es el nombre de la variable que se asignará a la iteración actual dentro de la vista. Por ejemplo, si está iterando sobre un array de jobs, normalmente querrá 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 puede 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')
Las vistas renderizadas mediante @each no heredan las variables de la vista padre. Si la vista hija requiere estas variables, debe usar las directivas @foreach y @include en su lugar.
#La Directiva @once
La directiva @once le permite definir una porción de la plantilla que solo se evaluará una vez por ciclo de renderizado. Esto puede ser útil para insertar un fragmento de JavaScript en el encabezado de la página usando stacks. Por ejemplo, si está renderizando un componente dentro de un bucle, puede querer insertar el JavaScript en el encabezado solo la primera vez que se renderice el componente:
@once
@push('scripts')
<script>
// Su JavaScript personalizado...
</script>
@endpush
@endonce
Dado que la directiva @once se usa a menudo junto con las directivas @push o @prepend, las directivas @pushOnce y @prependOnce están disponibles para su conveniencia:
@pushOnce('scripts')
<script>
// Su JavaScript personalizado...
</script>
@endPushOnce
#PHP en Crudo
En algunas situaciones, es útil incrustar código PHP en sus vistas. Puede usar la directiva Blade @php para ejecutar un bloque de PHP puro dentro de su plantilla:
@php
$counter = 1;
@endphp
O, si solo necesita usar PHP para importar una clase, puede usar la directiva @use:
@use('App\Models\Flight')
Se puede proporcionar un segundo argumento a la directiva @use para aliasar la clase importada:
@use('App\Models\Flight', 'FlightModel')
#Comentarios
Blade también le permite definir comentarios en sus vistas. Sin embargo, a diferencia de los comentarios HTML, los comentarios Blade no se incluyen en el HTML que devuelve su aplicación:
{{-- This comment will not be present in the rendered HTML --}}
#Componentes
Los componentes y slots ofrecen beneficios similares a las secciones, layouts e includes; 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 clase, puede usar el comando Artisan make:component. Para ilustrar cómo usar componentes, crearemos un componente simple 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 su 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 registro adicional de componentes.
También puede 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 desea crear un componente anónimo (un componente con solo una plantilla Blade y sin clase), puede 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 puede renderizarse como un componente mediante <x-forms.input />.
#Registro Manual de Componentes de Paquetes
Al escribir componentes para su 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á construyendo un paquete que utiliza componentes Blade, necesitará registrar manualmente su clase de componente y su alias de etiqueta HTML. Normalmente debería registrar sus componentes en el método boot del service provider de su paquete:
use Illuminate\Support\Facades\Blade;
/**
* Inicializar los servicios de su paquete.
*/
public function boot(): void
{
Blade::component('package-alert', Alert::class);
}
Una vez que su componente ha sido registrado, puede renderizarse usando su alias de etiqueta:
<x-package-alert/>
Alternativamente, puede 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 residan dentro del namespace Package\Views\Components:
use Illuminate\Support\Facades\Blade;
/**
* Inicializar los servicios de su paquete.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}
Esto permitirá el uso de componentes del paquete por su namespace de proveedor usando la sintaxis package-name:::
<x-nightshade::calendar />
<x-nightshade::color-picker />
Blade detectará automáticamente la clase vinculada a este componente convirtiendo el nombre del componente a PascalCase. También se soportan subdirectorios usando la notación con "puntos".
#Renderizando Componentes
Para mostrar un componente, puede usar una etiqueta de componente Blade dentro de una de sus plantillas Blade. Las etiquetas de componentes 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, puede usar el carácter . para indicar el anidamiento 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 desea renderizar condicionalmente su componente, puede definir un método shouldRender en su clase de 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;
}
#Pasando Datos a Componentes
Puede pasar datos a los componentes Blade usando atributos HTML. Los valores primitivos codificados pueden pasarse al componente usando cadenas simples de atributos HTML. Las expresiones y variables PHP deben pasarse al componente mediante atributos que usen el carácter : como prefijo:
<x-alert type="error" :message="$message"/>
Debe definir todos los atributos de datos del componente en su constructor de clase. Todas las propiedades públicas de un componente estarán automáticamente disponibles 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
{
/**
* Crear la instancia del componente.
*/
public function __construct(
public string $type,
public string $message,
) {}
/**
* Obtener la vista / contenido que representa el componente.
*/
public function render(): View
{
return view('components.alert');
}
}
Cuando su componente se renderice, puede mostrar el contenido de las variables públicas de su componente haciendo echo de las variables por nombre:
<div class="alert alert-{{ $type }}">
{{ $message }}
</div>
#Convenciones de Nombres
Los argumentos del constructor del componente deben especificarse usando camelCase, mientras que kebab-case debe usarse al referenciar los nombres de los argumentos en sus atributos HTML. Por ejemplo, dado el siguiente constructor de componente:
/**
* Crear la instancia del componente.
*/
public function __construct(
public string $alertType,
) {}
El argumento $alertType puede proporcionarse al componente así:
<x-alert alert-type="danger" />
#Sintaxis Corta para Atributos
Al pasar atributos a componentes, también puede usar una sintaxis de "atributo corto". Esto es conveniente ya que los nombres de atributos frecuentemente 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" />
#Escapando la Renderización de Atributos
Dado que algunos frameworks JavaScript como Alpine.js también usan atributos con prefijo de dos puntos, puede 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 Componentes
Además de que las variables públicas estén disponibles para la plantilla de su componente, cualquier método público en el componente puede invocarse. Por ejemplo, imagine 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;
}
Puede ejecutar este método desde la plantilla de su 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 le permiten acceder al nombre del componente, atributos y slot dentro del método render de la clase. Sin embargo, para acceder a estos datos, debe retornar un closure desde el método render de su componente. El closure recibirá un array $data como único argumento. Este array contendrá varios elementos que proporcionan información sobre el componente:
use Closure;
/**
* Obtener la vista / contenido que representa el componente.
*/
public function render(): Closure
{
return function (array $data) {
// $data['componentName'];
// $data['attributes'];
// $data['slot'];
return '<div>Contenido del componente</div>';
};
}
El componentName es igual al nombre usado en la etiqueta HTML después del prefijo x-. Así que 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.
La closure debe devolver una cadena. Si la cadena devuelta corresponde a una vista existente, esa vista será renderizada; de lo contrario, la cadena devuelta será evaluada como una vista Blade en línea.
#Dependencias adicionales
Si su componente requiere dependencias del contenedor de servicios de Laravel, puede listarlas antes de cualquiera de los atributos de datos del componente y serán inyectadas automáticamente por el contenedor:
use App\Services\AlertCreator;
/**
* Crear la instancia del componente.
*/
public function __construct(
public AlertCreator $creator,
public string $type,
public string $message,
) {}
#Ocultar atributos / métodos
Si desea evitar que algunos métodos o propiedades públicas se expongan como variables en la plantilla de su componente, puede agregarlos a una propiedad $except como un array en su componente:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
/**
* Las propiedades / métodos que no deben exponerse a la plantilla del componente.
*
* @var array
*/
protected $except = ['type'];
/**
* Crear la instancia del componente.
*/
public function __construct(
public string $type,
) {}
}
#Atributos del componente
Ya hemos visto cómo pasar atributos de datos a un componente; sin embargo, a veces puede necesitar especificar atributos HTML adicionales, como class, que no forman parte de los datos necesarios para que un componente funcione. Normalmente, querrá pasar estos atributos adicionales al elemento raíz de la plantilla del componente. Por ejemplo, imagine que queremos renderizar un componente alert así:
<x-alert type="error" :message="$message" class="mt-4"/>
Todos los atributos que no formen parte del constructor del componente se agregarán automáticamente a la "bolsa de atributos" del componente. Esta bolsa de atributos está disponible automáticamente para el componente a través de la variable $attributes. Todos los atributos pueden renderizarse dentro del componente haciendo eco de esta variable:
<div {{ $attributes }}>
<!-- Contenido del componente -->
</div>
Actualmente no se soporta el uso de directivas como @env dentro de etiquetas de componentes. Por ejemplo, <x-alert :live="@env('production')"/> no será compilado.
#Atributos predeterminados / combinados
A veces puede necesitar especificar valores predeterminados para atributos o combinar valores adicionales en algunos de los atributos del componente. Para lograr esto, puede 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 siempre deben aplicarse a un componente:
<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
{{ $message }}
</div>
Si asumimos que este componente se utiliza así:
<x-alert type="error" :message="$message" class="mb-4"/>
El HTML final renderizado del componente aparecerá como el siguiente:
<div class="alert alert-error mb-4">
<!-- Contenido de la variable $message -->
</div>
#Combinar clases condicionalmente
A veces puede querer combinar clases si una condición dada es true. Puede lograr esto mediante el método class, que acepta un array de clases donde la clave del array contiene la clase o clases que desea 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 necesita combinar otros atributos en su componente, puede encadenar el método merge al método class:
<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}>
{{ $slot }}
</button>
Si necesita compilar clases condicionalmente en otros elementos HTML que no deberían recibir atributos combinados, puede usar la directiva @class.
#Combinación de atributos que no son clase
Al combinar 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 inyectados. En cambio, serán sobrescritos. Por ejemplo, la implementación de un componente button podría verse así:
<button {{ $attributes->merge(['type' => 'button']) }}>
{{ $slot }}
</button>
Para renderizar el componente button con un type personalizado, puede especificarse 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 desea que un atributo distinto de class tenga sus valores predeterminados y los valores inyectados unidos, puede 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>
#Recuperar y filtrar atributos
Puede filtrar atributos usando el método filter. Este método acepta una closure que debe devolver true si desea conservar el atributo en la bolsa de atributos:
{{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}
Para mayor comodidad, puede 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 puede usarse para excluir todos los atributos cuyas claves comienzan con una cadena dada:
{{ $attributes->whereDoesntStartWith('wire:model') }}
Usando el método first, puede renderizar el primer atributo en una bolsa de atributos dada:
{{ $attributes->whereStartsWith('wire:model')->first() }}
Si desea verificar si un atributo está presente en el componente, puede usar el método has. Este método acepta el nombre del atributo como ú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, este 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 puede usarse para determinar si alguno 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
Puede 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 para renderizar componentes. Las siguientes palabras clave no pueden definirse como propiedades públicas o nombres de métodos dentro de sus componentes:
datarenderresolveViewshouldRenderviewwithAttributeswithName
#Slots
A menudo necesitará pasar contenido adicional a su componente mediante "slots". Los slots de componentes se renderizan haciendo 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>Whoops!</strong> Something went wrong!
</x-alert>
A veces un componente puede necesitar renderizar múltiples slots diferentes en distintas ubicaciones dentro del componente. Modifiquemos nuestro componente alert para permitir la inyección de un slot llamado "title":
<!-- /resources/views/components/alert.blade.php -->
<span class="alert-title">{{ $title }}</span>
<div class="alert alert-danger">
{{ $slot }}
</div>
Puede 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>Whoops!</strong> Something went wrong!
</x-alert>
Puede 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, el método hasActualContent puede usarse para determinar si el slot contiene algún contenido "real" que no sea un comentario HTML:
@if ($slot->hasActualContent())
The scope has non-comment content.
@endif
#Slots con ámbito (Scoped Slots)
Si ha usado un framework JavaScript como Vue, puede estar familiarizado con los "scoped slots", que permiten acceder a datos o métodos del componente dentro de su slot. Puede lograr un comportamiento similar en Laravel definiendo métodos o propiedades públicas en su componente y accediendo al componente dentro de su slot mediante 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 slots
Al igual que los componentes Blade, puede 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 de los slots, puede acceder a la propiedad attributes de la variable del slot. Para más información sobre cómo interactuar con atributos, consulte la documentación sobre atributos de componentes:
@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 componentes 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, puede devolver el marcado del componente directamente desde el método render:
/**
* Obtener la vista / contenido que representa el componente.
*/
public function render(): string
{
return <<<'blade'
<div class="alert alert-danger">
{{ $slot }}
</div>
blade;
}
#Generar componentes de vista en línea
Para crear un componente que renderice una vista en línea, puede usar la opción inline al ejecutar el comando make:component:
php artisan make:component Alert --inline
#Componentes dinámicos
A veces puede necesitar renderizar un componente pero no saber cuál debe renderizarse hasta tiempo de ejecución. En esta situación, puede usar el componente incorporado dynamic-component de Laravel para renderizar el componente basado en un valor o variable en tiempo de ejecución:
// $componentName = "secondary-button";
<x-dynamic-component :component="$componentName" class="mt-4" />
#Registro manual de componentes
La siguiente documentación sobre el registro manual de componentes es principalmente aplicable para quienes están escribiendo paquetes Laravel que incluyen componentes de vista. Si no está escribiendo un paquete, esta parte de la documentación de componentes puede no ser relevante para usted.
Al escribir componentes para su 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á construyendo un paquete que utiliza componentes Blade o colocando componentes en directorios no convencionales, necesitará registrar manualmente su clase de componente y su alias de etiqueta HTML para que Laravel sepa dónde encontrar el componente. Normalmente, debería registrar sus componentes en el método boot del proveedor de servicios de su paquete:
use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;
/**
* Inicializar los servicios de su paquete.
*/
public function boot(): void
{
Blade::component('package-alert', AlertComponent::class);
}
Una vez que su componente ha sido registrado, puede renderizarse usando su alias de etiqueta:
<x-package-alert/>
#Autocarga de componentes de paquete
Alternativamente, puede 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 residan dentro del espacio de nombres Package\Views\Components:
use Illuminate\Support\Facades\Blade;
/**
* Inicializar los servicios de su paquete.
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}
Esto permitirá el uso de componentes del paquete por su espacio de nombres de proveedor usando la sintaxis package-name:::
<x-nightshade::calendar />
<x-nightshade::color-picker />
Blade detectará automáticamente la clase vinculada a este componente usando el nombre del componente en PascalCase. También se soportan subdirectorios usando la notación con "puntos".
#Componentes anónimos
Similar a los componentes en línea, los componentes anónimos proporcionan un mecanismo para gestionar un componente mediante 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 necesita colocar una plantilla Blade dentro de su directorio resources/views/components. Por ejemplo, suponiendo que haya definido un componente en resources/views/components/alert.blade.php, puede simplemente renderizarlo así:
<x-alert/>
Puede 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, puede renderizarlo así:
<x-inputs.button/>
#Componentes anónimos índice
A veces, cuando un componente está compuesto por muchas plantillas Blade, puede querer agrupar las plantillas del componente dado dentro de un solo directorio. Por ejemplo, imagine un componente "accordion" con la siguiente estructura de directorios:
/resources/views/components/accordion.blade.php
/resources/views/components/accordion/item.blade.php
Esta estructura de directorios le permite renderizar el componente accordion y su ítem así:
<x-accordion>
<x-accordion.item>
...
</x-accordion.item>
</x-accordion>
Sin embargo, para renderizar el componente accordion mediante x-accordion, nos vimos obligados a colocar la plantilla del componente "index" accordion en el directorio resources/views/components en lugar de anidarla dentro del directorio accordion con las otras plantillas relacionadas con accordion.
Afortunadamente, Blade le 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, esta se renderizará como el nodo "raíz" del componente. Así, podemos seguir usando la misma sintaxis Blade dada en el ejemplo anterior; sin embargo, ajustaremos nuestra estructura de directorios así:
/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, puede preguntarse cómo diferenciar qué datos deben pasarse al componente como variables y qué atributos deben colocarse en la bolsa de atributos del componente.
Puede especificar qué atributos deben considerarse variables de datos usando la directiva @props al inicio de la plantilla Blade de su componente. Todos los demás atributos en el componente estarán disponibles a través de la bolsa de atributos del componente. Si desea dar a una variable de datos un valor predeterminado, puede especificar el nombre de la variable como clave del array y el valor predeterminado como 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 así:
<x-alert type="error" :message="$message" class="mb-4"/>
#Acceder a datos del componente padre
A veces puede querer acceder a datos de un componente padre dentro de un componente hijo. En estos casos, puede usar la directiva @aware. Por ejemplo, imagine 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>
Como la propiedad color solo se pasó al padre (<x-menu>), no estará disponible dentro de <x-menu.item>. Sin embargo, si usamos la directiva @aware, podemos hacerla 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>
La directiva @aware no puede acceder a datos del padre que no se pasen explícitamente al componente padre mediante atributos HTML. Los valores predeterminados de @props que no se pasen 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 normalmente se definen colocando una plantilla Blade dentro de su directorio resources/views/components. Sin embargo, ocasionalmente puede querer 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 "namespace" opcional bajo el cual deben colocarse los componentes como su segundo argumento. Normalmente, este método debe llamarse desde el método boot de uno de los proveedores de servicios de su aplicación:
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::anonymousComponentPath(__DIR__.'/../components');
}
Cuando las rutas de componentes se registran sin un prefijo especificado como en el ejemplo anterior, pueden renderizarse en sus componentes Blade sin un prefijo correspondiente también. Por ejemplo, si existe un componente panel.blade.php en la ruta registrada arriba, puede renderizarse así:
<x-panel />
Se pueden proporcionar "namespaces" de prefijo como segundo argumento al método anonymousComponentPath:
Blade::anonymousComponentPath(__DIR__.'/../components', 'dashboard');
Cuando se proporciona un prefijo, los componentes dentro de ese "namespace" pueden renderizarse anteponiendo el namespace del componente al nombre del componente cuando se renderiza:
<x-dashboard::panel />
#Construyendo layouts
#Layouts usando componentes
La mayoría de las aplicaciones web mantienen el mismo layout 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 layout en cada vista que creamos. Afortunadamente, es conveniente definir este layout como un solo componente Blade y luego usarlo en toda nuestra aplicación.
#Definiendo el componente layout
Por ejemplo, imagine que estamos construyendo una aplicación de lista de "tareas". Podríamos definir un componente layout que se vea así:
<!-- resources/views/components/layout.blade.php -->
<html>
<head>
<title>{{ $title ?? 'Gestor de tareas' }}</title>
</head>
<body>
<h1>Tareas</h1>
<hr/>
{{ $slot }}
</body>
</html>
#Aplicando el componente layout
Una vez que el componente layout ha sido definido, 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)
{{ $task }}
@endforeach
</x-layout>
Recuerde, el contenido que se inyecta en un componente se suministrará a la variable predeterminada $slot dentro de nuestro componente layout. Como habrá 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 usando la sintaxis estándar de slots 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 nuestros layouts y vistas de lista de tareas, solo necesitamos devolver la vista tasks desde una ruta:
use App\Models\Task;
Route::get('/tasks', function () {
return view('tasks', ['tasks' => Task::all()]);
});
#Layouts usando herencia de plantillas
#Definiendo un layout
Los layouts también pueden crearse mediante "herencia de plantillas". Esta fue la forma principal de construir aplicaciones antes de la introducción de los componentes.
Para comenzar, veamos un ejemplo simple. Primero, examinaremos un layout de página. Dado que la mayoría de las aplicaciones web mantienen el mismo layout general en varias páginas, es conveniente definir este layout como una sola vista 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 puede ver, este archivo contiene marcado HTML típico. Sin embargo, tome 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 usa para mostrar el contenido de una sección dada.
Ahora que hemos definido un layout para nuestra aplicación, definamos una página hija que herede el layout.
#Extender un layout
Al definir una vista hija, use la directiva Blade @extends para especificar qué layout debe "heredar" la vista hija. Las vistas que extienden un layout Blade pueden inyectar contenido en las secciones del layout usando directivas @section. Recuerde, como se vio en el ejemplo anterior, el contenido de estas secciones se mostrará en el layout usando @yield:
<!-- resources/views/child.blade.php -->
@extends('layouts.app')
@section('title', 'Título de la página')
@section('sidebar')
@@parent
<p>Esto se añade 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 añadir (en lugar de sobrescribir) contenido a la barra lateral del layout. La directiva @@parent será reemplazada por el contenido del layout cuando la vista se renderice.
Contrariamente al ejemplo anterior, esta sección sidebar termina con @endsection en lugar de @show. La directiva @endsection solo define una sección mientras que @show define y renderiza inmediatamente la sección.
La directiva @yield también acepta un valor predeterminado como segundo parámetro. Este valor se renderizará si la sección que se está mostrando no está definida:
@yield('content', 'Default content')
#Formularios
#Campo CSRF
Cada vez que defina un formulario HTML en su aplicación, debe incluir un campo oculto de token CSRF para que el middleware de protección CSRF pueda validar la solicitud. Puede usar la directiva Blade @csrf para generar el campo del 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á agregar un campo oculto _method para simular estos verbos HTTP. La directiva Blade @method puede crear este campo por usted:
<form action="/foo/bar" method="POST">
@method('PUT')
...
</form>
#Errores de validación
La directiva @error puede usarse para verificar rápidamente si existen mensajes de error de validación para un atributo dado. Dentro de una directiva @error, puede hacer eco de 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 sentencia "if", puede usar la directiva @else para renderizar contenido cuando no hay 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">
Puede 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
#Stacks
Blade le permite agregar contenido a stacks nombrados que pueden renderizarse en otro lugar en otra vista o layout. Esto puede ser particularmente útil para especificar cualquier biblioteca JavaScript requerida por sus vistas hijas:
@push('scripts')
<script src="/example.js"></script>
@endpush
Si desea @push contenido solo si una expresión booleana dada evalúa a true, puede usar la directiva @pushIf:
@pushIf($shouldPush, 'scripts')
<script src="/example.js"></script>
@endPushIf
Puede agregar contenido a un stack tantas veces como sea necesario. Para renderizar el contenido completo del stack, pase el nombre del stack a la directiva @stack:
<head>
<!-- Contenido del head -->
@stack('scripts')
</head>
Si desea anteponer contenido al inicio de un stack, debe usar la directiva @prepend:
@push('scripts')
This will be second...
@endpush
// Más tarde...
@prepend('scripts')
This will be first...
@endprepend
#Inyección de Servicios
La directiva @inject puede usarse para obtener un servicio del service container de Laravel. El primer argumento que se pasa a @inject es el nombre de la variable donde se almacenará el servicio, mientras que el segundo argumento es el nombre de la clase o interfaz del servicio que desea resolver:
@inject('metrics', 'App\Services\MetricsService')
<div>
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>
#Renderizando Plantillas Blade en Línea
A veces puede necesitar transformar una cadena de plantilla Blade en HTML válido. Puede lograr esto usando el método render proporcionado por el facade Blade. El método render acepta la cadena de plantilla Blade y un arreglo 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 desea que Laravel elimine estos archivos temporales después de renderizar la plantilla Blade, puede proporcionar el argumento deleteCachedView al método:
return Blade::render(
'Hello, {{ $name }}',
['name' => 'Julian Bashir'],
deleteCachedView: true
);
#Renderizando Fragmentos Blade
Cuando usa frameworks frontend como Turbo y htmx, puede que ocasionalmente necesite devolver solo una parte de una plantilla Blade dentro de su respuesta HTTP. Los "fragmentos" de Blade permiten hacer justamente eso. Para comenzar, coloque una parte de su 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, puede invocar el método fragment para especificar que solo el fragmento indicado debe incluirse en la respuesta HTTP saliente:
return view('dashboard', ['users' => $users])->fragment('user-list');
El método fragmentIf le 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 le permiten devolver múltiples fragmentos de vista en la respuesta. Los fragmentos se concatenarán juntos:
view('dashboard', ['users' => $users])
->fragments(['user-list', 'comment-list']);
view('dashboard', ['users' => $users])
->fragmentsIf(
$request->hasHeader('HX-Request'),
['user-list', 'comment-list']
);
#Extender Blade
Blade le permite definir sus propias directivas personalizadas usando el método directive. Cuando el compilador Blade encuentra la directiva personalizada, llamará al callback proporcionado con la expresión que contiene la directiva.
El siguiente ejemplo crea una directiva @datetime($var) que formatea una variable $var dada, 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
{
/**
* Registrar cualquier servicio de la aplicación.
*/
public function register(): void
{
// ...
}
/**
* Inicializar 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 puede 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'); ?>
Después de actualizar la lógica de una directiva Blade, necesitará eliminar todas las vistas Blade en caché. Las vistas Blade en caché pueden eliminarse usando el comando Artisan view:clear.
#Manejadores de Echo Personalizados
Si intenta "echo" un objeto usando Blade, se invocará el método __toString del objeto. El método __toString es uno de los "métodos mágicos" incorporados en PHP. Sin embargo, a veces puede que no tenga control sobre el método __toString de una clase dada, como cuando la clase con la que interactúa pertenece a una biblioteca de terceros.
En estos casos, Blade le permite registrar un manejador de echo personalizado para ese tipo particular de objeto. Para lograr esto, debe invocar el método stringable de Blade. El método stringable acepta un closure. Este closure debe indicar el tipo de objeto que es responsable de renderizar. Normalmente, el método stringable debe invocarse dentro del método boot de la clase AppServiceProvider de su aplicación:
use Illuminate\Support\Facades\Blade;
use Money\Money;
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::stringable(function (Money $money) {
return $money->formatTo('en_GB');
});
}
Una vez que su manejador de echo personalizado ha sido definido, simplemente puede hacer echo del objeto en su plantilla Blade:
Cost: {{ $money }}
#Sentencias If Personalizadas
Programar una directiva personalizada a veces es más complejo de lo necesario para definir sentencias condicionales simples personalizadas. Por esa razón, Blade proporciona un método Blade::if que le permite definir rápidamente directivas condicionales personalizadas usando closures. Por ejemplo, definamos una condicional personalizada que verifica el "disk" predeterminado configurado para la aplicación. Podemos hacer esto en el método boot de nuestro AppServiceProvider:
use Illuminate\Support\Facades\Blade;
/**
* Inicializar cualquier servicio de la aplicación.
*/
public function boot(): void
{
Blade::if('disk', function (string $value) {
return config('filesystems.default') === $value;
});
}
Una vez que la condicional personalizada ha sido definida, puede usarla dentro de sus plantillas:
@disk('local')
<!-- La aplicación está usando el disco local... -->
@elsedisk('s3')
<!-- La aplicación está usando el disco s3... -->
@else
<!-- La aplicación está usando algún otro disco... -->
@enddisk
@unlessdisk('local')
<!-- La aplicación no está usando el disco local... -->
@enddisk