Laravel 编码技巧 - 视图

作者: 温新

图书: 【Laravel 编码技巧】

阅读: 167

时间: 2024-03-01 02:08:00

foreach 语句中使用 $loop 变量

foreach 循环中,使用 $loop 变量来查看当前是否是第一次 / 最后一次循环。

@foreach ($users as $user)
     @if ($loop->first)
        This is the first iteration.
     @endif

     @if ($loop->last)
        This is the last iteration.
     @endif

     <p>This is user {{ $user->id }}</p>
@endforeach

同样也有诸如 $loop->iteration$loop->count 等属性。可以在 官方文档中查看更多相关内容。

你可以使用 Blade 生成 HTML 以外的内容

你可以用它来生成任何你想要的动态字符串或文件。例如,shell 脚本或站点地图文件。

你只需要在视图上调用 render() 方法就可以得到字符串形式的结果。

$script = view('deploy-script')->render();

$ssh = $this->createSshConnection();

info("Executing deploy script...");
$process = $ssh->execute(explode("\n", $script));

Blade 组件的简短属性语法

从 Laravel 9.32 开始

当前语法:

<x-profile :user-id="$userId"></x-profile>

简短语法:

<x-profile :$userId></x-profile>

多视图共享一个变量

你是否曾经需要在 Laravel 中与多个视图共享一个变量?这里有一个简单的解决方案

use App\Models\Post;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        if (Schema::hasTable('posts')) {
            View::share('recentPosts', Post::latest()->take(3)->get());
        }
    }
}

视图文件是否存在?

你可以在加载视图文件之前检查它是否存在。

if (view()->exists('custom.page')) {
    // 加载视图
}

你甚至可以加载一个视图数组,只有第一个存在的视图才会被实际加载。

return view()->first(['custom.dashboard', 'dashboard'], $data);

视图错误代码页面

如果你想为一些特殊的 HTTP 返回码建立特定的错误页面,比如 500 —— 只需要使用该码值创建视图文件,比如 resources/views/errors/500.blade.php ,或者是 403.blade.php 等等,这些视图会在对应的错误码出现时自动被加载。

不带控制器的视图

如果你想让 route 只显示某个视图,不要创建 Controller 方法,只要使用 Route::view()函数就可以了。

Route::get('about', 'TextsController@about');

class TextsController extends Controller
{
    public function about()
    {
        return view('texts.about');
    }
}

// 可以这做
Route::view('about', 'texts.about');

Blade @auth 指令

使用 @auth 指令代替if语句来检查登录用户。

典型方式:

@if(auth()->user())
    // 用户已通过身份验证。
@endif

auth 写法

@auth
    // 用户已通过身份验证。
@endauth

相反的是 @guest 指令:

@guest
    // 用户未通过身份验证。
@endguest

Blade 中的两级 $loop 变量

你甚至可以在 Blade 视图的二级 foreach 循环中使用 $loop 变量来表示外层的循环变量。

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

创建你自己的 Blade 指令

这是一个简单的方法,只需在 app/Providers/AppServiceProvider.php 中添加你自己的方法。例如,如果你想用换行符替换<br>标签:

<textarea>@br2nl($post->post_text)</textarea>

将这个指令添加到AppServiceProvider的boot()方法中:

public function boot()
{
    Blade::directive('br2nl', function ($string) {
        return "<?php echo preg_replace('/\<br(\s*)?\/?\>/i', \"\n\", $string); ?>";
    });
}

视图指令 IncludeIf IncludeWhen IncludeFirst

如果你不确定 Blade 文件是否存在,你可以使用这些条件指令。 仅当 Blade 文件存在时载入 header:

@includeIf('partials.header')

仅当用户的 role_id == 1 的时候载入 header:

@includeWhen(auth()->user()->role_id == 1, 'partials.header')

尝试加载 adminlte.header ,如果不存在,则加载 default.header:

@includeFirst('adminlte.header', 'default.header')

使用 Laravel Blade-X 变量绑定来节省更多空间

// 使用 include,旧方法
@include("components.post", ["title" => $post->title])

// 使用 Blade-X
<x-post link="{{ $post->title }}" />

// 使用 Blade-X 变量绑定
<x-post :link="$post->title" />

Blade 组件属性

// button.blade.php
@props(['rounded' => false])

<button {{ $attributes->class([
    'bg-red-100 text-red-800',
    'rounded' => $rounded
    ]) }}>
    {{ $slot }}
</button>

// view.blade.php
// Non-rounded:
<x-button>Submit</x-button>

// Rounded:
<x-button rounded>Submit</x-button>

Blade 自动类型提示

@php
    /* @var App\Models\User $user */
@endphp

<div>
    // 你的 ide 将 typehint 属性为您
    {{$user->email}}
</div>

组件语法提示

在组件参数之前传入 : 你可以直接传入变量而不需要使用 {{}}表达式

<x-navbar title="{{ $title }}"/>
    
// 你可以做的
<x-navbar :title="$title"/>

自动高亮导航链接

当URL完全匹配时,自动高亮导航链接,或者传递路径或路由名称模式。

一个带有请求和 CSS 类帮助器的Blade组件使其非常简单地显示活动/非活动状态。

class NavLink extends Component
{
    public function __construct($href, $active = null)
    {
        $this->href = $href;
        $this->active = $active ?? $href;
    }

    public function render(): View
    {
        $classes = ['font-medium', 'py-2', 'text-primary' => $this->isActive()];

        return view('components.nav-link', [
            'class' => Arr::toCssClasses($classes);
        ]);
    }

    protected function isActive(): bool
    {
        if (is_bool($this->active)) {
            return $this->active;
        }

        if (request()->is($this->active)) {
            return true;
        }

        if (request()->fullUrlIs($this->active)) {
            return true;
        }

        return request()->routeIs($this->active);
    }
}
<a href="{{ $href }}" {{ $attributes->class($class) }}>
    {{ $slot }}
</a>
<x-nav-link :href="route('projects.index')">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" active="projects.*">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" active="projects/*">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" :active="$tab = 'projects'">Projects</x-nav-link>

简化循环

你知道 Blade @each 指令可以帮助清理模板中的循环吗?

// 好的
@foreach($item in $items)
    <div>
        <p>Name: {{ $item->name }}
        <p>Price: {{ $item->price }}
    </div>
@endforeach

// 更好(HTML提取为部分)
@each('partials.item', $items, 'item')

整理 Blade 的简单方法

这是一个清理Blade视图的简单方法!

使用forelse循环,而不是嵌套在if语句中的foreach循环。

<!-- if/loop combination -->
@if ($orders->count())
    @foreach($orders as $order)
        <div>
            {{ $order->id }}
        </div>
    @endforeach
@else
    <p>您还没有下过订单。</p>
@endif

<!-- Forelse alternative -->
@forelse($orders as $order)
    <div>
        {{ $order->id }}
    </div>
@empty
    <p>您还没有下过订单。</p>
@endforelse

检查 Blade 指令

在 Laravel 9 中,你可以使用新的 "checked" Blade 指令。

这将是一个很棒的添加,我们可以使用它来稍微清理一下我们的 Blade 视图。

// 在 Laravel 9 之前:
<input type="radio" name="active" value="1" {{ old('active', $user->active) ? 'checked' : '' }}/>
<input type="radio" name="active" value="0" {{ old('active', $user->active) ? '' : 'checked' }}/>

// Laravel 9
<input type="radio" name="active" value="1" @checked(old('active', $user->active))/>
<input type="radio" name="active" value="0" @checked(!old('active', $user->active))/>

select Blade 指令

在 Laravel 9 中,你可以使用新的 "selected" Blade 指令来为 HTML select 元素设置选中状态。

这将是一个不错的添加,我们可以使用它来稍微清理一下我们的 Blade 视图。

// 在 Laravel 9 之前:
<select name="country">
    <option value="India" {{ old('country') ?? $country == 'India' ? 'selected' : '' }}>印度</option>
    <option value="Pakistan" {{ old('country') ?? $country == 'Pakistan' ? 'selected' : '' }}>巴基斯坦</option>
</select>

// Laravel 9
<select name="country">
    <option value="India" @selected(old('country') ?? $country == '印度')>印度</option>
    <option value="Pakistan" @selected(old('country') ?? $country == '巴基斯坦')>巴基斯坦</option>
</select>
请登录后再评论