【问题标题】:Where does pagination live when using datamappers, services and domain object trio使用数据映射器、服务和域对象三重奏时分页在哪里
【发布时间】:2014-06-09 15:26:27
【问题描述】:

当使用服务/数据映射器/域对象三重奏时,我的分页所在的正确位置被认为是什么?

例子:

  • 使用一些给定条件获取端口
  • 对结果进行分页
  • 从视图类中了解我们所在的页面、总页数、结果数等

以下只是我现在写的东西,但它与我的应用程序相似。

class PostController extends Controller
{
    function viewPosts()
    {
        return $this->serviceFactory
            ->build('post')
            ->getPosts($aCriteria, $this->request->_get('page'), 10);
    }
}

我目前正在计算和存储每个服务中的分页参数。请注意,我没有将任何数据从控制器推送到视图。

class PostService extends AbstractService
{
    public $posts;

    public $iTotalPages; // This does not belong here does it?

    function getPosts($aCriteria, $iPage, $iItemsPerPage)
    {
        $mapper = $this->dataMapperFactory->build('post');

        // I do not know where to put the below
        // (The parameters and the code itself)
        $iCount = $mapper->count($aCriteria);
        $iOffset = $iItemsPerPage * $iPage;
        $this->iTotalPages = $iCount / $iItemsPerPage;

        $this->posts = $mapper->find($aCriteria, $iOffset, $iOffset + $iItemsPerPage);

        return $this->posts;
    }
}

我的视图可以访问与我的控制器相同的模型层实例,因此我可以从视图中调用$service->iTotalPages,但感觉不对。

class PostsView extends AbstractView
{
    function viewPosts()
    {
        $service = $this->serviceFactory->build('post');

        if(count($service->posts)>0) {
            $this->template->assign_var('TOTAL_PAGES', $service->iTotalPages);
            $this->template->assign_vars('POSTS', $service->posts);        
        }
    }
}

解决方案?

1) 创建分页服务,并让控制器根据需要与 post 服务交换数据?

2) 为每个服务可以包含的分页创建一个辅助类? (这样的课程会是什么样子?)

3) 向 AbstractService 添加通用分页?

4) 为我的 Repos 添加某种分页支持?

【问题讨论】:

  • 如果您需要在数据库级别进行分页,您可以将条件和分页添加到您的读取存储库。就个人而言,我更喜欢首先使用 max 作为 finder 的参数(我认为它更通用)并在控制器处转换总页数、当前页(通常是 ui 术语)。

标签: php pagination domain-driven-design datamapper


【解决方案1】:

由于缺乏对这个问题的答案,我发布了我想出的解决方案。如果可以改进,请欣赏 cmets/additions。

// Controller method
public function viewPosts()
{
    // Create service objects
    $postService = $this->serviceFactory->build('post', true);
    $searchService = $this->serviceFactory->build('search');

    // Set the search/filter parameters
    $searchService->addFilter('author_id', $this->visitor->user_id);
    $searchService->setOffset($this->request->_get('offset'));
    $searchService->setLimit($this->request->_get('limit'));

    // Search service will call the 'find' method on $articleService
    $searchService->setServiceObject($articleService, 'find');

    // Search service will return a filtered collection
    return $searchService->search();
}

这样做我不会将业务逻辑泄漏到我的控制器中(我认为),并且我有一个类来完成对返回的 sql 数据的所有过滤和分析,同时仍然保持每个特定服务对其的控制具体的 find() 方法和数据映射器。

【讨论】:

    【解决方案2】:

    你的回答很好,虽然我有一些建议。

    图层位置:

    分页基础架构应位于数据访问层,这样您就可以对数据的检索方式进行低级别控制。

    最高调用次数

    分页的界面应该被抽象出来并通过服务暴露在 UI 中,因为它是一个前端问题。 (我认为您的答案中已经涵盖了这一点)

    抽象:

    UI 应该知道页面索引、页面数、每页项目数和总项目数。不是 Offset 也不是 limit,这些是应该封装的基础架构术语。

    输入:(您的部分过滤器)

    1. 搜索过滤器
    2. 排序过滤器(如有必要)
    3. 页面索引。
    4. 每页的项目数。 (如果 UI 有控制权,如果没有,则应该封装)

    输出:

    1. 过滤的集合
    2. 页数(用于导航)
    3. 项目总数(如果需要,在 UI 中)

    【讨论】:

    • 有效积分。无论如何,我必须对我的解决方案做一些进一步的修改,我认为你的输入会很好地适应它。稍后我会更新并添加我对我的问题的答案。
    猜你喜欢
    • 2012-08-19
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多