The book "Laravel. Complete guide. 2nd edition

imageHello, habrozhiteli! What sets Laravel apart from other PHP frameworks? Speed ​​and simplicity. Rapid application development, an extensive ecosystem, and the Laravel toolkit allow you to quickly create sites and applications with clean, readable code.

Matt Staffer, a renowned teacher and lead developer, offers both a general overview of the framework and specific examples of working with it. The book will help experienced PHP developers quickly enter a new topic to implement a project on Laravel. The publication also covers the topics of Laravel Dusk and Horizon, collects information about community resources and other packages that are not part of the Laravel core. In this book you will find: • Tools for collecting, checking, normalizing, filtering user data • Blade, a powerful Laravel custom template engine • Expressive Eloquent ORM model for working with application databases • Information about the role of the Illuminate Request object in the application life cycle • PHPUnit, Mockery and Dusk for testing your PHP code • Tools for writing JSON and RESTful API • Interfaces for accessing the file system, sessions, cookies,caches and search • Implementing queues, jobs, events, and publishing WebSocket events

Blade Template Engine


PHP as a template language functions relatively well. But it has its drawbacks, so you cannot use <? Php inline everywhere. Most modern frameworks have their own template language.

Laravel offers its own Blade template engine based on the .NET Razor engine. It has a concise syntax, is fairly understandable, accompanied by a powerful and intuitive inheritance model and easy extensibility.

You can quickly familiarize yourself with what Blade looks like in Example 4.1.

Example 4.1 Blade Examples

<h1>{{ $group->title }}</h1>
{!! $group->heroImageHtml() !!}

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

As you can see, the Blade code uses curly braces for Echo and an agreement in which its user tags, called "directives", are prefixed with @. You will apply directives for all of your management structures, as well as for inheritance and any custom functions you want to add.

The Blade syntax is clean and concise, so working with it is easier and more enjoyable than with alternatives. But at the moment when you need something complicated in your templates - nested inheritance, complex conditions or recursion - the engine shows its best side. Like the best components of Laravel, it simplifies and makes access to heavy application requirements.

In addition, since all Blade syntax is compiled into regular PHP code and then cached, it is fast and allows you to use native PHP in your files of this engine if desired. However, I would recommend avoiding using PHP when it’s possible at all — usually if you need to do something that’s not possible with Blade or its user directive, this does not apply to the template.

Data display


As you can see in Example 4.1, the brackets {{and}} are used to wrap the PHP code that you would like to display. The code {{$ $ variable}} acts like <? = $ Variable?> In simple PHP.

However, there is a difference: Blade shields all mappings by default with the htmlentities () PHP function to protect your users from pasting malicious scripts. This means that {{$ variable}} is functionally equivalent to <? = Htmlentities ($ variable)?>. If you do not want to escape the output, use {!!! and !!} instead.
{{ }} -

, Blade ({{}}) -. Laravel , Blade Handlebars?

Blade {{ @. , , :

// Blade; $bladeVariable
//
{{ $bladeVariable }}

// @ "{{ handlebarsVariable }}"
//
@{{ handlebarsVariable }}

verbatim( http://bit.ly/2OnrPRP ).

Governing structures


Most control structures in Blade will be familiar. Many directly duplicate the name and structure of the same tag in PHP.

There are a few helpers for convenience, but overall the control structures look cleaner than in PHP.

Conditional Constructions


Consider the logical structure of management.

@if

The expression @if ($ condition) in Blade compiles to <? Php if ($ condition):?>.else, elseif and endif- with exactly the same syntax style in PHP. Take a look at

Example 4.2. Example 4.2. @ifelse, elseif and 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

As with PHP's own conditional expressions, you can mix and combine them as you like. They have no particular logic; There is an analyzer with a search in the form @if ($ condition) and replacement with the corresponding PHP code.

@unless @endunless

@unless, on the other hand, is a new syntax that has no direct equivalent in PHP. This is the opposite of @if. @unless ($ condition) is the same as <? php if (! $ condition). You can see this in Example 4.3.

Example 4.3 @unless and @endunless

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

Cycles


Next, consider the cycles.

@for, @foreach @while

for, foreach and whilework in Blade in the same way as in PHP (examples 4.4–4.6).

Example 4.4for and @endfor

@for ($i = 0; $i < $talk->slotsCount(); $i++)
      The number is {{ $i }}<br>
@endfor

Example 4.5 foreach and @endforeach

@foreach ($talks as $talk)
       • {{ $talk->title }} ({{ $talk->length }} minutes)<br>
@endforeach

Example 4.6. while and @endwhile

@while ($item = array_pop($items))
       {{ $item->orSomething() }}<br>
@endwhile

@forelse @endforelse

forelse is foreach, which can be executed even if the object you are looking for is empty. We saw this in action at the beginning of the chapter. Example 4.7 shows another option.

Example 4.7.forelse

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

VARIABLE $ LOOP IN DIRECTIVES FOREACHAnd @FORELSE

Directivesforeach and forelse (introduced in Laravel 5.3) adds the $ loop variable, which is not available in PHP foreach loops. When used inside a loopforeach or forelse stdClass .

• index — 0 ; 0 — « ».

• iteration — 1 ; 1 — « ».

• remaining — , .

• count — .

• first — , , .

• last — , , .

• depth — «» : 1 , 2 . .

• parent — $loop , foreach; otherwise null.

Here is an example of how this works:

<ul>
@foreach ($pages as $page)
       <li>{{ $loop->iteration }}: {{ $page->title }}
             @if ($page->hasChildren())
             <ul>
             @foreach ($page->children() as $child)
             <li>{{ $loop->parent->iteration }}
                   .{{ $loop->iteration }}:
                   {{ $child->title }}</li>
             @endforeach
             </ul>
             @endif
       </li>
@endforeach
</ul>

Template Inheritance


Blade provides a template inheritance framework that allows views to expand, modify, and include other views.

Let's see how inheritance is structured with Blade.

Defining sections of a page using the @ section / @ show directives and yield


Let's start with the top-level Blade layout, as in Example 4.8. This is the definition of a universal page wrapper in which we will later place page-specific content.

Example 4.8. Blade Structure

<!-- resources/views/layouts/master.blade.php -->
<html>
       <head>
              <title>My Site | @yield('title', 'Home Page')</title>
       </head>
       <body>
              <div class="container">
                    @yield('content')
              </div>
              @section('footerScripts')
                     <script src="app.js"></script>
              @show
       </body>
</html>

This resembles a regular HTML page, but you can see yield in two places (title and content), and we defined section in the third (footerScripts). Here we have three Blade directives: onlyyield('content'), yield('title', 'Home Page') with the default value and @ section / @ show with the actual content in it.

Although they look a bit different, they function essentially the same. All three determine that there is a section with a given name (the first parameter) that can be expanded later, and what to do if the section has not been expanded. They do this either with a return line ('Home Page'), or without a return (nothing will simply be displayed if the directive is not expanded), or with the return of the entire block (in this case).

What is the difference? Atyield('content') no default content. Besides, inyield('title') it will be displayed only if the directive is not expanded. Otherwise, its child sections will not have programmatic access to the default value. @ section / @ show simultaneously defines the default value and makes its contents accessible to its children via @parent.

If you have such a parent layout, you can expand it in a new template file, as in example 4.9.

Example 4.9. Blade Layout Extension

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

@section('title', 'Dashboard')

@section('content')
       Welcome to your application dashboard!
@endsection

@section('footerScripts')
      @parent
      <script src="dashboard.js"></script>
@endsection

This child view allows us to show you some new concepts of Blade inheritance.

@extends

In Example 4.9, using @extends ('layouts.master'), we determine that this view should not be displayed by itself, but instead extends another view. This means that its role is to establish the content of various sections, but not to work alone. More like a series of content blocks than an HTML page. The line also determines that the view it extends is located at resources / views / layouts / master.blade.php.

Each file must expand only one other file, and the @extends call must be the first line of the file.

@section @endsection

Using @section ('title', 'Dashboard') we provide our content for the first section, title. Since the content is very short, instead of @section and @endsection we use an abbreviated form. This allows you to pass the content as the second @section parameter, and then move on. If you are a little confused with @section without @endsection, you can use the usual syntax.

From @section ('content') onwards, we use the usual syntax to define the contents of the content section. Until we insert a little greeting. However, note: when you use @section in a child view, you end with @endsection (or its aliasstop) instead show, which is reserved for defining sections in parent views.

@parent

From @section ('footerScripts') onwards, we use the usual syntax to define the contents of the footerScripts section.

Remember that we actually defined this content (or at least its “default value”) already in the main layout. So this time we have two options: either overwrite the contents from the parent view, or add to it.
You can see that we have the ability to include content from the parent view using the @parent directive inside this section. Otherwise, the contents of the section will be completely rewritten with everything that is defined in the parent of this section.

Inclusion of presentation components


Now that we’ve figured out the basics of inheritance, a few more tricks can be used.

@include

What if we are in one view and want to use another? Perhaps there is a registration button, which is desirable to re-add throughout the site. And maybe I want to select the button text every time we use it. Take a look at Example 4.10.

Example 4.10. Include view components withinclude

<!-- resources/views/home.blade.php -->
<div class="content" data-page-name="{{ $pageName }}">
      <p>Here's why you should sign up for our app: <strong>It's Great.</strong></p>

      @include('sign-up-button', ['text' => 'See just how great it is'])
</div>

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

includepulls up a component and transfers data to it (optional). Please note that you can not only explicitly pass data for inclusion through the second parameterinclude, but also refer to any variables in the included file that are available for the included view (in this example, $ pageName). You can do whatever you want, but I would recommend for clarity to always pass each variable that you intend to apply.

You can also use directivesincludeIf includeWhen and includeFirst, as shown in Example 4.11.

Example 4.11. Include conditional views

{{--  ,    --}}
@includeIf('sidebars.admin', ['some' => 'data'])

{{--  ,     true --}}
@includeWhen($user->isAdmin(), 'sidebars.admin', ['some' => 'data'])

{{--        --}}
@includeFirst(['customs.header', 'header'], ['some' => 'data'])

@each

You can imagine circumstances when you need to iterate over an array, a collection and includepart for each item. There is a directive for this.each.

Let's say we have a side modular panel and we want to include several modules with their own name. Take a look at Example 4.12.

Example 4.12. Using view components in a loop witheach

<!-- 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">
      No modules :(
</div>

Consider the syntax each. The first parameter is the name of the component of the view. The second is an array or collection for iteration. Third, the name of the variable under which each element (in this case, each element in the $ modules array) will be passed to the view. And the optional fourth parameter is a view showing whether the array or collection is empty (or if you wish, you can pass a string here that will be used as your template).

Using stacks


The generic template may be difficult to manage with the basic Blade — when each view in the Blade hierarchy needs to add something to a specific section — much like adding an entry to an array.

The most common situation is when certain pages (and sometimes in a broader sense certain sections of the site) have specific unique CSS and JavaScript files that they need to load. Imagine that you have a “global” CSS file for the entire site, a CSS file for the job section and a CSS file for the “Get a Job” page.

Blade stacks are made for just that. In the parent template, define a placeholder stack. Then, in each child template, you can “push” records there usingpush/ @ endpush, which adds them to the end of the stack in the final image. You can also use @ prepend / @ endprepend to add them to the beginning. Example 4.13 illustrates this.

Example 4.13. Using Blade Stacks

<!-- resources/views/layouts/app.blade.php -->
<html>
<head><!--  --></head>
<body>
       <!--    -->
       <script src="/css/global.css"></script>
       <!-- ,       -->
       @stack('scripts')
</body>
</html>

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

@push('scripts')
        <!--  -    -->
        <script src="/css/jobs.css"></script>
@endpush

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

@prepend('scripts')
       <!--  -    -->
       <script src="/css/jobs--apply.css"></script>

@endprepend

This leads to the following result:

<html>
<head><!--  --></head>
<body>
       <!--    -->
       <script src="/css/global.css"></script>
       <!-- ,       -->
       <script src="/css/jobs--apply.css"></script>
       <script src="/css/jobs.css"></script>
</body>
</html>

Using components and slots


Laravel offers another template for including content between views, which was introduced in 5.4: components and slots. The former are most effective in contexts when you use component views and pass large portions of content into them as variables. Look at Example 4.14 for an illustration of a model or tooltip that might alert the user to an error or other action.

Example 4.14. A modal window is a bad example of a component view

<!-- resources/views/partials/modal.blade.php -->
<div class="modal">
      <div>{{ $content }}</div>
      <div class="close button etc">...</div>
</div>

<!--    -->
@include('partials.modal', [
       'body' => '<p>The password you have provided is not valid. Here are the rules
       for valid passwords: [...]</p><p><a href="#">...</a></p>'
])

This is too much for such a variable and is ideal for a component.

Components with slots are components of views that are designed to include large portions (“slots”) for retrieving content from an included template. Example 4.15 shows how to reverse engineer the code from example 4.14 using components and slots.

Example 4.15. Modal window as a more suitable component with slots

<!-- resources/views/partials/modal.blade.php -->
<div class="modal">
      <div>{{ $slot }}</div>
      <div class="close button etc">...</div>
</div>

<!--    -->
@component('partials.modal')
        <p>The password you have provided is not valid.
        Here are the rules for valid passwords: [...]</p>

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

As you can see in Example 4.15, the directive componentallows you to extract our HTML code from a compressed string of a variable and returns to the template space. The $ slot variable in the template of our component receives any content transferred tocomponent.

Compound slots


The method that we used in Example 4.15 is called the “default” slot; everything you pass betweencomponentand @endcomponent, passed to the $ slot variable. But you can also have more than just a default slot. Imagine a modal window with a title, as in example 4.16.

Example 4.16. Component of a modal representation with two variables

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

You can use the directive slot in their challenges componentto transfer content to slots other than the default, as shown in Example 4.17.

Example 4.17. Transfer more than one slot to a component

@component('partials.modal')
        @slot('title')
               Password validation failure
        @endslot

        <p>The password you have provided is not valid.
        Here are the rules for valid passwords: [...]</p>

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

And if in your view there are other variables that are meaningless as a slot, you can still pass an array of contents as the second parameter to component same as with include. Take a look at Example 4.18.

Example 4.18. Passing data to a component without slots

@component('partials.modal', ['class' => 'danger'])
         ...
@endcomponent

Naming a component as a directive


There is a trick to simplify the components for the call: aliases. Just call Blade :: component () on the Blade facade - the most common is the AppServiceProvider boot () method - and pass it the location of the component and then the name of the desired directive, as shown in Example 4.19.

Example 4.19. Pseudonymizing a component as a directive

// AppServiceProvider@boot
Blade::component('partials.modal', 'modal');

<!--   -->
@modal
         Modal content here
@endmodal


»More information about the book can be found on the publisher’s website
» Contents
» Excerpt

For Khabrozhiteley 25% discount on the coupon - Laravel

Upon the payment of the paper version of the book, an electronic book is sent by e-mail.

All Articles