交换刀片和计算刀片的区别_有关编写自定义刀片指令的所有信息

交换刀片和计算刀片的区别

介绍 ( Introduction )

Often, you will find yourself writing complex logic and conditionals in your views. They not only muck up your pretty Blade templates but also induce logic into your views until you sweep them out with custom Blade directives. Here come Blade directives to rescue your views.

通常,您会发现自己在视图中编写了复杂的逻辑和条件。 它们不仅可以修饰漂亮的Blade模板,还可以在视图中引入逻辑,直到您使用自定义Blade指令将其清除。 Blade指令来拯救您的观点。

刀片指令 ( Blade Directives )

Laravel Blade is a templating engine that compiles its special syntax back into PHP and HTML. Its special syntax includes directives. Directives are sugar-added functions hiding complex or ugly code behind them. Blade includes lots of built-in directives and also allows you to define custom ones. The built-in ones are more than enough for small projects. But as you find yourself repeating complex functionality in your code, it is a smell that you need to refactor to custom Blade directives.

Laravel Blade是一个模板引擎,可以将其特殊语法编译回PHP和HTML。 它的特殊语法包括指令。 伪指令是加糖的函数,在它们后面隐藏了复杂或难看的代码。 Blade包含许多内置指令,还允许您定义自定义指令。 对于小型项目而言,内置的功能已绰绰有余。 但是,当您发现自己在代码中重复了复杂的功能时,就需要将其重构为自定义的Blade指令。

定义自定义刀片指令 ( Defining a Custom Blade Directive )

You can define a custom Blade directive like this:

您可以像这样定义自定义Blade指令:

\Blade::directive('directive_name', function ($expression) {
    return $expression;
});

The $expression parameter is optional in case if the directive is used without anything inside the round brackets.

如果使用该指令而圆括号内没有任何内容,则$expression参数是可选的。

Let's start with a simple Hello World custom directive which you want to be able to use like this:

让我们从一个简单的Hello World自定义指令开始,您可以像这样使用它:

<p>@hello('World')</p>

This, of course, is a terrible example. But for the sake of easy explanation for this easy thing, it tailors right. Now, we have to declare this custom directive and the place for this task is the boot method of the AppServiceProvider.php file.

当然,这是一个可怕的例子。 但是为了便于解释,我们裁量权正确。 现在,我们必须声明此自定义指令,并且此任务的位置是AppServiceProvider.php文件的启动方法。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('hello', function ($expression) {
            return "<?php echo 'Hello ' . {$expression}; ?>";
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

If you have read any old tutorial, then you may know that the $expression passed to your directive callback used to include the outermost parentheses with the expression. But this was changed and they were omitted in Laravel 5.3. In Laravel 5.2- They had to be stripped with something like this: str_replace(['(',')',' '], '', $expression). But don't worry, you don't have to to do anything like that if you are using Laravel 5.3+.

如果您阅读过任何旧教程,那么您可能知道传递给指令回调的$ expression用来在表达式中包含最外面的括号。 但这已更改,在Laravel 5.3中被省略。 在Laravel 5.2中,必须用类似以下的内容剥离它们: str_replace(['(',')',' '], '', $expression) 。 但是不用担心,如果您使用的是Laravel 5.3+,则不必做任何类似的事情。

In this way, our custom directive gets loaded correctly and can be used in any Blade template. The string returned by the closure of the directive just echoes the string 'Hello ' concatenated by the expression passed, all of which is wrapped in PHP tags. So, @hello('World') gets resulted in 'Hello World' and `@hello('Hammad') get resulted in 'Hello Hammad'. This is it. You have made your first custom Blade directive and are ready to challenge Lord Otwell... But wait, this is only a trivial example. Now that you have got your hands dirty, I must arm you with some better and useful examples before you... Come, let me show you more.

这样,我们的自定义指令可以正确加载,并且可以在任何Blade模板中使用。 指令结束处返回的字符串仅回显由传递的表达式连接的字符串“ Hello”,所有这些字符串均包装在PHP标记中。 因此, @hello('World')得到的结果是'Hello World',而'@hello('Hammad')得到的结果是'Hello Hammad'。 就是这个。 您已经制定了第一个自定义Blade指令,并准备挑战Otwell勋爵……但是,等等,这只是一个简单的例子。 现在您已经不习惯了,在您开始之前,我必须向您提供一些更好和有用的示例。来吧,让我向您展示更多。

示例:隐藏付费内容 ( Example: Hiding Paid Content )

Imagine you have a subscription-based vlog like Laracasts or Scotch and you want to hide your premium videos from unsubscribed users. You could manually put an IF block in your view and check if the user has a subscription. This would be fine for one or two views, but for every view, it can get tedious. Like, you want to show premium videos to subscribed users and hide annoying ads from them. With custom Blade directives, this is a cinch.

假设您有一个基于订阅的视频博客,例如Laracasts或Scotch,并且您想向未订阅的用户隐藏高级视频。 您可以在视图中手动放置IF块,并检查用户是否有订阅。 这对于一个或两个视图来说很好,但是对于每个视图来说,它都可能很乏味。 就像,您想向订阅的用户显示优质视频,并向他们隐藏烦人的广告。 使用自定义的Blade指令,这很麻烦。

Let's get started by doing a fresh install of Laravel:

让我们从全新安装Laravel开始:

laravel new vlog

Now, modify the users' table migration to add a new property - isSubscribed:

现在,修改用户的表迁移以添加一个新属性-isSubscribed:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('username')->unique();
            $table->string('email')->unique();
            $table->string('password');
            $table->boolean('isSubscribed')->default(false);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

We have the user in place. Now, create the model and migration for videos:

我们已经到位了。 现在,为视频创建模型和迁移:

php artisan make:model Video -m

Finally, add the necessary columns to the videos table:

最后,将必要的列添加到视频表中:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateVideosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('videos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('file')->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('videos');
    }
}

Now that we have everything in place, let's see how we can hide those videos from unsubscribed users. See, you should first try to think how you'd use the directive before you start implementing it's functionality. This is a nice practice to get into. Maybe like this:

现在我们已经准备就绪,让我们看看如何向未订阅的用户隐藏这些视频。 看,您应该首先尝试思考如何使用指令,然后再开始实现其功能。 这是一个很好的实践。 可能是这样的:

<h1>As~Seen~On~Internet.io</h1>
<p>Premium Videos soon-to-be-available on every browser window near you.</p>
<div id="app">
    <div class="premium-video">
        <h2>Premium Video</h2>
        @subscribed
            <video src="video_for_paid_users_only.mp4"></video>
        @unsubscribed
            <p>Bummer! Looks like you need a subscription to access this video.</p>
        @endsubscribed
    </div>
    <div class="annoying-ads">
        <h2>Annoying Ads</h2>
        @subscribed
            {{-- Annoying Ads - not allowed here --}}
        @unsubscribed
            @foreach ($annoyingAds as $ad)
                {{-- Sponsorships: more than a hundred annyoing companies --}}
                <div class="despicable">{!! $ad !!}</div>
            @endforeach
        @endsubscribed
    </div>
</div>

This is how clean it looks when we do good use of custom Blade directives. Here, we have namely used three custom ones: @subscribed, @unsubscribed and @endsubscribed. Now, we need them to be functional to fulfill the destiny of our premium users and sponsors. Let's think in code: What @subscribed does is that it only checks if there is a user logged in and if there is one, it further checks if he has a subscription and if he has one: it returns true. The unsubscribed directive is used in place of the else block of the conditional. And finally, the endsubscribed directive ends the conditional with an end if. Let's jot it down.

当我们充分利用定制的Blade指令时,它的外观看上去很干净。 在这里,我们使用了三个自定义变量@subscribed@unsubscribed@endsubscribed 。 现在,我们需要它们发挥功能,以实现我们的高级用户和赞助商的命运。 让我们考虑一下代码:@subscribed的作用是,它仅检查是否有用户登录,如果有用户登录,则进一步检查他是否有订阅以及是否有订阅:返回true。 使用unsubscribed指令代替条件的else块。 最后,endsubscribed指令以条件if结束条件。 让我们记下来。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('subscribed', function () {
            $conditon = false;

            // check if the user is authenticated
            if (Auth::check()) {
                // check if the user has a subscription
                $condition = Auth::user()->isSubscribed;
            }

            return "<?php if ($condition) { ?>";
        });

        Blade::directive('unsubscribed', function () {
            return "<?php } else { ?>";
        });

        Blade::directive('endsubscribed', function () {
            return "<?php } ?>";
        });
    }
}

Remember to use Illuminate\Support\Facades\Blade; or do \Blade::directive().

记住要use Illuminate\Support\Facades\Blade; 或做\Blade::directive()

Don't worry about the isSubscribed method. It should belong to the User model.

不用担心isSubscribed方法。 它应该属于用户模型。

预防措施 ( Precautions )

Here are three precautions you should keep in mind while writing custom Blade directives.

编写自定义Blade指令时,应牢记以下三个注意事项。

首要注意事项 ( First Precaution )

If you are still in this stance that the $expression returned by the directive's closure is a PHP statement, you are wrong. It is just a plain old string you came to know about when your PHP journey incarnated. Consider a modified version of our first example:

如果您仍然认为该指令的闭包返回的$expression是PHP语句,则您错了。 这只是一个普通的旧字符串,您在了解PHP旅程时就知道了。 考虑第一个示例的修改版本:

<p>@greet('Hi', 'Hammad')</p>

In the above example, you can't access the first or second argument separately. You get the whole $expression, everything in the parentheses. You need to break them down like this:

在上面的示例中,您不能单独访问第一个或第二个参数。 您将获得整个$expression ,括号中的所有内容。 您需要像这样分解它们:

\Blade::directive('hello', function ($expression) {
    list($greet, $name) = explode(', ', $expression);

    return "<?php echo {$greet} . ' ' . {$name}; ?>";
});

Let's break this down. On the left part of the assignment operator is the explode function. The explode function takes a string as input and returns an array of strings, each of which is a substring of the input string split by a delimiter which is given as the first argument. In this case, the delimiter is ', ' and the string is $expression. The $expression is broken down into elements of an array which what we wanted, but not exactly. We wanted a variable for each, not array elements. For assigning each element of the $expression array to a variable, we use the list construct to do that. The list construct is used to assign a list of variables in one operation.

让我们分解一下。 爆炸运算符在赋值运算符的左侧。 explode函数将一个字符串作为输入,并返回一个字符串数组,每个字符串都是输入字符串的子字符串,该子字符串由定界符分割,该定界符作为第一个参数给出。 在这种情况下,分隔符为',',字符串为$expression$expression被分解为我们想要但不是完全想要的数组元素。 我们需要每个变量,而不是数组元素。 为了将$expression数组的每个元素分配给一个变量,我们使用列表构造来做到这一点。 列表构造用于在一个操作中分配变量列表。

Like array(), list() is not really a function, but a language construct.

array()list()并不是一个真正的函数,而是一种语言构造。

In this way, you can now access the variables as if they were passed to a normal function.

这样,您现在就可以像访问变量一样将其访问常规函数。

第二注意事项 ( Second Precaution )

Remember to escape your output. When you use {{ }}, Blade already does that for you. To avoid malicious users from injecting JavaScript alerts and dirty other code into your site, remember to escape HTML. You can make use of the Laravel helper function e() which is the equivalent of using htmlentities().

记住要转义输出。 当您使用{{ }} ,Blade已经为您做到了。 为避免恶意用户向您的站点注入JavaScript警报和弄脏其他代码,请记住转义HTML。 您可以使用Laravel辅助函数e() ,相当于使用htmlentities()

\Blade::directive('hello', function ($expression) {
    return "<?php echo 'Hello ' . e({$expression}); ?>";
});

第三注意事项 ( Third Precaution )

After updating the logic of a Blade directive, you will need to delete all of the cached Blade views. The cached Blade views may be removed using the view:clear Artisan command.

更新Blade指令的逻辑后,您将需要删除所有缓存的Blade视图。 可以使用view:clear Artisan命令删除缓存的Blade视图。

php artisan view:clear

You need to run this command every time you make a change to any of your custom Blade directives.

每次更改任何自定义Blade指令时,都需要运行此命令。

自定义刀片“如果”指令:Laravel 5.5中的新功能 ( Custom Blade 'If' Directives: New in Laravel 5.5 )

While making use of custom Blade directives, you will notice that most of them are just some form of conditionals. These require you to register three separate directives: one for the if, one for else and the third one for endif. Luckily, Laravel 5.5 adds support for simplifying these if directives.

在使用自定义Blade指令时,您会注意到其中大多数只是某种形式的条件语句。 这些要求您注册三个单独的指令:一个用于if ,一个用于else ,第三个用于endif 。 幸运的是,Laravel 5.5增加了对简化这些if指令的支持。

You can now register a custom if directive like this:

您现在可以注册自定义的if指令,如下所示:

// AppServiceProvider.php
...
public function boot()
{
    \Blade::if('admin', function () {
        return auth()->check() && auth()->user()->isAdmin();
    });
}

This register the whole trio: admin, else and endadmin.

这将注册整个三人组: adminelseendadmin

结论 ( Conclusion )

This is more than all, you need to know about writing custom Blade directives and cleaning your mucked up templates. But what about the duel? This is only one part of your journey to challenge Lord Otwell. There is a lot about Laravel which you need to know, before you...

这不仅是全部,您还需要了解有关编写自定义Blade指令和清理已废弃的模板的知识。 但是决斗呢? 这只是挑战奥特维尔勋爵的旅程的一部分。 在您开始之前,您需要了解很多有关Laravel的信息。

Happy Coding!

编码愉快!

翻译自: https://scotch.io/tutorials/all-about-writing-custom-blade-directives

交换刀片和计算刀片的区别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值