当使用数据映射器、服务和域对象三者时,分页在哪里


Where does pagination live when using datamappers, services and domain object trio

使用service/datamapper/domain object trio时,我的分页的正确位置是什么?

示例:

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

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

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;
    }
}

我的视图可以访问与我的控制器相同的Model层实例,所以我可以从视图中调用$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) 创建一个分页服务,并让控制器根据需要与后期服务交换数据?

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

3) 向抽象服务添加通用分页?

4) 在我的回购中添加某种分页支持?

你的回答很好,不过我有一些建议。

层位置:

分页基础结构应该位于数据访问层,这样您就可以对如何检索数据进行低级控制。

最高调用

分页的接口应该是抽象的,并通过服务在UI中公开,因为这是一个前端问题。(我想你的答案中已经包含了这一点)

摘要:

UI应该知道的是页面索引、页数、每页项目数和项目总数。无论是偏移还是限制,这些都是应该封装的基础设施术语。

输入:(fitlers的一部分)

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

输出:

  1. 筛选的集合
  2. 页数(用于导航)
  3. 总项目数(如有必要,在UI中)

由于没有这个问题的答案,我发布了我提出的解决方案。如果可以改进的话,感谢对它的评论/补充。

// 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()方法和数据映射器。