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: 1108

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 .

Exemplo 4-22. Compartilhando uma variável globalmente
// Some service provider
public function boot()
{
    ...
    view()->share('recentPosts', Post::recent());
}

Se você quiser usar view()->share(), o melhor lugar seria o boot()método de um provedor de serviços para que a ligação seja executada a cada carregamento de página. Você pode criar um personalizado ViewComposerServiceProvider(consulte o Capítulo 11 para saber mais sobre provedores de serviços), mas, por enquanto, basta colocá-lo no App\Providers\AppServiceProvidermétodo boot().

Usar view()->share()torna a variável acessível a todas as exibições em todo o aplicativo, portanto, pode ser um exagero.

Compositores de visualização com escopo de exibição com encerramentos

A próxima opção é usar um compositor de visualização baseado em fechamento para compartilhar variáveis ​​com uma única visualização, como no Exemplo 4-23 .

Exemplo 4-23. Criando um compositor de exibição baseado em encerramento
view()->composer('partials.sidebar', function ($view) {
    $view->with('recentPosts', Post::recent());
});

Como você pode ver, definimos o nome da visualização com a qual desejamos compartilhá-la no primeiro parâmetro ( partials.sidebar) e, em seguida, passamos um fechamento para o segundo parâmetro; noencerramento que usamos $view->with()para compartilhar uma variável, mas apenas com uma exibição específica.

Compositores de visualização com escopo de exibição com classes

Por fim, a opção mais flexível, mas também a mais complexa, é criar uma classe dedicada para o seu compositor de visualização.

Primeiro, vamos criar a classe view composer. Não há um lugar formalmente definido para os compositores de exibição viverem, mas os documentos recomendam App\Http\ViewComposersEntão, vamos criar App\Http\ViewComposers\RecentPostsComposercomo no Exemplo 4-24 .

Exemplo 4-24. Um compositor de visualização
<?php

namespace App\Http\ViewComposers;

use App\Post;
use Illuminate\Contracts\View\View;

class RecentPostsComposer
{
    public function compose(View $view)
    {
        $view->with('recentPosts', Post::recent());
    }
}

Como você pode ver, quando este composer é chamado, ele executa o compose()método, no qual associamos a recentPostsvariável ao resultado da execução do método Postdo modelo .recent()

Como os outros métodos de compartilhamento de variáveis, esse compositor de exibição precisa ter uma ligação em algum lugar. Novamente, você provavelmente criaria um custom ViewComposerServiceProvider, mas por enquanto, como visto no Exemplo 4-25 , vamos apenas colocá-lo no boot()método de App\Providers\AppServiceProvider.

Exemplo 4-25. Registrando um compositor de exibição no AppServiceProvider
public function boot()
{
    view()->composer(
        'partials.sidebar',
        \App\Http\ViewComposers\RecentPostsComposer::class
    );
}

Observe que essa vinculação é a mesma de um compositor de exibição baseado em fechamento, mas, em vez de passar um fechamento, estamos passando o nome da classe de nosso compositor de exibição. Agora, toda vez que o Blade renderizar a partials.sidebarexibição, ele executará automaticamente nosso provedor e passará à exibição uma recentPostsvariável definida para os resultados do recent()método em nosso Postmodelo.

Injeção de serviço de lâmina

Existem três tipos principais de dados que provavelmente injetaremos em uma exibição: coleções de dados para iterar, objetos únicos que estamos exibindo na página e serviços que geram dados ou exibições.

Com um serviço, o padrão provavelmente se parecerá com o Exemplo 4-26 , em que injetamos uma instância de nosso serviço de análise na definição de rota digitando-a na assinatura do método da rota e, em seguida, passamos para a exibição.

Exemplo 4-26. Injetando serviços em uma exibição por meio do construtor de definição de rota
Route::get('backend/sales', function (AnalyticsService $analytics) {
    return view('backend.sales-graphs')
        ->with('analytics', $analytics);
});

Assim como com os compositores de visualização, a injeção de serviço do Blade oferece um atalho conveniente para reduzir a duplicação em suas definições de rota. Normalmente, o conteúdo de uma exibição usando nosso serviço de análise pode parecer com o Exemplo 4-27 .

Exemplo 4-27. Usando um serviço de navegação injetado em uma exibição
<div class="finances-display">
     {{ $analytics->getBalance() }} / {{ $analytics->getBudget() }}
</div>

A injeção de serviço blade facilita a injeção de uma instância de uma classe do contêiner diretamente da exibição, como no Exemplo 4-28 .

Exemplo 4-28. Injetando um serviço diretamente em uma exibição
@inject('analytics', 'App\Services\Analytics')

<div class="finances-display">
     {{ $analytics->getBalance() }} / {{ $analytics->getBudget() }}
</div>

Como você pode ver, esta @injectdiretiva realmente disponibilizou uma $analyticsvariável, que usaremos posteriormente em nossa view.

O primeiro parâmetro @injecté o nome da variável que você está injetando e o segundo parâmetro é a classe ou interface da qual você deseja injetar uma instância. Isso é resolvido exatamente como quando você digita uma dependência em um construtor em outro lugar no Laravel; se você não estiver familiarizado com o funcionamento disso, consulte o Capítulo 11 para saber mais.

Assim como os compositores de visualização, a injeção de serviço Blade facilita a disponibilização de determinados dados ou funcionalidades para todas as instâncias de uma visualização, sem a necessidade de injetá-los por meio da definição de rota todas as vezes.

Diretivas de lâmina personalizada

Toda a sintaxe interna do Blade que abordamos até agora @if— @unless, e assim por diante — são chamadas de diretivas . Cada diretiva Blade é um mapeamento entre um padrão (por exemplo, e uma saída PHP (por exemplo, ).@if ($condition))<?php if ($condition): ?>

As diretivas não são apenas para o núcleo; você pode realmente criar o seu próprio. Você pode pensar que as diretivas são boas para criar pequenos atalhos para trechos maiores de código, por exemplo, usando @button('buttonName')e expandindo para um conjunto maior de botões HTML. Essa não é uma péssima ideia, mas para uma expansão de código simples como essa, talvez seja melhor incluir uma visão parcial.

Diretivas personalizadas tendem a ser mais úteis quando simplificam alguma forma de lógica repetida. Digamos que estamos cansados ​​de ter que agrupar nosso código (para verificar se um usuário está logado ou não) e queremos uma diretiva personalizada. Assim como os compositores de visualização, pode valer a pena ter um provedor de serviços personalizado para registrá-los, mas, por enquanto, vamos apenas colocá-lo no método de Dê uma olhada no Exemplo 4-29 para ver como será essa ligação.@if (auth()->guest())@ifGuestboot()App\Providers\AppServiceProvider

Exemplo 4-29. Vinculando uma diretiva Blade personalizada em um provedor de serviços
public function boot()
{
    Blade::directive('ifGuest', function () {
        return "<?php if (auth()->guest()): ?>";
    });
}

Agora registramos uma diretiva personalizada, @ifGuest, que será substituída pelo código PHP <?php if (auth()->guest()): ?>.

Isso pode parecer estranho. Você está escrevendo uma string que será retornada e executada como PHP. Mas o que isso significa é que agora você pode pegar os aspectos complexos, feios, obscuros ou repetitivos de seu código de modelo PHP e ocultá-los atrás de uma sintaxe clara, simples e expressiva.

CACHE DE RESULTADOS DE DIRETIVA PERSONALIZADA

Você pode ficar tentado a fazer alguma lógica para tornar sua diretiva personalizada mais rápida executando uma operação na ligação e, em seguida, incorporando o resultado na string retornada:

Blade::directive('ifGuest', function () {
    // Antipattern! Do not copy.
    $ifGuest = auth()->guest();
    return "<?php if ({$ifGuest}): ?>";
});

O problema com essa ideia é que ela assume que essa diretiva será recriada a cada carregamento de página. No entanto, o Blade armazena em cache de forma agressiva, então você se encontrará em uma situação ruim se tentar isso.

Parâmetros nas Diretivas de Lâmina Personalizada

E se você quiser aceitar parâmetros em sua lógica personalizada? Verifique o Exemplo 4-30 .

Exemplo 4-30. Criando uma diretiva Blade com parâmetros
// Binding
Blade::directive('newlinesToBr', function ($expression) {
    return "<?php echo nl2br({$expression}); ?>";
});

// In use
<p>@newlinesToBr($message->body)</p>

$expressionparâmetro recebido pelo encerramento representa o que estiver entre parênteses. Como você pode ver, geramos um trecho de código PHP válido e o retornamos.

ESCOPO DO PARÂMETRO $EXPRESSION ANTES DO LARAVEL 5.3

Antes do Laravel 5.3, o $expressionparâmetro também incluía os próprios parênteses . Portanto, no Exemplo 4-30 , $expression(que está $message->bodyno Laravel 5.3 e posterior) seria ($message->body), e teríamos que escrever .<?php echo nl2br{$expression}; ?>

Se você estiver constantemente escrevendo a mesma lógica condicional repetidamente, considere uma diretiva Blade.

Exemplo: usando diretivas de blade personalizadas para um aplicativo multilocatário

Vamos imaginar que estamos criando um aplicativo compatível com multilocação , o que significa que os usuários podem visitar o site em www.myapp.com , client1.myapp.com , client2.myapp.com ou em outro lugar.

Suponha que escrevemos uma classe para encapsular parte de nossa lógica de multilocação e a nomeamos ContextEssa classe irá capturar informações e lógica sobre o contexto da visita atual, como quem é o usuário autenticado e se o usuário está visitando o site público ou um subdomínio do cliente.

Provavelmente resolveremos essa Contextclasse com frequência em nossas visualizações e executaremos condicionais nela, como no Exemplo 4-31 . app('context')é um atalho para obter uma instância de uma classe do contêiner, sobre o qual aprenderemos mais no Capítulo 11 .

Exemplo 4-31. Condicionais no contexto sem uma diretiva Blade personalizada
@if (app('context')->isPublic())
    &copy; Copyright MyApp LLC
@else
    &copy; Copyright {{ app('context')->client->name }}
@endif

E se pudéssemos simplificar @if (app('context')->isPublic())para apenas @ifPublicVamos fazê-lo. Verifique o Exemplo 4-32 .

Exemplo 4-32. Condicionais no contexto com uma diretiva Blade personalizada
// Binding
Blade::directive('ifPublic', function () {
    return "<?php if (app('context')->isPublic()): ?>";
});

// In use
@ifPublic
    &copy; Copyright MyApp LLC
@else
    &copy; Copyright {{ app('context')->client->name }}
@endif

Como isso resolve uma instrução simples if, ainda podemos contar com o nativo @elsee os @endifcondicionais. Mas, se quiséssemos, também poderíamos criar uma @elseIfClientdiretiva personalizada, ou uma @ifClientdiretiva separada, ou qualquer outra coisa que quiséssemos.

Diretivas personalizadas mais fáceis para declarações “if”

Embora as diretivas Blade personalizadas sejam poderosas, o uso mais comum para elas são as ifinstruções. Portanto, há uma maneira mais simples de criar diretivas “if” personalizadas: Blade::if()O Exemplo 4-33 mostra como poderíamos refatorar o Exemplo 4-32 usando o Blade::if()método:

Exemplo 4-33. Definindo uma diretiva Blade "if" personalizada
// Binding
Blade::if('ifPublic', function () {
    return (app('context'))->isPublic();
});

Você usará as diretivas exatamente da mesma maneira, mas como pode ver, defini-las é um pouco mais simples. Em vez de digitar manualmente as chaves do PHP, você pode simplesmente escrever um fechamento que retorne um booleano.

teste

O método mais comum de testar visualizações é por meio de teste de aplicativo, o que significa que você está realmente chamando a rota que exibe as visualizações e garantindo que as visualizações tenham determinado conteúdo (consulte o Exemplo 4-34 ). Você também pode clicar em botões ou enviar formulários e garantir que seja redirecionado para uma determinada página ou que veja um determinado erro. (Você aprenderá mais sobre testes no Capítulo 12. )

Exemplo 4-34. Testando se uma exibição exibe determinado conteúdo
// EventsTest.php
public function test_list_page_shows_all_events()
{
    $event1 = factory(Event::class)->create();
    $event2 = factory(Event::class)->create();

    $this->get('events')
        ->assertSee($event1->title)
        ->assertSee($event2->title);
}

Você também pode testar se uma determinada exibição foi aprovada em um determinado conjunto de dados, que, se atingir seus objetivos de teste, é menos frágil do que verificar determinado texto na página. O Exemplo 4-35 demonstra essa abordagem.

Exemplo 4-35. Testando se uma visualização foi aprovada em determinado conteúdo
// EventsTest.php
public function test_list_page_shows_all_events()
{
    $event1 = factory(Event::class)->create();
    $event2 = factory(Event::class)->create();

    $response = $this->get('events');

    $response->assertViewHas('events', Event::all());
    $response->assertViewHasAll([
        'events' => Event::all(),
        'title' => 'Events Page',
    ]);
    $response->assertViewMissing('dogs');
}

NOMES DIFERENTES PARA MÉTODOS DE TESTE ANTERIORES AO LARAVEL 5.4

Em projetos executando versões do Laravel anteriores a 5.4, get()assertSee()deve ser substituído por visit()see().

Na versão 5.3, ganhamos a capacidade de passar um encerramento para assertViewHas(), o que significa que podemos personalizar como queremos verificar estruturas de dados mais complexas. O Exemplo 4-36 ilustra como podemos usar isso.

Exemplo 4-36. Passando um fechamento para assertViewHas ()
// EventsTest.php
public function test_list_page_shows_all_events()
{
    $event1 = factory(Event::class)->create();

    $response = $this->get("events/{ $event1->id }");

    $response->assertViewHas('event', function ($event) use ($event1) {
        return $event->id === $event1->id;
    });
}

TL;DR

Blade é o mecanismo de modelagem do Laravel. Seu foco principal é uma sintaxe clara, concisa e expressiva com poderosa herança e extensibilidade. Seus colchetes de “eco seguro” são {{}}, seus colchetes de eco desprotegidos são {!!!!}, e ele tem uma série de tags personalizadas chamadas diretivas que começam com @@if@unless, por exemplo).

Você pode definir um modelo pai e deixar “buracos” nele para o conteúdo usando @yield @section@showVocê pode então ensinar suas visualizações filhas a estendê-las usando , e definir suas seções usando Você usa para fazer referência ao conteúdo do pai do bloco.@extends('parent.view')@section@endsection@parent

Os compositores de visualização facilitam a definição de que, toda vez que uma visualização ou subvisualização específica é carregada, ela deve ter certas informações disponíveis. E a injeção de serviço permite que a própria visualização solicite dados diretamente do contêiner do aplicativo.

Fonte: https://www.oreilly.com/library/view/laravel-up/9781492041207/ch04.html


2

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 0 Comments

No comments yet! Be the first to comment

Blog Search


Categories

OUTROS (16) Variados (109) PHP (133) Laravel (171) Black Hat (3) front-end (29) linux (114) postgresql (39) Docker (28) rest (5) soap (1) webservice (6) October (1) CMS (2) node (7) backend (13) ubuntu (56) devops (25) nodejs (5) npm (3) nvm (1) git (8) firefox (1) react (7) reactnative (5) collections (1) javascript (7) reactjs (8) yarn (0) adb (1) Solid (2) blade (3) models (1) controllers (0) log (1) html (2) hardware (3) aws (14) Transcribe (2) transcription (1) google (4) ibm (1) nuance (1) PHP Swoole (5) mysql (31) macox (4) flutter (1) symfony (1) cor (1) colors (2) homeOffice (2) jobs (3) imagick (2) ec2 (1) sw (1) websocket (2) markdown (1) ckeditor (1) tecnologia (14) faceapp (1) eloquent (14) query (4) sql (40) ddd (3) nginx (9) apache (4) certbot (1) lets-encrypt (3) debian (12) liquid (1) magento (2) ruby (1) LETSENCRYPT (1) Fibonacci (1) wine (1) transaction (1) pendrive (1) boot (1) usb (1) prf (1) policia (2) federal (1) lucena (1) mongodb (4) paypal (1) payment (1) zend (1) vim (4) ciencia (6) js (1) nosql (1) java (1) JasperReports (1) phpjasper (1) covid19 (1) saude (1) athena (1) cinnamon (1) phpunit (2) binaural (1) mysqli (3) database (42) windows (6) vala (1) json (2) oracle (1) mariadb (4) dev (12) webdev (24) s3 (4) storage (1) kitematic (1) gnome (2) web (2) intel (3) piada (1) cron (2) dba (18) lumen (1) ffmpeg (2) android (2) aplicativo (1) fedora (2) shell (4) bash (3) script (3) lider (1) htm (1) csv (1) dropbox (1) db (3) combustivel (2) haru (1) presenter (1) gasolina (1) MeioAmbiente (1) Grunt (1) biologia (1) programming (22) performance (3) brain (1) smartphones (1) telefonia (1) privacidade (1) opensource (3) microg (1) iode (1) ssh (3) zsh (2) terminal (3) dracula (1) spaceship (1) mac (2) idiomas (1) laptop (2) developer (37) api (5) data (1) matematica (1) seguranca (2) 100DaysOfCode (9) hotfix (1) documentation (1) laravelphp (10) RabbitMQ (3) Elasticsearch (1) redis (2) Raspberry (4) Padrao de design (4) JQuery (1) angularjs (4) Dicas (43) Kubernetes (3) vscode (2) backup (1) angular (3) servers (2) pipelines (1) AppSec (1) DevSecOps (4) rust (1) RustLang (1) Mozilla (1) algoritimo (1) sqlite (1) Passport (2) jwt (5) security (2) translate (1) kube (2) iot (1) politica (2) bolsonaro (1) flow (1) podcast (1) Brasil (1) containers (3) traefik (1) networking (1) host (1) POO (2) microservices (2) bug (1) cqrs (1) arquitetura (3) Architecture (4) sail (3) militar (1) artigo (1) economia (1) forcas armadas (1) ffaa (1) autenticacao (2) autorizacao (2) authentication (4) authorization (3) NoCookies (1) wsl (4) memcached (1) macos (2) unix (2) kali-linux (1) linux-tools (5) apple (1) noticias (2) composer (1) rancher (1) k8s (1) escopos (1) orm (1) jenkins (4) github (5) gitlab (3) queue (1) Passwordless (1) sonarqube (1) phpswoole (1) laraveloctane (1) Swoole (1) Swoole (1) octane (1) Structurizr (1) Diagramas (1) c4 (1) c4-models (1) compactar (1) compression (1) messaging (1) restfull (1) eventdrive (1) services (1) http (1) Monolith (1) microservice (1) historia (1) educacao (1) cavalotroia (1) OOD (0) odd (1) chatgpt (1) openai (3) vicuna (1) llama (1) gpt (1) transformers (1) pytorch (1) tensorflow (1) akitando (1) ia (1) nvidia (1) agi (1) guard (1) multiple_authen (2) rpi (1) auth (1) auth (1) livros (2) ElonMusk (2) Oh My Zsh (1) Manjaro (1) BigLinux (2) ArchLinux (1) Migration (1) Error (1) Monitor (1) Filament (1) LaravelFilament (1) replication (1) phpfpm (1) cache (1) vpn (1) l2tp (1) zorin-os (1) optimization (1) scheduling (1) monitoring (2) linkedin (1) community (1) inteligencia-artificial (2) wsl2 (1) maps (1) API_KEY_GOOGLE_MAPS (1) repmgr (1) altadisponibilidade (1) banco (1) modelagemdedados (1) inteligenciadedados (4) governancadedados (1) bancodedados (2) Observability (1) picpay (1) ecommerce (1) Curisidades (1) Samurai (1) KubeCon (1) GitOps (1) Axios (1) Fetch (1) Deepin (1) vue (4) nuxt (1) PKCE (1) Oauth2 (2) webhook (1) TypeScript (1) tailwind (1) gource (2)

New Articles



Get Latest Updates by Email