该书“ Laravel。完整指南。第二版

图片您好,habrozhiteli!是什么让Laravel与其他PHP框架区分开?速度和简便性。快速的应用程序开发,广泛的生态系统和Laravel工具包使您可以使用清晰易读的代码快速创建站点和应用程序。

著名的老师兼首席开发人员Matt Staffer提供了该框架的一般概述以及使用该框架的具体示例。这本书将帮助经验丰富的PHP开发人员快速输入一个新主题,以在Laravel上实施一个项目。该出版物还涵盖了Laravel Dusk和Horizo​​n的主题,收集了有关社区资源和Laravel核心以外的其他软件包的信息。在本书中,您将找到:•用于收集,检查,规范化,过滤用户数据的工具•Blade,功能强大的Laravel自定义模板引擎•用于处理应用程序数据库的高效Eloquent ORM模型•有关在应用程序生命周期中Illuminate Request对象的作用的信息•PHPUnit,用于测试PHP代码的Mockery和Dusk•用于编写JSON和RESTful API的工具•用于访问文件系统,会话,Cookie,缓存和搜索•实现队列,作业,事件和发布WebSocket事件

刀片模板引擎


PHP作为模板语言,功能相对较好。但是它有其缺点,因此您不能在任何地方都使用<?Php内联。大多数现代框架都有自己的模板语言。

Laravel提供了自己的基于.NET Razor引擎的Blade模板引擎。它具有简洁的语法,相当容易理解,并伴随着强大而直观的继承模型以及易于扩展的特性。

您可以快速熟悉示例4.1中Blade的外观。

示例4.1 刀片实例

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

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

如您所见,Blade代码对Echo使用大括号,并且在协议中将其用户标签(称为“指令”)的前缀为@。您将对所有管理结构,继承和要添加的任何自定义函数应用指令。

Blade语法简洁明了,因此与替代方法相比,使用它更容易且更有趣。但是目前,当您需要模板中的复杂内容(嵌套继承,复杂条件或递归)时,引擎将展现出其最佳方面。像Laravel的最佳组件一样,它可以简化并满足繁重的应用程序需求。

另外,由于所有Blade语法都被编译为常规的PHP代码,然后进行缓存,因此它速度很快,并且允许您根据需要在此引擎的文件中使用本机PHP。但是,我建议您尽可能避免使用PHP-通常,如果您需要使用Blade或其用户指令无法执行某些操作,则此操作不适用于模板。

数据显示


如例4.1所示,方括号{{and}}用于包装要显示的PHP代码。在简单的PHP中,代码{{$ $ variable}}的作用类似于<?= $ Variable?>。

但是,两者之间存在差异:默认情况下,Blade用htmlentities()PHP函数屏蔽所有映射,以保护您的用户免于粘贴恶意脚本。这意味着{{$ variable}}在功能上等效于<?= Htmlentities($变量)?>。如果您不想转义输出,请使用{!!!和!!}。
{{ }} -

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

Blade {{ @. , , :

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

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

verbatimhttp://bit.ly/2OnrPRP)。

治理结构


Blade中的大多数控制结构都是熟悉的。许多代码直接在PHP中重复相同标签的名称和结构。

为了方便起见,有一些帮助程序,但是总体而言,控制结构看起来比PHP中的干净。

条件构造


考虑管理的逻辑结构。

@if

Blade中的@if($条件)表达式编译为<?Php if($条件):?>。其他其他如果和 万一-在PHP中具有完全相同的语法样式。

例4.2,例4.2。@如果其他其他如果和 万一

@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

与PHP自己的条件表达式一样,您可以根据需要混合和组合它们。他们没有特别的逻辑。有一个分析器,其搜索形式为@if($条件),并用相应的PHP代码替换。

@unless @endunless

另一方面,@除非是在PHP中没有直接等效项的新语法。这与@if相反。@unless($条件)与<?php if(!$条件)相同。您可以在示例4.3中看到这一点。

范例4.3 @unless和@endunless

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

周期数


接下来,考虑周期。

@for, @foreach @while

对于前言在Blade中工作的方式与在PHP中一样(示例4.4–4.6)。

示例4.4对于 和@endfor

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

示例4.5 前言 和@endforeach

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

示例4.6 和@endwhile

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

@forelse @endforelse

对于否则是 前言,即使您要查找的对象为空也可以执行。我们在本章开始时看到了这一点。例4.7显示了另一个选项。

示例4.7对于其他

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

指令中的变量$循环 前瞻和@FORELSE

指令前言对于else(在Laravel 5.3中引入)添加了$循环变量,在PHP foreach循环中不可用。在循环内使用时前言 要么 对于else stdClass .

• index — 0 ; 0 — « ».

• iteration — 1 ; 1 — « ».

• remaining — , .

• count — .

• first — , , .

• last — , , .

• depth — «» : 1 , 2 . .

• parent — $loop , foreach; 否则为null。

这是一个如何工作的示例:

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

模板继承


Blade提供了模板继承框架,该框架允许视图扩展,修改和包含其他视图。

让我们看看Blade是如何构造继承的。

使用@ section / @ show指令和


让我们从示例Blade的顶层Blade布局开始。这是通用页面包装程序的定义,稍后我们将在其中放置特定于页面的内容。

示例4.8 叶片结构

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

这类似于常规的HTML页面,但是您可以在两个地方(标题和内容)看到yield,并且在第三处定义了section(footerScripts)。这里我们有三个Blade指令:仅('内容'), (“标题”,“首页”)和默认值,@部分/ @显示其中的实际内容。

尽管它们看起来有些不同,但是它们的功能基本相同。这三个参数都确定存在一个具有给定名称(第一个参数)的节,该节可以在以后展开,以及如果节未展开该怎么办。他们要么使用返回行(“主页”),要么不返回(如果未扩展指令,则不会显示任何内容),或者返回整个块(在这种情况下)来执行此操作。

有什么区别?(“内容”)无默认内容。此外,在(“标题”),仅当指令未扩展时才会显示。否则,其子节将无法以编程方式访问默认值。 @ section / @ show同时定义了默认值,并使其子元素可以通过@parent访问其默认值。

如果您有这样的父布局,则可以在示例模板4.9中将其展开到新的模板文件中。

示例4.9刀片布局扩展

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

此子视图使我们可以向您展示Blade继承的一些新概念。

@extends

在示例4.9中,使用@extends('layouts.master'),我们确定该视图不应单独显示,而应扩展另一个视图。这意味着它的作用是确定各个部分的内容,而不是单独工作。它比HTML页面更像一系列内容块。该行还确定其扩展的视图位于资源/视图/布局/master.blade.php中。

每个文件只能扩展另一个文件,并且@extends调用必须是文件的第一行。

@section @endsection

使用@section(“标题”,“仪表板”),我们为第一部分标题提供了内容。由于内容非常简短,因此我们使用缩写形式代替@section和@endsection。这使您可以将内容作为第二个@section参数传递,然后继续。如果您对不带@endsection的@section感到困惑,则可以使用通常的语法。

从@section('content')开始,我们使用常规语法定义content部分的内容。直到我们插入一点问候。但是请注意:在子视图中使用@section时,以@endsection(或其别名)结尾)代替 显示,保留用于在父视图中定义节。

@parent

从@section('footerScripts')开始,我们使用常规语法定义footerScripts部分的内容。

请记住,我们实际上已经在主布局中定义了此内容(或至少是其“默认值”)。因此,这次我们有两个选择:要么覆盖父视图的内容,要么添加它。
您可以看到,我们可以使用本节中的@parent指令从父视图中包含内容。否则,该部分的内容将被本部分的父级中定义的所有内容完全重写。

包含演示组件


现在我们已经了解了继承的基础,可以使用更多技巧。

@include

如果我们处于一种观点并且想要使用另一种观点怎么办?也许有一个注册按钮,希望在整个站点中重新添加。也许我想在每次使用按钮时选择它。看一下示例4.10。

示例4.10 包含视图组件包括

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

包括提取组件并将数据传输到该组件(可选)。请注意,您不仅可以通过第二个参数显式传递要包含的数据包括,还可以引用包含文件中可用于包含视图的任何变量(在本示例中为$ pageName)。您可以做任何您想做的事,但是为了清楚起见,我建议您始终传递要应用的每个变量。

您也可以使用指令包括如果 包括什么时候和 包括首先,如示例4.11所示。

示例4.11 包括条件视图

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

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

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

@each

您可以想像一下需要迭代数组,集合和 包括每个项目的一部分。为此有一个指令。

假设我们有一个侧面模块化面板,我们想包含几个具有自己名称的模块。看例4.12。

示例4.12 通过以下方式循环使用视图组件

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

考虑语法 第一个参数是视图组件的名称。第二个是用于迭代的数组或集合。第三,将每个元素(在本例中为$ modules数组中的每个元素)传递给视图的变量名。第四个可选参数是一个视图,该视图显示数组或集合是否为空(或者,如果您愿意,您可以在此处传递将用作模板的字符串)。

使用堆栈


使用基本Blade可能难以管理通用模板(当Blade层次结构中的每个视图都需要向特定部分添加内容时),就像向数组添加条目一样。

最常见的情况是某些页面(有时从广义上讲有时是网站的某些部分)具有需要加载的特定唯一CSS和JavaScript文件。假设您有一个用于整个站点的“全局” CSS文件,一个用于工作部分的CSS文件以及一个“获取工作”页面的CSS文件。

刀片堆栈就是为此而制造的。在父模板中,定义一个占位符堆栈。然后,在每个子模板中,您可以使用/ @ endpush,将它们添加到最终图像中堆栈的末尾。您也可以使用@ prepend / @ endprepend将它们添加到开头。例4.13说明了这一点。

示例4.13 使用刀片堆栈

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

这导致以下结果:

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

使用组件和插槽


Laravel提供了另一个在视图之间包含内容的模板,该模板在5.4中引入:组件和插槽。当您使用组件视图并将大部分内容作为变量传递到它们中时,前者在上下文中最有效。请参见示例4.14,以获取模型或工具提示的插图,该模型或工具提示可能会警告用户错误或其他操作。

示例4.14 模态窗口是组件视图的不良示例

<!-- 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>'
])

对于这样的变量来说,这太多了,对于组件来说是理想的选择。

带有插槽的组件是视图的组件,这些视图被设计为包括大部分(“插槽”),用于从包含的模板中检索内容。例4.15显示了如何使用组件和插槽对例4.14中的代码进行反向工程。

示例4.15 模态窗口作为更合适的带有插槽的组件

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

如例4.15所示,指令 零件允许您从变量的压缩字符串中提取HTML代码,然后返回模板空间。我们组件模板中的$ slot变量接收传输到的任何内容零件

复合插槽


在例4.15中使用的方法称为“默认”插槽。你之间传递的一切零件和@endcomponent,传递给$ slot变量。但是您还可以拥有多个默认插槽。想象一个带有标题的模态窗口,如示例4.16所示。

示例4.16 具有两个变量的模态表示的组成部分

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

您可以使用指令 插槽 在他们的挑战中 零件将内容传输到默认插槽以外的插槽,如示例4.17所示。

示例4.17 将多个插槽转移到一个组件

@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

并且,如果您认为还有其他变量作为槽没有意义,则您仍然可以将内容数组作为第二个参数传递给 零件包括看例4.18。

示例4.18 将数据传递到没有插槽的组件

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

将组件命名为指令


有一个技巧可以简化调用的组件:别名。只需在Blade外观上调用Blade :: component()-最常见的是AppServiceProvider boot()方法-并向其传递组件的位置,然后传递所需指令的名称,如示例4.19所示。

示例4.19 将组件假化为指令

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

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


»有关这本书的更多信息,请访问出版商的网站
» 目录
» Khabrozhiteley的节录:

优惠券可享受25%的折扣-Laravel

支付纸质版本后,会通过电子邮件发送电子图书。

All Articles