Plantillas Blade
- Introducción
- Visualización de datos
- Directivas Blade
- Componentes
- Componentes anónimos
- Creación de diseños
- Formularios
- Pilas
- Inyección de Servicios
- Renderizado de Plantillas Inline Blade
- Renderizado de Fragmentos Blade
- Ampliación de Blade
Introducción
Blade es el sencillo pero potente motor de plantillas que se incluye con Laravel. A diferencia de otros motores de plantillas PHP, Blade no restringe el uso de código PHP plano en las 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 esencialmente cero sobrecarga a su aplicación. Los archivos de plantillas Blade utilizan la extensión .blade.php
y se almacenan normalmente en el directorio resources/views
.
Las vistas Blade pueden ser devueltas desde rutas o controladores utilizando el helper view
. Por supuesto, como se menciona en la documentación sobre vistas/views, los datos pueden pasarse a la vista Blade utilizando el segundo argumento del helper de view
:
Route::get('/', function () { return view('greeting', ['name' => 'Finn']);});
Potenciando Blade con Livewire
¿Quieres llevar tus plantillas Blade al siguiente nivel y construir interfaces dinámicas con facilidad? Echa un vistazo a Laravel Livewire. Livewire le permite escribir componentes Blade mejorados con funcionalidades dinámicas que normalmente sólo serían posible usando frameworks frontend como React o Vue.
Visualización de Datos
Puede mostrar los 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
de la siguiente manera:
Hello, {{ $name }}.
Nota:
Las sentencias{{ }}
de Blade se pasan automáticamente a través de la funciónhtmlspecialchars
de PHP para evitar ataques XSS.
No está limitado a mostrar el contenido de las variables pasadas a la vista. También puede mostrar 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 el helper de Laravel e
) codificarán doblemente las entidades HTML. Si desea desactivar la doble codificación, 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{ /** * Bootstrap any application services. * * @return void */ public function boot() { Blade::withoutDoubleEncoding(); }}
Visualización de datos no codificados
Por defecto, las sentencias {{ }}
de Blade se envían automáticamente a través de la función htmlspecialchars
de PHP para evitar ataques XSS. Si no desea que sus datos sean escapados, puede utilizar la siguiente sintaxis:
Hello, {!! $name !!}.
Advertencia
Tenga mucho cuidado cuando se muestre del contenido suministrado por los usuarios de su aplicación. Normalmente debe utilizar la sintaxis de doble llave escapada para evitar ataques XSS al mostrar datos proporcionados por el usuario.
Blade y Frameworks JavaScript
Dado que muchos frameworks de JavaScript también utilizan llaves "curly" para indicar que una expresión determinada debe mostrarse en el navegador, puede utilizar el símbolo @
para informar al motor de renderizado de Blade de 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, permitiendo que sea renderizada por su framework JavaScript.
El símbolo @
también puede utilizarse para escapar de las directivas de Blade:
{{-- Blade template --}}@@if() <!-- HTML output -->@if()
Procesamiento de 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 la directiva de método Illuminate\Support\Js::from
. El método from
acepta los mismos argumentos que la función json_encode
de PHP; sin embargo, se asegurará de que el JSON resultante se escape correctamente para su inclusión dentro de las comillas HTML. El método from
devolverá una declaración JavaScript de cadena JSON.parse
que convertirá el objeto o matriz dado en un objeto JavaScript válido:
<script> var app = {{ Illuminate\Support\Js::from($array) }};</script>
Las últimas versiones del esqueleto de aplicaciones Laravel incluyen una facade Js
, que proporciona un cómodo acceso a esta funcionalidad dentro de tus plantillas Blade:
<script> var app = {{ Js::from($array) }};</script>
Advertencia
Sólo debes utilizar el métodoJs::from
para renderizar variables existentes como JSON. Las plantillas Blade se basan en expresiones regulares y los intentos de pasar una expresión compleja a la directiva pueden 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 anteponer un símbolo @
a cada sentencia echo de Blade:
@verbatim <div class="container"> Hello, {{ name }}. </div>@endverbatim
Directivas Blade
Además de la herencia de plantillas y la visualización de datos, Blade también proporciona cómodos atajos para estructuras de control de PHP comunes, como sentencias condicionales y bucles. Estos atajos proporcionan una forma muy limpia y concisa de trabajar con estructuras de control de PHP, a la vez que resultan familiares a sus homólogos PHP.
Sentencias If
Puede construir sentencias if
usando las directivas @if
, @elseif
, @else
y @endif
. Estas directivas funcionan de forma idéntica a sus equivalentes 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 discutidas, las directivas @isset
y @empty
pueden ser usadas como atajos para sus respectivas funciones PHP:
@isset($records) // $records is defined and is not null...@endisset @empty($records) // $records is "empty"...@endempty
Directivas de autenticación
Las directivas @auth
y @guest
pueden utilizarse para determinar rápidamente si el usuario actual está autenticado o es un invitado:
@auth // The user is authenticated...@endauth @guest // The user is not authenticated...@endguest
Si es necesario, puede especificar la guarda de autenticación que debe comprobarse al usar las directivas @auth
y @guest
:
@auth('admin') // The user is authenticated...@endauth @guest('admin') // The user is not authenticated...@endguest
Directivas de entorno
Puede comprobar si la aplicación se está ejecutando en el entorno de producción usando la directiva @production
:
@production // Production specific content...@endproduction
O puede determinar si la aplicación se está ejecutando en un entorno específico utilizando la directiva @env
:
@env('staging') // The application is running in "staging"...@endenv @env(['staging', 'production']) // The application is running in "staging" or "production"...@endenv
Directivas de sección
Puede determinar si una sección de la herencia de la plantilla tiene contenido usando la directiva @hasSection
:
@hasSection('navigation') <div class="pull-right"> @yield('navigation') </div> <div class="clearfix"></div>@endif
Puede utilizar 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 sentencias switch pueden construirse utilizando las directivas @switch
, @case
, @break
, @default
y @endswitch
:
@switch($i) @case(1) First case... @break @case(2) Second case... @break @default Default case...@endswitch
Bucles
Además de las sentencias condicionales, Blade proporciona directivas simples para trabajar con las estructuras de bucle de PHP. De nuevo, cada una de estas directivas funciona de forma idéntica a sus equivalentes 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
Nota
Mientras se itera a través de un bucleforeach
, se puede utilizar la variable loop para obtener información valiosa sobre el bucle, como por ejemplo si se está en la primera o en la última iteración a través del bucle.
Cuando utilice bucles, también puede saltarse la iteración actual o finalizar el bucle utilizando las directivas @continue
y @break
:
@foreach ($users as $user) @if ($user->type == 1) @continue @endif <li>{{ $user->name }}</li> @if ($user->number == 5) @break @endif@endforeach
También 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 es la primera o la última iteración a través del bucle:
@foreach ($users as $user) @if ($loop->first) This is the first iteration. @endif @if ($loop->last) This is the last iteration. @endif <p>This is user {{ $user->id }}</p>@endforeach
Si estás en un bucle anidado, puedes acceder a la variable $loop
del bucle padre a través de la propiedad parent
:
@foreach ($users as $user) @foreach ($user->posts as $post) @if ($loop->parent->first) This is the first iteration of the parent loop. @endif @endforeach@endforeach
La variable $loop
también contiene 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 del array que se está iterando. |
$loop->first |
Si es la primera iteración del bucle. |
$loop->last |
Si es la última iteración del bucle. |
$loop->even |
Si es una iteración par del bucle. |
$loop->odd |
Si es una iteración impar del bucle. |
$loop->depth |
El nivel de anidamiento del bucle actual. |
$loop->parent |
En un bucle anidado, la variable del bucle padre. |
Clases 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 añadir, 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 renderizada:
@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>
Atributos Adicionales
Para mayor comodidad, puede utilizar la directiva @checked
para indicar fácilmente si una entrada de casilla de verificación HTML está "marcada". Esta directiva mostrará checked
si la condición proporcionada se evalúa como true
:
<input type="checkbox" name="active" value="active" @checked(old('active', $user->active)) />
Del mismo modo, la directiva @selected
puede utilizarse para indicar si una opción de selección debe estar marcada como "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 ser marcado como "disabled":
<button type="submit" @disabled($errors->isNotEmpty())>Submit</button>
Por otra parte, la directiva @readonly
puede utilizarse para indicar si un elemento dado debe ser marcado como "readonly":
<input type="email" name="email" value="email@laravel.com" @readonly($user->isNotAdmin()) />
Además, la directiva @required
puede utilizarse para indicar si un elemento dado debe ser marcado como "required":
<input type="text" name="title" value="title" @required($user->isAdmin()) />
Inclusión de subvistas
Nota
Aunque es libre de utilizar la directiva@include
, los componentes Blade proporcionan una funcionalidad similar y ofrecen varias ventajas sobre la directiva@include
, como la vinculación de datos y atributos.
La directiva @include
de Blade 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> <!-- Form Contents --> </form></div>
Aunque la vista incluida heredará todos los datos disponibles en la vista padre, también puede pasar una array de datos adicionales que se pondrán a disposición de la vista incluida:
@include('view.name', ['status' => 'complete'])
Si intentas incluir una vista que no existe, Laravel arrojará un error. Si quieres incluir una vista que puede o no estar presente, debes usar la directiva @includeIf
:
@includeIf('view.name', ['status' => 'complete'])
Si quieres incluir una vista si una expresión booleana dada es 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 exista de un array de vistas dado, puede utilizar la directiva includeFirst
:
@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])
Advertencia
Evita utilizar las constantes__DIR__
y__FILE__
en tus vistas Blade, ya que harán referencia a la ubicación de la vista compilada en caché.
Renderizado de 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 a mostrar para cada elemento del array o colección. El segundo argumento es la array o colección sobre la 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. Así, por ejemplo, si estás iterando sobre un array de jobs
, normalmente querrás acceder a cada trabajo como una variable de job
dentro de la vista. La clave de la array para la iteración actual estará disponible como variable key
dentro de la vista.
También puede pasar un cuarto argumento a la directiva @each
. Este argumento determina la vista que se mostrará si la array dada está vacía.
@each('view.name', $jobs, 'job', 'view.empty')
Advertencia
Las vistas renderizadas mediante@each
no heredan las variables de la vista padre. Si la vista hija requiere estas variables, debe utilizar las directivas@foreach
e@include
en su lugar.
La Directiva @once
La directiva @once
permite definir una parte de la plantilla que sólo se evaluará una vez por ciclo de renderizado. Esto puede ser útil para empujar una determinada pieza de JavaScript en la cabecera de la página utilizando pilas. Por ejemplo, si está renderizando un componente determinado dentro de un bucle, puede que sólo desee insertar el JavaScript en la cabecera la primera vez que se renderice el componente:
@once @push('scripts') <script> // Your custom JavaScript... </script> @endpush@endonce
Dado que la directiva @once
se utiliza a menudo junto con las directivas @push
o @prepend
, las directivas @pushOnce
y @prependOnce
están disponibles para su conveniencia:
@pushOnce('scripts') <script> // Your custom JavaScript... </script>@endPushOnce
PHP en crudo
En algunas situaciones, es útil incrustar código PHP en las vistas. Puede utilizar la directiva @php
de Blade para ejecutar un bloque de PHP plano dentro de su plantilla:
@php $counter = 1;@endphp
Si sólo necesita escribir una única sentencia PHP, puede incluir la sentencia dentro de la directiva @php
:
@php($counter = 1)
Comentarios
Blade también le permite definir comentarios en sus vistas. Sin embargo, a diferencia de los comentarios HTML, los comentarios de Blade no se incluyen en el HTML devuelto por su aplicación:
{{-- This comment will not be present in the rendered HTML --}}
Componentes
Los componentes y los slots proporcionan beneficios similares a las secciones, los layouts y los includes; sin embargo, algunos pueden encontrar el modelo mental de los componentes y los slots más fácil de entender. Existen dos enfoques para escribir componentes: componentes basados en clases y componentes anónimos.
Para crear un componente basado en clases, puede utilizar el comando make:component
de Artisan. Para ilustrar el uso de componentes, crearemos un simple componente Alert
. El comando make:component
colocará el componente en el directorio app/View/Components
:
php artisan make:component Alert
El comando make:component
también creará una plantilla de vista para el componente. La vista se colocará en el directorio resources/views/components
. Al escribir componentes para su propia aplicación, los componentes se descubren automáticamente en el directorio app/View/Components
y en el directorio resources/views/components
, por lo que no suele ser necesario registrar más 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 sólo una plantilla Blade y sin clase), puede utilizar el indicador --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 ser renderizado como un componente a través de <x-forms.input />
.
Registro manual de componentes de paquetes
Al escribir componentes para su propia aplicación, los componentes se descubren automáticamente en el directorio app/View/Components
y en el directorio resources/views/components
.
Sin embargo, si está creando un paquete que utiliza componentes Blade, deberá registrar manualmente su clase de componente y su alias de etiqueta HTML. Normalmente, deberá registrar sus componentes en el método boot
del proveedor de servicios de su paquete:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. */public function boot(){ Blade::component('package-alert', Alert::class);}
Una vez registrado el componente, puede renderizarse utilizando su alias de etiqueta:
<x-package-alert/>
De manera alternativa, puede utilizar el método componentNamespace
para autocargar las clases de componentes por convención. Por ejemplo, un paquete Nightshade
puede tener componentes Calendar
y ColorPicker
que residan en el espacio de nombres Package\Views\Components
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. * * @return void */public function boot(){ Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');}
Esto permitirá el uso de componentes de paquete por 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 usando el nombre del componente en pascal-case. También se admiten subdirectorios utilizando la notación "punto".
Renderizado de Componentes
Para mostrar un componente, puede utilizar una etiqueta de componente Blade dentro de una de sus plantillas Blade. Las etiquetas de componente Blade comienzan con la cadena x-
seguida del nombre en mayúsculas y minúsculas de la clase de componente:
<x-alert/> <x-user-profile/>
Si la clase del componente está anidada a mayor profundidad dentro del directorio app/View/Components
, puede utilizar el carácter .
para indicar el anidamiento del directorio. Por ejemplo, si asumimos que un componente se encuentra en app/View/Components/Inputs/Button.php
, podemos renderizarlo así:
<x-inputs.button/>
Pasando Datos a los Componentes
Puede pasar datos a los componentes Blade utilizando atributos HTML. Los valores primitivos codificados pueden pasarse al componente usando simples cadenas de atributos HTML. Las expresiones y variables PHP deben pasarse al componente mediante atributos que utilicen 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 disponibles automáticamente para la vista del componente. No es necesario pasar los datos a la vista desde el método de render
del componente:
<?php namespace App\View\Components; use Illuminate\View\Component; class Alert extends Component{ /** * The alert type. * * @var string */ public $type; /** * The alert message. * * @var string */ public $message; /** * Create the component instance. * * @param string $type * @param string $message * @return void */ public function __construct($type, $message) { $this->type = $type; $this->message = $message; } /** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|\Closure|string */ public function render() { return view('components.alert'); }}
Cuando su componente es renderizado, puede mostrar el contenido de las variables públicas de su componente haciendo eco de las variables por su nombre:
<div class="alert alert-{{ $type }}"> {{ $message }}</div>
Casing
Los argumentos de los constructores de componentes deben especificarse utilizando camelCase
, mientras que debe utilizarse kebab-case
cuando se haga referencia a los nombres de los argumentos en los atributos HTML. Por ejemplo, dado el siguiente constructor de componente:
/** * Create the component instance. * * @param string $alertType * @return void */public function __construct($alertType){ $this->alertType = $alertType;}
El argumento $alertType
puede proporcionarse al componente de la siguiente manera:
<x-alert alert-type="danger" />
Sintaxis corta de atributos
Al pasar atributos a los componentes, también puede utilizar una sintaxis de "atributo corto". Esto suele ser conveniente, ya que los nombres de los atributos suelen coincidir 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" />
Cómo evitar el renderizado de atributos
Dado que algunos frameworks JavaScript como Alpine.js también utilizan atributos con prefijo de dos puntos, puede utilizar un prefijo de dos puntos dobles (::
) para informar a Blade de 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 del componente
Además de que las variables públicas estén disponibles para su plantilla de componentes, cualquier método público del componente puede ser invocado. Por ejemplo, imagine un componente que tiene un método isSelected
:
/** * Determine if the given option is the currently selected option. * * @param string $option * @return bool */public function isSelected($option){ return $option === $this->selected;}
Puede ejecutar este método desde su plantilla de componentes invocando la variable que coincida con el nombre del método:
<option {{ $isSelected($value) ? 'selected' : '' }} value="{{ $value }}"> {{ $label }}</option>
Acceso a atributos y slots dentro de las clases de componentes
Los componentes Blade también le 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, debe devolver un closure desde el método de 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:
/** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|\Closure|string */public function render(){ return function (array $data) { // $data['componentName']; // $data['attributes']; // $data['slot']; return '<div>Components content</div>'; };}
El componentName
es igual al nombre utilizado en la etiqueta HTML después del prefijo x-
. Así, el componentName
de <x-alert />
será alert
. El elemento attributes
contendrá todos los atributos presentes en la etiqueta HTML. El elemento slot
es una instancia Illuminate\Support\HtmlString
con el contenido del slot del componente.
El closure debe devolver una cadena. Si la cadena devuelta corresponde a una vista existente, esa vista se renderizará; en caso contrario, la cadena devuelta se evaluará como una vista Blade en línea.
Dependencias adicionales
Si su componente requiere dependencias del contenedor de servicios de Laravel, puede enumerarlas antes de cualquiera de los atributos de datos del componente y serán inyectadas automáticamente por el contenedor:
use App\Services\AlertCreator; /** * Create the component instance. * * @param \App\Services\AlertCreator $creator * @param string $type * @param string $message * @return void */public function __construct(AlertCreator $creator, $type, $message){ $this->creator = $creator; $this->type = $type; $this->message = $message;}
Ocultar atributos / métodos
Si desea evitar que algunos métodos públicos o propiedades se expongan como variables a la plantilla de su componente, puede añadirlos a una propiedad $except
array en su componente:
<?php namespace App\View\Components; use Illuminate\View\Component; class Alert extends Component{ /** * The alert type. * * @var string */ public $type; /** * The properties / methods that should not be exposed to the component template. * * @var array */ protected $except = ['type'];}
Atributos de Componentes
Ya hemos examinado cómo pasar atributos de datos a un componente; sin embargo, a veces puede ser necesario especificar atributos HTML adicionales, como class
, que no forman parte de los datos necesarios para que funcione un componente. Normalmente, querrá pasar estos atributos adicionales al elemento raíz de la plantilla del componente. Por ejemplo, imagine que queremos renderizar un componente de alert
de la siguiente manera:
<x-alert type="error" :message="$message" class="mt-4"/>
Todos los atributos que no formen parte del constructor del componente se añadirán automáticamente a la "bolsa de atributos" del componente. Esta bolsa de atributos se pone automáticamente a disposición del componente a través de la variable $attributes
. Todos los atributos pueden ser renderizados dentro del componente haciendo eco de esta variable:
<div {{ $attributes }}> <!-- Component content --></div>
Advertencia
El uso de directivas como@env
dentro de las etiquetas del componente no está soportado en este momento. Por ejemplo,<x-alert :live="@env('production')"/>
no será compilado.
Atributos por defecto / mergeados
A veces puede ser necesario especificar valores por defecto para los atributos o combinar valores adicionales en algunos de los atributos del componente. Para ello, puede utilizar el método de merge
de la bolsa de atributos. Este método es especialmente útil para definir un conjunto de clases CSS predeterminadas que deben aplicarse siempre a un componente:
<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}> {{ $message }}</div>
Si suponemos que este componente se utiliza así:
<x-alert type="error" :message="$message" class="mb-4"/>
El HTML final renderizado del componente tendrá el siguiente aspecto:
<div class="alert alert-error mb-4"> <!-- Contents of the $message variable --></div>
Combinar clases condicionalmente
A veces puede que desee combinar clases si una condición dada es true
. Puede hacerlo mediante el método class
, que acepta un array de clases donde la clave array contiene la clase o clases que desea añadir, 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 renderizada:
<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}> {{ $message }}</div>
Si necesita combinar otros atributos en su componente, puede encadenar el método merge
con el método class
:
<button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}> {{ $slot }}</button>
Nota
Si necesita compilar condicionalmente clases en otros elementos HTML que no deben recibir atributos fusionados, puede utilizar la directiva@class
.
combinación de atributos no de clase
Al combinar atributos que no son atributos class
, los valores proporcionados al método merge
se considerarán los valores "por defecto" del atributo. Sin embargo, a diferencia de los atributos class
, estos atributos no se combinarán con valores de atributo inyectados. En su lugar, se sobrescribirán. Por ejemplo, la implementación de un componente button
puede tener el siguiente aspecto:
<button {{ $attributes->merge(['type' => 'button']) }}> {{ $slot }}</button>
Para renderizar el componente botón con un type
personalizado, se puede especificar al consumir el componente. Si no se especifica ningún tipo, se utilizará el tipo button
:
<x-button type="submit"> Submit</x-button>
El HTML renderizado del componente button
en este ejemplo sería:
<button type="submit"> Submit</button>
Si desea que un atributo distinto a class
tenga su valor por defecto y los valores inyectados unidos, puede utilizar 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 por defecto:
<div {{ $attributes->merge(['data-controller' => $attributes->prepends('profile-controller')]) }}> {{ $slot }}</div>
Recuperación y filtrado de atributos
Puede filtrar atributos utilizando el método filter
. Este método acepta un closure que debe devolver true
si desea conservar el atributo en la bolsa de atributos:
{{ $attributes->filter(fn ($value, $key) => $key == 'foo') }}
Para mayor comodidad, puede utilizar el método whereStartsWith
para recuperar todos los atributos cuyas claves empiecen por una cadena determinada:
{{ $attributes->whereStartsWith('wire:model') }}
Por el contrario, el método whereDoesntStartWith
puede utilizarse para excluir todos los atributos cuyas claves empiecen por una cadena determinada:
{{ $attributes->whereDoesntStartWith('wire:model') }}
Utilizando el método first
, puede obtener el primer atributo de una bolsa de atributos dada:
{{ $attributes->whereStartsWith('wire:model')->first() }}
Si desea comprobar si un atributo está presente en el componente, puede utilizar 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
Puede recuperar el valor de un atributo específico utilizando el método get
:
{{ $attributes->get('class') }}
Palabras clave reservadas
Por defecto, algunas palabras clave están reservadas para el uso interno de Blade con el fin de renderizar componentes. Las siguientes palabras clave no pueden definirse como propiedades públicas o nombres de métodos dentro de sus componentes:
-
data
-
render
-
resolveView
-
shouldRender
-
view
-
withAttributes
-
withName
Slots
A menudo necesitará pasar contenido adicional a su componente a través de "slots". Los slots del componente se renderizan haciendo eco de la variable $slot
. Para explorar este concepto, imaginemos que un componente alert
tiene la siguiente forma:
<!-- /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 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
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>
Scoped Slots
Si has utilizado un framework JavaScript como Vue, puede que estés familiarizado con los "scoped slots", que te permiten acceder a datos o métodos del componente dentro de tu slot. Puedes conseguir un comportamiento similar en Laravel definiendo métodos públicos o propiedades 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 componente:
<x-alert> <x-slot:title> {{ $component->formatAlert('Server Error') }} </x-slot> <strong>Whoops!</strong> Something went wrong!</x-alert>
Atributos de los 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 los 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
:
/** * Get the view / contents that represent the component. * * @return \Illuminate\View\View|\Closure|string */public function render(){ return <<<'blade' <div class="alert alert-danger"> {{ $slot }} </div> blade;}
Generación de componentes de vista en línea
Para crear un componente que renderice una vista en línea, puede utilizar 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 qué componente debe ser renderizado hasta el momento de la ejecución. En este caso, puedes usar el dynamic-component
de Laravel para renderizar el componente basándote en un valor o variable en tiempo de ejecución:
<x-dynamic-component :component="$componentName" class="mt-4" />
Registro manual de componentes
Advertencia
La siguiente documentación sobre el registro manual de componentes es aplicable principalmente a aquellos que están escribiendo paquetes Laravel que incluyen componentes de vista. Si no estás escribiendo un paquete, esta parte de la documentación sobre componentes puede no ser relevante para ti.
Al escribir componentes para su propia aplicación, los componentes se descubren automáticamente en el directorio app/View/Components
y en el directorio resources/views/components
.
Sin embargo, si estás construyendo un paquete que utiliza componentes Blade o colocando componentes en directorios no convencionales, necesitarás registrar manualmente tu clase de componente y su alias de etiqueta HTML para que Laravel sepa dónde encontrar el componente. Por lo general, debe registrar sus componentes en el método de boot
del proveedor de servicios de su paquete:
use Illuminate\Support\Facades\Blade;use VendorPackage\View\Components\AlertComponent; /** * Bootstrap your package's services. * * @return void */public function boot(){ Blade::component('package-alert', AlertComponent::class);}
Una vez que su componente ha sido registrado, puede ser renderizado usando su alias de etiqueta:
<x-package-alert/>
Autoloading Package Components
De manera alternativa, puede utilizar el método componentNamespace
para autocargar clases de componentes por convención. Por ejemplo, un paquete Nightshade
puede tener componentes Calendar
y ColorPicker
que residan dentro del espacio de nombres Package\Views\Components
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap your package's services. * * @return void */public function boot(){ Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');}
Esto permitirá el uso de componentes de paquete por su namespace de proveedor utilizando la sintaxis package-name::
:
<x-nightshade::calendar /><x-nightshade::color-picker />
Blade detectará automáticamente la clase vinculada a este componente escribiendo el nombre del componente en pascal-case. También se admiten subdirectorios utilizando la notación "punto".
Componentes anónimos
De forma similar a los componentes en línea, los componentes anónimos proporcionan un mecanismo para gestionar un componente a través de un único archivo. Sin embargo, los componentes anónimos utilizan un único archivo de vista y no tienen una clase asociada. Para definir un componente anónimo, sólo 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 utilizar el carácter .
para indicar si un componente está anidado a mayor profundidad dentro del directorio components
. Por ejemplo, asumiendo que el componente está definido en resources/views/components/inputs/button.blade.
php, puede renderizarlo así:
<x-inputs.button/>
Componentes de índice anónimos
A veces, cuando un componente se compone de muchas plantillas Blade, es posible que desee agrupar las plantillas del componente dado dentro de un único directorio. Por ejemplo, imagine un componente "acordeón" 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 acordeón y su elemento así:
<x-accordion> <x-accordion.item> ... </x-accordion.item></x-accordion>
Sin embargo, para renderizar el componente acordeón a través de x-accordion
, nos vimos obligados a colocar la plantilla del componente 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 permite colocar un archivo index.blade.php
dentro del directorio de plantillas de un componente. Cuando exista una plantilla index.blade.php
para el componente, se mostrará como el nodo "raíz" del componente. Por lo tanto, podemos seguir utilizando la misma sintaxis de Blade que 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, es posible que se pregunte cómo puede 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 utilizando la directiva @props
en la parte superior de la plantilla Blade de su componente. Todos los demás atributos del componente estarán disponibles a través de la bolsa de atributos del componente. Si desea dar a una variable de datos un valor por defecto, puede especificar el nombre de la variable como clave del array y el valor por defecto 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 de componente anterior, podemos representar el componente así:
<x-alert type="error" :message="$message" class="mb-4"/>
Acceso a datos principales
A veces es posible que desee acceder a los datos de un componente padre dentro de un componente hijo. En estos casos, puede utilizar la directiva @aware
. Por ejemplo, imaginemos que estamos construyendo un componente de menú complejo que consta de un padre <x-menu>
y un hijo <x-menu.item>:
<x-menu color="purple"> <x-menu.item>...</x-menu.item> <x-menu.item>...</x-menu.item></x-menu>
El componente <x-menu>
puede tener una implementación como la siguiente:
<!-- /resources/views/components/menu/index.blade.php --> @props(['color' => 'gray']) <ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}> {{ $slot }}</ul>
Debido a que la prop de color
sólo se pasó al padre (<x-menu>
), no estará disponible dentro de <x-menu.item>
. Sin embargo, si utilizamos la directiva @aware
, podemos hacer que también esté disponible 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 padre que no se hayan pasado explícitamente al componente padre mediante atributos HTML. La directiva@aware
no puede acceder a valores@props
predeterminados que no se hayan pasado explícitamente al componente padre.
Rutas de componentes anónimos
Como se ha comentado anteriormente, los componentes anónimos se definen normalmente colocando una plantilla Blade en el directorio resources/views/components
. Sin embargo, ocasionalmente puede querer registrar otras rutas de componentes anónimos con Laravel además de la ruta por defecto.
El método anonymousComponentPath
acepta la "ruta" a la ubicación del componente anónimo como primer argumento y un "namespace" opcional bajo el que deben colocarse los componentes como segundo argumento. Normalmente, este método debería llamarse desde el método boot
de uno de los proveedores de servicios de su aplicación:
/** * Bootstrap any application services. * * @return void */public function boot(){ Blade::anonymousComponentPath(__DIR__.'/../components');}
Cuando las rutas de los componentes se registran sin un prefijo especificado como en el ejemplo anterior, pueden ser renderizados también en sus componentes Blade sin un prefijo correspondiente. Por ejemplo, si un componente panel.blade.php
existe en la ruta registrada arriba, puede ser renderizado así:
<x-panel />
Se pueden proporcionar "namespace" prefijados como segundo argumento del método anonymousComponentPath
:
Blade::anonymousComponentPath(__DIR__.'/../components', 'dashboard');
Cuando se proporciona un prefijo, los componentes dentro de ese "namespace" pueden ser renderizados anteponiendo el prefijo del namespace del componente al nombre del componente cuando el este es renderizado:
<x-dashboard::panel />
Creación de diseños
Layouts 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 mantener nuestra aplicación si tuviéramos que repetir todo el diseño HTML en cada vista que creamos. Afortunadamente, es conveniente definir este diseño como un único componente Blade y luego utilizarlo en toda nuestra aplicación.
Definición del componente de layout
Por ejemplo, imaginemos que estamos creando una aplicación de listas de tareas. Podríamos definir un componente de layout
como el siguiente:
<!-- resources/views/components/layout.blade.php --> <html> <head> <title>{{ $title ?? 'Todo Manager' }}</title> </head> <body> <h1>Todos</h1> <hr/> {{ $slot }} </body></html>
Aplicación del componente Layout
Una vez definido el componente de layout
, podemos crear una vista Blade que utilice el componente. En este ejemplo, definiremos una vista simple que muestre nuestra lista de tareas:
<!-- resources/views/tasks.blade.php --> <x-layout> @foreach ($tasks as $task) {{ $task }} @endforeach</x-layout>
Recuerde que el contenido que se inyecte en un componente se suministrará a la variable predeterminada $slot
dentro de nuestro componente de layout
. Como habrá notado, nuestro layout
también respeta un slot $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 utilizando la sintaxis de un slot estándar que se discute en la documentación del componente :
<!-- resources/views/tasks.blade.php --> <x-layout> <x-slot:title> Custom Title </x-slot> @foreach ($tasks as $task) {{ $task }} @endforeach</x-layout>
Ahora que hemos definido nuestras vistas de diseño y de lista de tareas, sólo 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
Definir un Layout
Los diseños también pueden crearse a través de la "herencia de plantillas". Esta era la forma principal de construir aplicaciones antes de la introducción de los componentes.
Para empezar, veamos un ejemplo sencillo. En primer lugar, examinaremos el diseño de una 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 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 el típico marcado HTML. Sin embargo, tenga 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 determinada.
Ahora que hemos definido un layout para nuestra aplicación, vamos a definir una página hija que herede el diseño.
Extender un layout
Al definir una vista hija, utilice la directiva @extends
Blade para especificar qué diseño debe "heredar" la vista hija. Las vistas que extienden un diseño Blade pueden inyectar contenido en las secciones del layout utilizando las directivas @section
. Recuerde que, como se ha visto 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>This is appended to the master sidebar.</p>@endsection @section('content') <p>This is my body content.</p>@endsection
En este ejemplo, la sección sidebar
utiliza la directiva @parent
para añadir (en lugar de sobrescribir) contenido a la barra lateral del diseño. La directiva @parent
será sustituida por el contenido del diseño cuando se muestre la vista.
Nota
A diferencia del ejemplo anterior, esta secciónsidebar
termina con@endsection
en lugar de@show
. La directiva@endsection
sólo definirá una sección, mientras que@show
definirá y mostrará inmediatamente la sección.
La directiva @yield
también acepta un valor por defecto como segundo parámetro. Este valor se mostrará si la sección que se muestra 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 de token CSRF oculto en el formulario para que el middleware de protección CSRF pueda validar la solicitud. Puede utilizar la directiva @csrf
Blade para generar el campo token:
<form method="POST" action="/profile"> @csrf ...</form>
Campo de método
Dado que los formularios HTML no pueden realizar peticiones PUT
, PATCH
o DELETE
, tendrá que añadir un campo _method
oculto para imitar estas acciones de222222s HTTP. La directiva @method
de Blade puede crear este campo por usted:
<form action="/foo/bar" method="POST"> @method('PUT') ...</form>
Errores de validación
La directiva @error
puede utilizarse para comprobar rápidamente si existen mensajes de error de validación para un atributo determinado. 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">Post Title</label> <input id="title" type="text" class="@error('title') is-invalid @enderror"> @error('title') <div class="alert alert-danger">{{ $message }}</div>@enderror
Dado que la directiva @error
se compila como una sentencia "if", puede utilizar la directiva @else
para mostrar el contenido cuando no haya ningún error para un atributo:
<!-- /resources/views/auth.blade.php --> <label for="email">Email address</label> <input id="email" type="email" class="@error('email') is-invalid @else is-valid @enderror">
Puede pasar el nombre de una bolsa de errores específica como segundo parámetro de la directiva @error
para recuperar mensajes de error de validación en páginas que contengan varios formularios:
<!-- /resources/views/auth.blade.php --> <label for="email">Email address</label> <input id="email" type="email" class="@error('email', 'login') is-invalid @enderror"> @error('email', 'login') <div class="alert alert-danger">{{ $message }}</div>@enderror
Pilas
Blade te permite añadir contenido a pilas con nombre que pueden ser renderizadas en otro lugar en otra vista o layout. Esto puede ser particularmente útil para especificar cualquier librería JavaScript requerida por sus vistas hijas:
@push('scripts') <script src="/example.js"></script>@endpush
Si desea añadir contenido a una pila si una expresión booleana dada se evalúa como true
, puede utilizar la directiva @pushIf
:
@pushIf($shouldPush, 'scripts') <script src="/example.js"></script>@endPushIf
Puede añadir contenido a una pila tantas veces como sea necesario. Para mostrar el contenido completo de la pila, pase el nombre de la pila a la directiva @stack
:
<head> <!-- Head Contents --> @stack('scripts')</head>
Si desea añadir contenido al principio de una pila, utilice la directiva @prepend
:
@push('scripts') This will be second...@endpush // Later... @prepend('scripts') This will be first...@endprepend
Inyección de Servicios
La directiva @inject
puede utilizarse para recuperar un servicio del contenedor de servicios de Laravel. El primer argumento que se pasa a @inject
es el nombre de la variable en la que se colocará el servicio, mientras que el segundo argumento es el nombre de la clase o interfaz del servicio que se desea resolver:
@inject('metrics', 'App\Services\MetricsService') <div> Monthly Revenue: {{ $metrics->monthlyRevenue() }}.</div>
Renderizado de Plantillas Inline Blade
A veces puede que necesite transformar una cadena de plantilla Blade sin procesar en HTML válido. Para ello puede utilizar el método render
proporcionado por la facade Blade
. El método render
acepta la cadena de la plantilla Blade y un array opcional de datos para proporcionar a la plantilla:
use Illuminate\Support\Facades\Blade; return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
Laravel renderiza las plantillas Blade en línea escribiéndolas en el directorio storage/framework/views
. Si quieres que Laravel elimine estos ficheros temporales después de renderizar la plantilla Blade, puedes proporcionar el argumento deleteCachedView
al método:
return Blade::render( 'Hello, {{ $name }}', ['name' => 'Julian Bashir'], deleteCachedView: true);
Renderizado de Fragmentos Blade
Al utilizar frameworks de frontend como Turbo y htmx, puede que ocasionalmente necesite devolver sólo una parte de una plantilla Blade dentro de su respuesta HTTP. Los "fragmentos" de Blade le permiten hacer precisamente eso. Para empezar, 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
A continuación, al renderizar la vista que utiliza esta plantilla, puede invocar el método fragment
para especificar que sólo el fragmento especificado debe incluirse en la respuesta HTTP saliente:
return view('dashboard', ['users' => $users])->fragment('user-list');
Ampliación de Blade
Blade le permite definir sus propias directivas personalizadas utilizando el método directive
. Cuando el compilador de Blade encuentre la directiva personalizada, llamará a la llamada de retorno proporcionada con la expresión que contiene la directiva.
El siguiente ejemplo crea una directiva @datetime($var)
que formatea una $var
dada, que debe ser una instancia de DateTime
:
<?php namespace App\Providers; use Illuminate\Support\Facades\Blade;use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * Register any application services. * * @return void */ public function register() { // } /** * Bootstrap any application services. * * @return void */ public function boot() { Blade::directive('datetime', function ($expression) { return "<?php echo ($expression)->format('m/d/Y H:i'); ?>"; }); }}
Como puedes ver, encadenaremos el método format
a cualquier expresión que se pase a la directiva. Así, en este ejemplo, el PHP final generado por esta directiva será:
<?php echo ($var)->format('m/d/Y H:i'); ?>
Warning
Después de actualizar la lógica de una directiva Blade, deberá eliminar todas las vistas Blade almacenadas en caché. Las vistas Blade almacenadas en caché pueden eliminarse utilizando el comandoview:clear
Artisan.
Manejadores de Eco Personalizados
Si intenta hacer "eco" de un objeto utilizando Blade, se invocará al método __toString
del objeto. El método __toString
es uno de los "métodos mágicos" de 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 está interactuando pertenece a una librería de terceros.
En estos casos, Blade permite registrar un manejador de eco personalizado para ese tipo concreto de objeto. Para lograr esto, debes invocar el método stringable
de Blade. El método stringable
acepta un closure. Este closure debe indicar el tipo de objeto del que es responsable. Típicamente, el método stringable
debería ser invocado dentro del método boot
de la clase AppServiceProvider
de su aplicación:
use Illuminate\Support\Facades\Blade;use Money\Money; /** * Bootstrap any application services. * * @return void */public function boot(){ Blade::stringable(function (Money $money) { return $money->formatTo('en_GB'); });}
Una vez que su manejador de eco personalizado ha sido definido, puede simplemente hacer eco del objeto en su plantilla Blade:
Cost: {{ $money }}
Sentencias If personalizadas
Programar una directiva personalizada es a veces más complejo de lo necesario cuando se trata de definir sentencias condicionales simples y personalizadas. Por esa razón, Blade proporciona un método Blade::if
que permite definir rápidamente directivas condicionales personalizadas utilizando closures. Por ejemplo, definamos una condicional personalizada que compruebe el "disco" configurado por defecto para la aplicación. Podemos hacer esto en el método boot
de nuestro AppServiceProvider
:
use Illuminate\Support\Facades\Blade; /** * Bootstrap any application services. * * @return void */public function boot(){ Blade::if('disk', function ($value) { return config('filesystems.default') === $value; });}
Una vez definido el condicional personalizado, puede utilizarlo dentro de sus plantillas:
@disk('local') <!-- The application is using the local disk... -->@elsedisk('s3') <!-- The application is using the s3 disk... -->@else <!-- The application is using some other disk... -->@enddisk @unlessdisk('local') <!-- The application is not using the local disk... -->@enddisk