【问题标题】:Filtering data in laravel and handling the views在 laravel 中过滤数据并处理视图
【发布时间】:2015-01-16 00:37:32
【问题描述】:

我正在构建一个电视节目 netflix-esque 项目,其中有一个 Shows 页面,我想按格式过滤该页面。每个节目都包含可以有电视、dvd 和 bd 格式的剧集。

目前我正在使用扩展基础 ShowsController 的单独路由和控制器进行过滤。

Route::get('shows/view/{type}', ['as' => 'shows.viewtype', 'uses' => 'ShowsController@viewType',]);
Route::get('shows/bluray',['as' => 'shows.bluray','uses' => 'ShowsBlurayController@index']);
Route::get('shows/dvd',['as' => 'shows.dvd','uses' => 'ShowsDVDController@index']);
Route::get('shows/tv',['as' => 'shows.tv','uses' => 'ShowsTVController@index']);

格式控制器之一的示例

class ShowsBlurayController extends ShowsController
{
    public function index()
    {
        // Set user state for browsing bluray
        Session::push('user.showtype', 'bluray');

        $shows = $this->show->getBlurayPaginated(16);

        return $this->getIndexView(compact('shows'));
    }
}

我使用getIndexView() 方法(在ShowsController 中)来确定2 个可用视图之一:posterlist

public function getIndexView($shows)
{
    $viewType = get_session_or_cookie('show_viewtype', 'list');
    if ($viewType == 'posters') {
        return View::make('shows.index', $shows)
            ->nest('showsView', 'shows.partials.posters', $shows);
    } else {
        return View::make('shows.index', $shows)
            ->nest('showsView', 'shows.partials.list', $shows);
    }
}

节目是根据剧集过滤的:

public function getBlurayPaginated($perPage)
{
    return $this->getByFormat('BD')->with('tagged')->paginate($perPage);
}
private function getByFormat($format)
{
    return $this->show->whereHas('episodes', function ($q) use ($format) {
        $q->whereHas('format', function ($q) use ($format) {
            $q->where('format', '=', $format);
        });
    });
}

问题是我想以一种干净的方式做到这一点。当用户选择一种格式时,将应用该过滤器。目前所有这些都分散在控制器中,不太有意义。

我也想过在routes.php做这样的事情:

Route::get('shows/format/{format}',['as' => 'shows.format','uses' => 'ShowsController@index']);

然后处理索引中的过滤,但这似乎也是一个奇怪的地方。

这种方法确实有效,但我不想以后用它搞砸自己。我正在计划一个简单的搜索,应该将过滤器考虑在内。

换句话说,我如何组织代码以使从数据库中获取数据时会考虑已设置的过滤器? (可能是会话状态?)

【问题讨论】:

  • 你能再澄清一点吗?有没有报错?
  • @MD.AtiqurRahman 没有错误。它工作正常,只是不可扩展且不干燥
  • 看看下面的答案,希望能解决你的问题。

标签: php laravel


【解决方案1】:
Route::get('shows/format/{format}',[
    'as' => 'shows.format',
    'uses' => 'ShowsController@index'
]);

我认为你在正确的轨道上。我什至会生成一个factory 并将其注入控制器。这个工厂的目的是构建一个格式化程序,为您的视图提供正确的数据:

// ShowController
public function __construct(ShowFormatFactory $factory, ShowRepository $shows)
{
    $this->factory = $factory;
    // NB: using a repository here just for illustrative purposes.
    $this->shows = $shows;
}

public function index($format = null) 
{
    $formatter = $this->factory->make($format);

    return View::make('shows.index', [
        'formatter' => $formatter,
        'shows' => $this->shows->all(),
    ]);
}

// ShowFormatFactory
class ShowFormatFactory
{
    public function make($format)
    {
        switch($format) {
            case 'blueray':
                return new BluerayFormat(); break;

            case 'dvd': /* Fallthrough for default option */
            default:
                return new BluerayFormat(); break;
        }
    }
}

// ShowFormatInterface
interface ShowFormatInterface
{
    public function format(Show $show);
}

// BluerayFormat
class BluerayFormat implements ShowFormatInterface
{
    public function format(Show $show)
    {
        return $show->blueray_format;
    }
}

那么在你看来,既然你保证有一个对象可以为你提供给定节目所要求的格式,那就叫它吧:

@foreach($shows as $show)
<div class="show">
    Chosen Format: {{ $formatter->format($show) }}
</div>
@endforeach

此解决方案可测试且可扩展,允许您稍后添加其他格式。如果这样做,您需要在工厂中为每种不同的格式添加一个离散的 case 语句,并编写一个相当苗条的 ~5-7 行类来支持新格式。

【讨论】:

  • 也许有一些误解,但你为什么要过滤视图中的节目?在 repo 中应用过滤器不是更好吗?我现在就是这样。我将过滤后的节目传递给视图。问题是我以一种奇怪的方式委派了过滤器操作。这些格式也存储在数据库中,并附有Format 模型。也更新了我的问题。
  • 这是一个索引视图,所以没有过滤,它将显示每个节目。路径shows/format/dvdshows/format/blueray 之间的不同之处在于工厂中创建的对象不同。由于您需要在视图中至少浏览每个节目一次,因此如果您改为从存储库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多