在刀片和laravel中简化这个@ foreach / if

时间:2015-04-07 17:59:49

标签: php laravel laravel-5

我对laravel(特别是L5)相当新,我正在创建自己的todo应用程序版本,而不是遵循其中一个教程。到目前为止我已经学到了很多东西,但是我在我的刀片模板中设置这段代码的方式让我觉得它们可能是一种更简单的方法。

我的TodosController@index fn是

public function index()
{
    $todos = Todo::get();
    return view('todos', compact('todos'));
}

App\Todo扩展了Eloquent模型,使数据处理变得非常简单!

我的路线是:

Route::bind('todos', function($slug)
{
    return App\Todo::whereSlug($slug)->first();
});

所以我的页面只显示一个“todos”的无序列表。我想要两个单独的列表。一个是完成的待办事项,另一个是不完整的。到目前为止,我的刀片模板看起来像这样,看起来有点乱。此外,我将结果循环两次,这是我认为我可以改进的地方。

<h3>Incomplete</h3>
<ul>
    @foreach ($todos as $todo)
        @if ($todo->completed == 'No')
            <li>
                <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
            </li>
        @endif
    @endforeach
</ul>

<h3>Complete</h3>
<ul>
    @foreach ($todos as $todo)
        @if ($todo->completed == 'Yes')
            <li>
                <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
            </li>
        @endif
    @endforeach
</ul>

有关简化该刀片模板的任何建议吗?

2 个答案:

答案 0 :(得分:4)

干掉你的代码。您可以通过将实际项目标记移动到部分模板来简化它,因为它在完整列表和不完整列表中都会重复:

<h3>Incomplete</h3>
<ul>
    @foreach ($todos as $todo)
        @if ($todo->completed == 'No')
            @include('partials.items.todo')
        @endif
    @endforeach
</ul>

<h3>Complete</h3>
<ul>
    @foreach ($todos as $todo)
        @if ($todo->completed == 'Yes')
            @include('partials.items.todo')
        @endif
    @endforeach
</ul>

partials.items.todo看起来像这样:

<li>
    <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
</li>

我也会重新考虑你的循环。您可以在控制器中拆分它们,而不是在同一列表上循环两次:

public function index()
{
    $todos = Todo::where('user_id', '=', Auth::id())->get();

    $complete = $todos->filter(function ($item) {
        return $item->completed = 'Yes';
    });

    $incomplete = $todos->filter(function ($item) {
        return $item->completed = 'No';
    });

    return view('todos', compact('complete', 'incomplete'));
}

查看您的Todo模型,我还会将数据库中的completed列设置为布尔字段,而不是包含“是”或“否”字符串的列。然后,您可以将该列值转换为适当的布尔值(因为MySQL没有本机布尔字段类型):

class Todo extends Model
{
    protected $casts = [
        'completed' => 'boolean',
    ];

    public function isComplete()
    {
        return $this->completed;
    }
}

然后重新考虑您的控制器操作以使用它:

public function index()
{
    $todos = Todo::where('user_id', '=', Auth::id())->get();

    $complete = $todos->filter(function ($item) {
        return $item->isComplete() === true;
    });

    $incomplete = $todos->filter(function ($item) {
        return $item->isComplete() === false;
    });

    return view('todos', compact('complete', 'incomplete'));
}

您甚至可以将这些集合过滤器移动到自定义TodoCollection类:

use Illuminate\Database\Eloquent\Collection as EloquentCollection;

class TodoCollection extends EloquentCollection
{
    public function complete()
    {
        return $this->filter(function ($item) {
            return $item->isComplete() === true;
        });
    }

    public function incomplete()
    {
        return $this->filter(function ($item) {
            return $item->isComplete() === false;
        });
    }
}

对于冗长的回复感到抱歉,但是应该为您提供有关如何重新计算代码的食物。

答案 1 :(得分:1)

只有一点简化,但......

您可以在控制器中试用:

public function index()
{
    $completed = Todo::where('completed','Yes')->get();
    $incompleted = Todo::where('completed','No')->get();
    return view('todos', compact('completed', 'incompleted'));
}

在你的模板中:

<h3>Incomplete</h3>
<ul>
    @foreach ($incompleted as $todo)
            <li>
                <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
            </li>
    @endforeach
</ul>

<h3>Complete</h3>
<ul>
    @foreach ($completed as $todo)
            <li>
                <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
            </li>
    @endforeach
</ul>

使用这样的子模板的另一种方法:

    //_list_todos.blade.php

    @foreach ($todos as $todo)
            <li>
                <a href="{{ route('todos.show', [$todo->slug]) }}">{{ $todo->title }}</a>
            </li>
    @endforeach

你的主要模板是这样的:

<h3>Incomplete</h3>
<ul>
     @include('_list_todos',['todos'=>$incompleted] )
</ul>

<h3>Complete</h3>
<ul>
     @include('_list_todos',['todos'=>$completed] )
</ul>

使用类似最后一个子模板的优点是您可以重用代码,并简化主模板。