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

Ron*_*nie 1 php laravel laravel-5

我对 laravel(特别是 L5)相当陌生,我正在制作自己的待办事项应用程序版本,而不是遵循那里的教程之一。到目前为止,我已经学到了很多东西,但是我目前在刀片模板中放置这段代码的方式让我认为它们可能是一种更简单的方法。

我的TodosController@indexfn 是

public function index()
{
    $todos = Todo::get();
    return view('todos', compact('todos'));
}
Run Code Online (Sandbox Code Playgroud)

App\Todo扩展了一个Eloquent模型,使数据处理变得非常容易!

我的路线是:

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

所以我的页面只是显示一个无序的“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>
Run Code Online (Sandbox Code Playgroud)

有什么建议可以简化刀片模板吗?

Mar*_*ean 6

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

<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>
Run Code Online (Sandbox Code Playgroud)

而且partials.items.todo应该是这样的:

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

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

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'));
}
Run Code Online (Sandbox Code Playgroud)

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

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

    public function isComplete()
    {
        return $this->completed;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后重构您的控制器操作以使用它:

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'));
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以将这些集合过滤器移动到自定义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;
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

抱歉回复太长,但应该为您提供有关如何重构代码的食物。