使用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的一部分)
- 搜索筛选器
- 排序过滤器(如有必要)
- 页面索引
- 每页的项目数。(如果UI具有控制权,如果没有,则应将其封装)
输出:
- 筛选的集合
- 页数(用于导航)
- 总项目数(如有必要,在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()方法和数据映射器。