Laravel: 我应该在循环中使用@include 吗?

Laravel: should i use @include inside loops?

下面我提供了两个循环显示产品卡片的例子。第一个在我看来更方便,但由于循环内的这个@include,我担心性能。由于这个任务很常见,我想选择最好的方法。

案例 1. 使用 @include:

search.blade.php

<div id='search-results'>   
    @foreach($items as $item)
         @include('items._item')
    @endforeach
</div>

_item.blade.php

<div>
    <div class='item-title'>{{$item->title}}</div>
    <div class='item-description'>{{$item->description}}</div>
</div>

情况 2. 没有 @include:

search.blade.php

<div id='search-results'>
    @include('items._items_list')
</div>

_items_list.blade.php

@foreach($items as $item)
    <div class='item-title'>{{$item->title}}</div>
    <div class='item-description'>{{$item->description}}</div>
@endforeach

第一种方法似乎是最正确的方法。

这可能会造成巨大的性能问题。当您像第一种情况一样循环 @include 时,生成的原始 php 文件确实将包含的视图作为函数调用。这会稍微减慢页面呈现速度。

第二种情况性能更高,因为它基本上是 1 个包含(带有一个包含 html 片段的循环)。

我现在遇到了这个问题。我有一个循环 250 条记录的数据表,但每条记录包含 5 个助手。在我的例子中,这些助手非常重要并且包含一些必要的(简单的)逻辑,但即使有简单的逻辑,1250 个子视图也会导致性能大幅下降,将页面的加载时间减少到 5-6 秒,而复制时为 300-400 毫秒在这个帮助代码上。

我正在努力编写一个 Laravel 扩展来解析所有 @include 并将其替换为实际代码,但这不是一件容易的事...

示例 1:查看 blade 如何解析您的 @foreach 循环

考虑一下这个非常简单的 foreach 循环。它只是在每个元素的 <h1> 标签中输出 object 的 name

@foreach($paymentMethods as $paymentMethod)
    <h1>{{ $paymentMethod->name }}</h1>
@endforeach

可以看到storage/framework/views/*.php里面生成的数据出来有点复杂:

<?php $__currentLoopData = $paymentMethods; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $paymentMethod): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
    <h3>
        <?php echo e($paymentMethod->name); 
    </h3>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php /**PATH C:\xampp\sites\someproject\resources\views/payment_providers.blade.php ENDPATH**/ ?>

正在调用来自 $__env object 的各种助手。例如,这些将为您的 @foreach 循环添加额外的功能,例如 $loop->first/$loop->last 变量(参见 https://laravel.com/docs/5.8/blade)。

示例 2:@include 语句

@include('myhelper')
<?php echo $__env->make('myhelper', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>

$__env->make() 函数解析为 vendor/laravel/framework/src/Illuminate/View/Factory.php,它计算您的 blade 助手。这个过程包括查找视图文件本身,通过 blade 引擎再次解析它,调度事件...

Blade 快捷方式无疑会对性能产生影响。这仅取决于您使用的数量以及是否值得为您多花几毫秒。

恕我直言,如果您碰巧需要循环大 collections 并使用许多 @include 语句,那么这对生产环境来说是一个非常值得的优化。然后我建议使用标准的 <?php foreach($arr as $item): ?>/<?php endforeach ?> 语法,结合一些简单的 php 函数,如果你需要 return html re-useable html 件.

我通过使用传递给某些 blade 的 75 行然后迭代这 75 行两次来测试此行为。 第一个仅使用此 blade 文件中的 blade 代码,另一个调用 @include 另一个具有相同代码的 blade 文件并使用 microtime(true) php 在每次刺激的开始和结束时起作用 如果使用@include.

,时间增加了 3 倍