Do not speak Portuguese? Translate this site with Google or Bing Translator
Blade Templating

Posted on: February 10, 2023 12:37 PM

Posted by: Renato

Views: 761

Blade Templating

Comparado com a maioria das outras linguagens de back-end, o PHP realmente funciona relativamente bem como uma linguagem de modelagem. Mas ele tem suas deficiências e também é feio usar <?phpinline em todos os lugares, portanto, você pode esperar que a maioria das estruturas modernas ofereça uma linguagem de modelo.

O Laravel oferece um mecanismo de modelagem personalizado chamado Blade , que é inspirado no mecanismo Razor do .NET. Possui uma sintaxe concisa, uma curva de aprendizado rasa, um modelo de herança poderoso e intuitivo e fácil extensibilidade.

Para uma rápida olhada em como é escrever Blade, confira o Exemplo 4-1 .

Exemplo 4-1. Amostras de lâmina
<h1>{{ $group->title }}</h1>
{!! $group->heroImageHtml() !!}

@forelse ($users as $user)
     {{ $user->first_name }} {{ $user->last_name }}<br>
@empty
    No users in this group.
@endforelse

Como você pode ver, o Blade usa chaves para seu “eco” e introduz uma convenção na qual suas tags personalizadas, chamadas “diretivas”, são prefixadas com um @Você usará diretivas para todas as suas estruturas de controle e também para herança e qualquer funcionalidade personalizada que desejar adicionar.

A sintaxe do Blade é limpa e concisa, portanto, em sua essência, é apenas mais agradável e organizada de se trabalhar do que as alternativas. Mas no momento em que você precisa de qualquer coisa de qualquer complexidade em seus modelos - herança aninhada, condicionais complexas ou recursão - o Blade começa a realmente brilhar. Assim como os melhores componentes do Laravel, ele exige requisitos complexos de aplicativos e os torna fáceis e acessíveis.

Além disso, como toda a sintaxe do Blade é compilada em código PHP normal e depois armazenada em cache, é rápido e permite que você use PHP nativo em seus arquivos Blade, se desejar. No entanto, eu recomendo evitar o uso de PHP, se possível - geralmente, se você precisar fazer algo que não pode fazer com o Blade ou com uma diretiva Blade personalizada, ela não pertence ao modelo.

USANDO TWIG COM LARAVEL

Ao contrário de muitos outros frameworks baseados em Symfony, o Laravel não usa o Twig por padrão. Mas se você está apaixonado pelo Twig, há um pacote Twig Bridge que facilita o uso do Twig em vez do Blade.

Ecoando dados

Como você pode ver no Exemplo 4-1 , {{}}são usados ​​para agrupar as seções do PHP que você gostaria de ecoar. é semelhante ao PHP simples.{{ $variable }}<?= $variable ?>

É diferente de uma maneira, no entanto, e você já deve ter adivinhado isso:Blade escapa de todos os ecos por padrão usando PHP htmlentities()para proteger seus usuários de inserção de script malicioso. Isso significa que é funcionalmente equivalente a .{{ $variable }}<?= htmlentities($variable) ?>Se você quiser ecoar sem escapar, use {!!!!}em vez disso.

Estruturas de controle

A maioria das estruturas de controle em Blade será muito familiar. Muitos ecoam diretamente o nome e a estrutura da mesma tag em PHP.

Existem alguns auxiliares de conveniência, mas, em geral, as estruturas de controle parecem mais limpas do que no PHP.

Condicionais

Primeiro, vamos dar uma olhada nas estruturas de controle que permitem a lógica.

@se

As compilações do Blade para , e também compilar exatamente no mesmo estilo de sintaxe em PHP. Dê uma olhada no Exemplo 4-2 para alguns exemplos.@if ($condition)<?php if ($condition): ?>@else@elseif@endif

Exemplo 4-2. @if, @else, @elseif e @endif
@if (count($talks) === 1)
    There is one talk at this time period.
@elseif (count($talks) === 0)
    There are no talks at this time period.
@else
    There are {{ count($talks) }} talks at this time period.
@endif

Assim como com os condicionais nativos do PHP, você pode misturá-los e combiná-los como quiser. Eles não têm nenhuma lógica especial; há literalmente um analisador procurando por algo com a forma de e substituindo-o pelo código PHP apropriado.@if ($condition)

@unless e @endunless

@unless, por outro lado, é uma nova sintaxe que não possui um equivalente direto em PHP. É o inverso direto de @ifé o mesmo que Você pode vê-lo em uso no Exemplo 4-3 .@unless ($condition)<?php if (! $condition)

Exemplo 4-3. @unless e @endunless
@unless ($user->hasPaid())
    You can complete your payment by switching to the payment tab.
@endunless

rotações

Em seguida, vamos dar uma olhada nos loops.

@for, @foreach e @while

@for@foreach, e @whilefuncionam no Blade da mesma forma que no PHP; veja os Exemplos 4-4 , 4-5 e 4-6 .

Exemplo 4-4. @for e @endfor
@for ($i = 0; $i < $talk->slotsCount(); $i++)
    The number is {{ $i }}<br>
@endfor
Exemplo 4-5. @foreach e @endforeach
@foreach ($talks as $talk)
     {{ $talk->title }} ({{ $talk->length }} minutes)<br>
@endforeach
Exemplo 4-6. @while e @endwhile
@while ($item = array_pop($items))
    {{ $item->orSomething() }}<br>
@endwhile

@forelse e @endforelse

@forelseé um @foreachque também permite que você programe um fallback se o objeto sobre o qual você está iterando estiver vazio. Nós o vimos em ação no início deste capítulo; O Exemplo 4-7 mostra outro exemplo.

Exemplo 4-7. @forelse
@forelse ($talks as $talk)
     {{ $talk->title }} ({{ $talk->length }} minutes)<br>
@empty
    No talks this day.
@endforelse

Herança de modelo

O blade fornece uma estrutura para herança de modelo que permite que as exibições se estendam, modifiquem e incluam outras exibições.

Vamos dar uma olhada em como a herança é estruturada com o Blade.

Definindo seções com @section/@show e @yield

vamoscomece com um layout Blade de nível superior, como no Exemplo 4-8 .Esta é a definição de um wrapper de página genérico no qual colocaremos posteriormente o conteúdo específico da página.

Exemplo 4-8. Disposição da lâmina
<!-- resources/views/layouts/master.blade.php -->
<html>
    <head>
        <title>Meu Site | @yield('título', 'Página inicial')</title>
    </head>
    <body>
        <div class="container">
            @yield('conteúdo')
        </div>
        @section('rodapés')
            <script src="app.js"></script>
        @mostrar
    </body>
</html>

Isso se parece um pouco com uma página HTML normal, mas você pode ver que cedemos em dois lugares ( titlecontent) e definimos uma seção em um terceiro ( footerScripts). Temos três diretivas Blade aqui: @yield('content')sozinhas, @yield('title', 'Home Page')com um padrão definido e @section/@showcom conteúdo real nela.

Embora cada um pareça um pouco diferente, todos os três funcionam essencialmente da mesma forma. Todos os três estão definindo que existe uma seção com um determinado nome (o primeiro parâmetro) que pode ser estendido posteriormente, e todos os três estão definindo o que fazer se a seção não for estendida. Eles fazem isso fornecendo um fallback de string ( 'Home Page'), nenhum fallback (que simplesmente não mostrará nada se não for estendido) ou um fallback de bloco inteiro (neste caso, <script src="app.js"></script>).

O que é diferente? Bem, claramente, @yield('content')não tem conteúdo padrão. Mas, além disso, o conteúdo padrão em @yield('title') será mostrado se nunca for estendido. Se for estendido, suas seções filhas não terão acesso programático ao valor padrão. , por outro lado, está definindo um padrão e fazendo isso de forma que seu conteúdo padrão esteja disponível para seus filhos, por meio de .@section/@show@parent

Depois de ter um layout pai como este, você pode estendê-lo em um novo arquivo de modelo, como no Exemplo 4-9 .

Exemplo 4-9. Estendendo um layout Blade
<!-- resources/views/dashboard.blade.php -->
@extends('layouts.master')

@section('título', 'Painel')

@seção('conteúdo')
    Bem-vindo ao painel do seu aplicativo!
@endsection

@section('rodapés')
    @pai
    <script src="dashboard.js"></script>
@endsection

@SHOW VERSUS @ENDSECTION

Você deve ter notado que o Exemplo 4-8 usa @section/@show, mas o Exemplo 4-9 usa @section/@endsectionQual é a diferença?

Use @showquando estiver definindo o local para uma seção, no modelo pai. Use @endsectionquando estiver definindo o conteúdo de um modelo em um modelo filho.

Essa exibição filha nos permite cobrir alguns novos conceitos na herança do Blade.

@extends

No Exemplo 4-9 , com @extends('layouts.master'), definimos que essa visualização não deve ser renderizada sozinha, mas que, em vez disso, estende outra visualização. Isso significa que seu papel é definir o conteúdo de várias seções, mas não ficar sozinho. É quase como uma série de baldes de conteúdo, em vez de uma página HTML. Esta linha também define que a visualização está estendendo vidas em resources/views/layouts/master.blade.php .

Cada arquivo deve estender apenas um outro arquivo e a @extendschamada deve ser a primeira linha do arquivo.

@section e @endsection

Com @section('title', 'Dashboard'), fornecemos nosso conteúdo para a primeira seção, title . Como o conteúdo é muito curto, em vez de usar @section@endsection, estamos usando apenas um atalho. Isso nos permite passar o conteúdo como o segundo parâmetro de @sectione depois seguir em frente. Se for um pouco desconcertante ver @sectionsem @endsection, você pode simplesmente usar a sintaxe normal.

Com @section('content')e assim, usamos a sintaxe normal para definir o conteúdo da contentseção. Vamos apenas dar uma pequena saudação por enquanto. Observe, no entanto, que quando você está usando @sectionem uma exibição filha, você termina com @endsection(ou seu alias @stop), em vez de @show, que é reservado para definir seções em exibições pai.

@pai

Finalmente, com @section('footerScripts')e sobre, usamos a sintaxe normal para definir o conteúdo da footerScriptsseção.

Mas lembre-se, na verdade definimos esse conteúdo (ou, pelo menos, seu “padrão”) já no layout mestre. Portanto, desta vez, temos duas opções: podemos substituir o conteúdo da exibição pai ou adicionar a ele.

Você pode ver que temos a opção de incluir o conteúdo do pai usando a @parentdiretiva dentro da seção. Se não o fizéssemos, o conteúdo desta seção substituiria totalmente qualquer coisa definida no pai para esta seção.

Incluindo ver parciais

Agora que estabelecemos os fundamentos da herança, há mais alguns truques que podemos executar.

@incluir

E se estivermos em uma exibição e quisermos obter outra exibição? Talvez tenhamos um botão de chamada para ação “Inscreva-se” que queremos reutilizar no site. E talvez queiramos personalizar o texto do botão toda vez que o usarmos. Dê uma olhada no Exemplo 4-10 .

Exemplo 4-10. Incluindo parciais de exibição com @include
<!-- resources/views/home.blade.php -->
<div class="content" data-page-name="{{ $pageName }}">
    <p>Veja por que você deve se inscrever em nosso aplicativo: <strong>É ótimo.</strong></p>

    @include('botão de inscrição', ['texto' => 'Veja como é bom'])
</div>

<!-- resources/views/sign-up-button.blade.php -->
<a class="button button--callout" data-page-name="{{ $pageName }}">
    <i class="exclamation-icon"></i>{{ $texto }}
</a>

@includepuxa o parcial e, opcionalmente, passa dados para ele. Observe que você não apenas pode passar dados explicitamente para uma inclusão por meio do segundo parâmetro de @include, mas também pode fazer referência a quaisquer variáveis ​​dentro do arquivo incluído que estejam disponíveis para a exibição de inclusão ( $pageName, neste exemplo). Mais uma vez, você pode fazer o que quiser, mas recomendo que considere sempre passar explicitamente todas as variáveis ​​que pretende usar, apenas para maior clareza.

Você também usa as diretivas , e , conforme mostrado @includeIfno @includeWhenExemplo 4-11 .@includeFirst

Exemplo 4-11. Incluindo exibições condicionalmente
{{-- Incluir uma visualização se existir --}}
@includeIf('sidebars.admin', ['alguns' => 'dados'])

{{-- Incluir uma visualização se uma variável passada for true-y --}}
@includeWhen($user->isAdmin(), 'sidebars.admin', ['some' => 'data'])

{{-- Incluir a primeira visualização existente de um determinado array de visualizações --}}
@includeFirst(['customs.header', 'header'], ['some' => 'data'])

@cada

Provavelmente, você pode imaginar algumas circunstâncias nas quais precisaria fazer um loop em uma matriz ou coleção e @includeuma parcial para cada item. Existe uma diretriz para isso: @each.

Digamos que temos uma barra lateral composta por módulos e queremos incluir vários módulos, cada um com um título diferente. Dê uma olhada no Exemplo 4-12 .

Exemplo 4-12. Usando parciais de exibição em um loop com @each
<!-- resources/views/sidebar.blade.php -->
<div class="sidebar">
    @each('partials.module', $modules, 'module', 'partials.empty-module')
</div>

<!-- resources/views/partials/module.blade.php -->
<div class="sidebar-module">
    <h1>{{ $module->title }}</h1>
</div>

<!-- resources/views/partials/empty-module.blade.php -->
<div class="sidebar-module">
    Sem módulos :(
</div>

Considere essa @eachsintaxe. O primeiro parâmetro é o nome da vista parcial. A segunda é a matriz ou coleção para iterar. O terceiro é o nome da variável com a qual cada item (neste caso, cada elemento do $modulesarray) será passado para a view. E o quarto parâmetro opcional é a view para mostrar se o array ou coleção está vazio (ou, opcionalmente, você pode passar uma string aqui que será usada como seu template).

Usando Pilhas

Um padrão comum que pode ser difícil de gerenciar usando as inclusões básicas do Blade é quando cada exibição em uma hierarquia de inclusão do Blade precisa adicionar algo a uma determinada seção, quase como adicionar uma entrada a uma matriz.

A situação mais comum para isso é quando certas páginas (e às vezes, mais amplamente, certas seções de um site) têm arquivos CSS e JavaScript exclusivos e específicos que precisam carregar. Imagine que você tem um arquivo CSS “global” em todo o site, um arquivo CSS de “seção de empregos” e um arquivo CSS de página “candidate-se a um emprego”.

As pilhas de Blade são construídas exatamente para esta situação. Em seu modelo pai, defina uma pilha, que é apenas um espaço reservado. Em seguida, em cada modelo filho, você pode “empurrar” as entradas para essa pilha com @push/@endpush, o que as adiciona ao final da pilha na renderização final. Você também pode usar @prepend/@endprependpara adicioná-los ao topo da pilha. O exemplo 4-13 ilustra.

Exemplo 4-13. Usando pilhas de lâminas
<!-- resources/views/layouts/app.blade.php -->
<html>
<head><!-- the head --></head>
<body>
    <!-- the rest of the page -->
    <script src="/css/global.css"></script>
    <!-- the placeholder where stack content will be placed -->
    @stack('scripts')
</body>
</html>

<!-- resources/views/jobs.blade.php -->
@extends('layouts.app')

@push('scripts')
    <!-- push something to the bottom of the stack -->
    <script src="/css/jobs.css"></script>
@endpush

<!-- resources/views/jobs/apply.blade.php -->
@extends('trabalhos')

@prepend('scripts')
    <!-- push something to the top of the stack -->
    <script src="/css/jobs--apply.css"></script>
@endprepend

Estes geram o seguinte resultado:

<html>
<head><!-- the head --></head>
<body>
    <!-- the rest of the page -->
    <script src="/css/global.css"></script>
    <!-- the placeholder where stack content will be placed -->
    <script src="/css/jobs--apply.css"></script>
    <script src="/css/jobs.css"></script>
</body>
</html>

Usando componentes e slots

O Laravel oferece outro padrão para incluir conteúdo entre visualizações, que foi introduzido na versão 5.4: componentes e slots . Os componentes fazem mais sentido em contextos quando você se encontra usando parciais de exibição e passando grandes blocos de conteúdo para eles como variáveis. Dê uma olhada no Exemplo 4-14 para ver um exemplo de modelo, ou popover, que pode alertar o usuário em resposta a um erro ou outra ação.

Exemplo 4-14. Um modal como uma visão desajeitada parcial
<!-- resources/views/partials/modal.blade.php -->
<div class="modal">
    <div>{{ $conteúdo }} </div>
    <div class="close button etc">...</div>
</div>

<!-- in another template -->
@include('parciais.modal', [
    'body' => ' <p>A senha que você forneceu não é válida. Aqui estão as regras
    para senhas válidas: [...] </p><p><a href="#">... </a></p>'
])

Isso é demais para essa variável e é o ajuste perfeito para um componente.

Componentes com slots são vistas parciais explicitamente projetadas para ter grandes partes (“slots”) destinadas a obter conteúdo do modelo de inclusão. Dê uma olhada no Exemplo 4-15 para ver como refatorar o Exemplo 4-14 com componentes e slots.

Exemplo 4-15. Um modal como componente mais apropriado com slots
<!-- resources/views/partials/modal.blade.php -->
<div class="modal">
    <div>{{ $espaço }} </div>
    <div class="close button etc">...</div>
</div>

<!-- in another template -->
@component('partials.modal')
    <p>A senha que você forneceu não é válida.
    Aqui estão as regras para senhas válidas: [...]</p>

    <p><a href="#">... </a></p>
@endcomponent

Como você pode ver no Exemplo 4-15 , a @componentdiretiva nos permite extrair nosso HTML de uma string variável apertada e de volta ao espaço do modelo. $slotvariável em nosso modelo de componente recebe qualquer conteúdo passado na @componentdiretiva.

Múltiplos slots

O método que usamos no Exemplo 4-15 é chamado de slot “padrão”; o que quer que você passe no meio @component@endcomponenté passado para a $slotvariável. Mas você também pode ter mais do que apenas o slot padrão. Vamos imaginar um modal com um título, como no Exemplo 4-16 .

Exemplo 4-16. Uma visão modal parcial com duas variáveis
<!-- resources/views/partials/modal.blade.php -->
<div class="modal">
    <div class="modal-header">{{ $title }} </div>
    <div>{{ $slot }} </div>
    <div class="close button etc">...</div>
</div>

Você pode usar a @slotdiretiva em suas @componentchamadas para passar conteúdo para slots diferentes do padrão, como você pode ver no Exemplo 4-17 .

Exemplo 4-17. Passando mais de um slot para um componente
@component('partials.modal')
    @slot('título')
        Falha na validação de senha
    @endslot

    <p>A senha que você forneceu não é válida.
    Aqui estão as regras para senhas válidas: [...]</p>

    <p><a href="#">... </a></p>
@endcomponent

E se você tiver outras variáveis ​​em sua visão que não fazem sentido como um slot, você ainda pode passar uma matriz de conteúdo como o segundo parâmetro para @component, assim como você pode com @includeDê uma olhada no Exemplo 4-18 .

Exemplo 4-18. Passando dados para um componente sem slots
@component('partials.modal', ['class' => 'perigo'])
    ...
@endcomponent

Alias ​​de um componente para ser uma diretiva

Há um truque inteligente que você pode usar para tornar seus componentes ainda mais fáceis de chamar: aliasing. Simplesmente chame Blade::component()Bladefachada — a localização mais comum é o boot()método do AppServiceProvider— e passe primeiro a localização do componente e depois o nome de sua diretiva desejada, conforme mostrado no Exemplo 4-19 .

Exemplo 4-19. Alias ​​de um componente para ser uma diretiva
// AppServiceProvider@boot
Blade::component('partials.modal', 'modal');
<!-- in a template -->
@modal
    Conteúdo modal aqui
@endmodal

IMPORTANDO FACHADAS

Esta é a primeira vez que trabalhamos com uma fachada em uma classe com namespace. Vamos abordá-los com mais profundidade mais tarde, mas saiba que se você usar fachadas em classes com namespace, que é a maioria das classes nas versões recentes do Laravel, você pode encontrar erros mostrando que a fachada não pode ser encontrada. Isso ocorre porque as fachadas são apenas classes normais com namespaces normais, mas o Laravel faz alguns truques para disponibilizá-las a partir do namespace raiz.

Então, no Exemplo 4-19 , precisaríamos importar a Illuminate\Support\Facades\Bladefachada no topo do arquivo.

Exibir compositores e injeção de serviço

Comoabordamos no Capítulo 3 , é simples passar dados para nossas visualizações a partir da definição de rota (consulte o Exemplo 4-20 ).

Exemplo 4-20. Lembrete de como passar dados para visualizações
Route::get('passing-data-to-views', function () {
    return view('dashboard')
        ->with('key', 'value');
});

Pode haver momentos, no entanto, em que você passa os mesmos dados repetidamente para várias exibições. Ou você pode encontrar-se usando um cabeçalho parcial ou algo semelhante que requer alguns dados; você terá que passar esses dados de cada definição de rota que possa carregar esse cabeçalho parcial?

Vinculando dados a exibições usando compositores de exibição

Felizmente, há uma maneira mais simples. A solução é chamada de view composer , e permite que você defina que sempre que uma determinada view for carregada, certos dados devem ser passados ​​para ela — sem que a definição de rota tenha que passar esses dados explicitamente.

Digamos que você tenha uma barra lateral em cada página, que é definida em um parcial nomeado partials.sidebarresources/views/partials/sidebar.blade.php ) e incluída em cada página. Esta barra lateral mostra uma lista das últimas sete postagens que foram publicadas em seu site. Se estiver em todas as páginas, cada definição de rota normalmente teria que pegar essa lista e passá-la, como no Exemplo 4-21 .

Exemplo 4-21. Passando dados da barra lateral de cada rota
Route::get('home', function () {
    return view('home')
        ->with('posts', Post::recent());
});

Route::get('about', function () {
    return view('about')
        ->with('posts', Post::recent());
});

Isso pode ficar irritante rapidamente. Em vez disso, vamos usar criadores de visualizações para “compartilhar” essa variável com um conjunto prescrito de visualizações. Podemos fazer isso de algumas maneiras, então vamos começar simples e avançar.

Compartilhando uma variável globalmente

Primeiro, a opção mais simples: apenas “compartilhar” globalmente uma variável com todas as visualizações em seu aplicativo, como no Exemplo 4-22