我在我的应用中使用了丰富的域名模型。基本想法是there。例如,我有User和Comment实体。它们定义如下:
<?php
class Model_User extends Model_Abstract {
public function getComments() {
/**
* @var Model_Mapper_Db_Comment
*/
$mapper = $this->getMapper();
$commentsBlob = $mapper->getUserComments($this->getId());
return new Model_Collection_Comments($commentsBlob);
}
}
class Model_Mapper_Db_Comment extends Model_Mapper_Db_Abstract {
const TABLE_NAME = 'comments';
protected $_mapperTableName = self::TABLE_NAME;
public function getUserComments($user_id) {
$commentsBlob = $this->_getTable()->fetchAllByUserId((int)$user_id);
return $commentsBlob->toArray();
}
}
class Model_Comment extends Model_Abstract {
}
?>
Mapper的getUserComments函数只返回如下内容:
return $this->getTable->fetchAllByUserId($user_id)
是数组。 fetchAllByUserId接受$ count和$ offset params,但是我不知道通过模型将它们从我的Controller传递给这个函数而不重写所有的模型代码。
所以问题是如何通过模型数据(getComments)组织分页。是否有一个“美丽”的方法来获取5到10之间的评论,而不是全部,因为getComments默认返回。
答案 0 :(得分:2)
Zend_Paginator
可能是您正在寻找的简单解决方案。它可能需要array()
或Iterator
的实例(Zend_Db_Table_Rowset
是
$paginator = Zend_Paginator::factory($model->getComments());
$paginator->setItemCountPerPage(5);
$paginator->setCurrentPageNumber($this->getRequest()->getParam('page',1));
$this->view->comments = $paginator;
在视图中:
<?php foreach($this->comments as $comment): ?>
Render your HTML for the comment
<?php endforeach; ?>
<?php echo $this->paginationControl($this->comments, 'Sliding', '_pagination.phtml'); ?>
一个(非常)简单paginationControl()
部分(取自this blog post):
<?php if ($this->pageCount): ?>
<div class="paginationControl">
<?php if (isset($this->previous)): ?>
<a href="<?= $this->url(array(’page’ => $this->previous)); ?>">< Previous</a> |
<?php else: ?>
<span class="disabled">< Previous</span> |
<?php endif; ?>
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
<a href="<?= $this->url(array(’page’ => $page)); ?>"><?= $page; ?></a> |
<?php else: ?>
<?= $page; ?> |
<?php endif; ?>
<?php endforeach; ?>
<?php if (isset($this->next)): ?>
<a href="<?= $this->url(array(’page’ => $this->next)); ?>">Next ></a>
<?php else: ?>
<span class="disabled">Next ></span>
<?php endif; ?>
</div>
<?php endif; ?>
More examples of Zend_Paginator可通过谷歌搜索获得。
答案 1 :(得分:2)
如果您只关心对用户看到的结果进行分页,并且不关心提高性能,则可以避免在模型基础结构中构建分页。
假设你有一些Model_Collection_Abstract类,你的所有集合类都来自它,你可能会破坏它的分页。
那么你的代码看起来像是:
<?PHP
//$comments is a subclass of Model_Collection_Abstract, which implements the paging stuff
$comments = $user->getComments();
$comments->setStart(10);
$comments->setPageLength(10);
$numPages = $comments->numPages(); //can be derived from the pagelength and the collection's internal record store.
$currentPage = $comments->currentPage(); //can be derived from start and page length
foreach($comments as $comment){
//this code runs up to ten times, starting at the tenth element in the collection.
}
这里的缺点是你总是抓住所有的评论,即使你只想看到其中的十条。但这对你来说可能是一个可以接受的解决方案。
如果您只想从数据库中提取N条记录(N =要显示的数字),那么当然您需要实现一些方法来传递开始/限制或等效参数,一直到您的模型。
编辑:关于查看Zend_Paginator的另一个答案也值得一读。如果您的集合类implements Iterator
,很可能您可以将其插入Zend_Paginator并保存一些严重的麻烦。我还没有这样做(但是),但值得一看!
答案 2 :(得分:2)
现在想一想。你找到了一个简洁的解决方案吗? 到目前为止我的想法是 1)避免使用像Zend_Paginator这样的东西,只做你自己的一切。即你从环境(请求对象或一些配置文件等)获取params,如itemCountPerPage,currentPageNumbe,你将它们传递到你的服务层方法(或者在你的情况下,它只是映射器),如
$comments = $this->getCommentsMapper()->getPage($itemCountPerPage, $currentPage);
然后你从你的映射器请求总项目金额(如果你应该在单独的请求中完成,那么完全由你决定),如
$totalComments = $this->getCommentsMapper()->getTotal();
所以现在你有了所有数据来制作“分页控制视图”。说到“Zendy”,你将所有这些变量传递给视图并自己绘制分页控件。
2)为Zend_Paginator 开发一个适用于LIE的适配器。即而不是拥有所有项目,它将只有你需要的一部分,但你将手动设置“总计数”值和其他。我自己并不喜欢这种方法。
3)添加一些名为“Page”的特殊域对象,该对象将从映射器或服务层返回。这样的对象将封装我们构建分页控件表示所需的所有变量。有了这个,我们就可以做到以下几点:
` $ commentsService = $ this-&gt; getCommentsService(); $ commentsService-&GT; setItemCountPerPage(10); //假设10取自一些config.ini
$ commentsPage = $ this-&gt; getCommentsService() - &gt; getPage(12); $ this-&gt; view-&gt; commentsPage = $ commentsPage;
`
在视图的某个地方我们可以得到这些 ` $ commentsPage-&GT; getItems(); //评论集合
$ commentsPage-&GT; getCurrentPageNumber();
$ commentsPage-&GT; getTotalItemsCount();
`
这足以构建分页控件。
这一切。
我目前正在选择第一种和第三种方法,可能会选择第三种方式。
答案 3 :(得分:0)
这是我的解决方案:
class Model_Mapper_Db_Comment extends Model_Mapper_Db_Abstract {
public function getUserCommentsPaginator($user_id) {
$select = $this->_getTable()->select()->where('user_id = ?', (int)$user_id);
$paginator = Zend_Paginator::factory($select, 'DbSelect');
return $paginator;
}
}
class Model_User extends Model_Abstract implements Zend_Auth_Adapter_Interface {
public function getCommentsPaginator() {
$paginator = $this->getMapper(null, 'Comment')->getUserCommentsPaginator($this->id);
$paginator->setFilter(new App_Filter_Array_Collection('Model_Collection_Comments'));
return $paginator;
}
}
模型根据Model提供的user_id请求Zend_Paginate对象和准备好的查询。然后Model将过滤器添加到Zend_Paginate对象,使其与其他Model方法兼容(返回Model_Collection类,而不是数组)。所有其他分页参数都在控制器中设置(页面,每页的项目数等)。
这就是我在应用程序中分离存储,业务和控制逻辑的方式。