TYPO3 Extbase - 通过大 table(100000 条记录)进行分页
TYPO3 Extbase - Paginate through a large table (100000 records)
我有一个相当大的 table,大约有 100000 条记录。如果我不在存储库中设置限制
存储库:
public function paginateRequest() {
$query = $this->createQuery();
$result = $query->setLimit(1000)->execute();
//$result = $query->execute();
return $result;
}
/**
* action list
*
* @return void
*/
public function listAction() {
$this->view->assign('records', $this->leiRepository->paginateRequest());
//$this->view->assign('records', $this->leiRepository->findAll());
}
...查询和分页符,尽管我使用的是 f:widget.paginate 。根据文档 https://fluidtypo3.org/viewhelpers/fluid/master/Widget/PaginateViewHelper.html 我希望我只能通过记录呈现 itemsPerPage 和 'parginate' ...
List.hmtl
<f:if condition="{records}">
<f:widget.paginate objects="{records}" as="paginatedRecords" configuration="{itemsPerPage: 100, insertAbove: 0, insertBelow: 1, maximumNumberOfLinks: 10}">
<f:for each="{paginatedRecords}" as="record">
<tr>
<td><f:link.action action="show" pageUid="43" arguments="{record:record}"> {record.name}</f:link.action></td>
<td><f:link.action action="show" pageUid="43" arguments="{record:record}"> {record.lei}</f:link.action></td>
</tr>
</f:for>
</f:widget.paginate>
型号:
class 磊延伸 \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
...
/**
* abc
*
* @lazy
* @var string
*/
protected $abc = '';
...
您要分页的对象有多大/多复杂?如果它们有您在列表视图中不需要的子对象,请将@lazy 注释添加到模型中的那些关系。
由于记录量很大,您应该在列表视图中使它们尽可能简单。您可以尝试仅使用 $this->leiRepository->findAll()->toArray()
或 return 将结果作为数组提供给列表视图,仅将存储库中的原始结果添加到 execute(true) 中。
您还可以在控制器的 foreach 中自己创建一个列表项数组,并只在列表中添加您真正需要的属性。
如果您的问题是性能,只需使用默认的 findAll()-方法。
\TYPO3\CMS\Extbase\Persistence\Repository 中的内置 defaultQuerySettings 根据分页小部件设置它们的偏移量和限制,如果没有另外设置的话。
如果性能问题仍然存在,您可能需要考虑为您的数据库请求编写一个自定义查询,它只请求您的视图实际显示的数据。文档中描述了该过程:https://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html
我用的是TYPO3 9.5。存储库中的下一个函数:
public function paginated($page = 1, $size = 9){
$query = $this->createQuery();
$begin = ($page-1) * $size;
$query->setOffset($begin);
$query->setLimit($size);
return $query->execute();
}
并且在控制器中,我使用参数作为参数来发送要在 Rest 操作中加载的页面。
public function listRestAction()
{
$arguments = $this->request->getArguments();
$totalElements = $this->repository->total();
$pages = ceil($totalElements/9);
$next_page = '';
$prev_page = '';
#GET Page to load
if($arguments['page'] AND $arguments['page'] != ''){
$page_to_load = $arguments['page'];
} else {
$page_to_load = 1;
}
#Configuration of pagination
if($page_to_load == $pages){
$prev = $page_to_load - 1;
$prev_page = "http://example.com/rest/news/page/$prev";
} elseif($page_to_load == 1){
$next = $page_to_load + 1;
$next_page = "http://example.com/rest/news/page/$next";
} else {
$prev = $page_to_load - 1;
$prev_page = "http://example.com/rest/news/page/$prev";
$next = $page_to_load + 1;
$next_page = "http://example.com/rest/news/page/$next";
}
$jsonPreparedElements = array();
$jsonPreparedElements['info']['count'] = $totalElements;
$jsonPreparedElements['info']['pages'] = $pages;
$jsonPreparedElements['info']['next'] = $next_page;
$jsonPreparedElements['info']['prev'] = $prev_page;
$result = $this->repository->paginated($page_to_load);
$collection_parsed_results = array();
foreach ($result as $news) {
array_push($collection_parsed_results, $news->parsedArray());
}
$jsonPreparedElements['results'] = $collection_parsed_results;
$this->view->assign('value', $jsonPreparedElements);
}
这样做的结果是 JSON 这样的:
{
"info": {
"count": 25,
"pages": 3,
"next": "",
"prev": "http://example.com/rest/news/page/2"
},
"results": [
{ ....}
] }
我有一个相当大的 table,大约有 100000 条记录。如果我不在存储库中设置限制
存储库:
public function paginateRequest() {
$query = $this->createQuery();
$result = $query->setLimit(1000)->execute();
//$result = $query->execute();
return $result;
}
/**
* action list
*
* @return void
*/
public function listAction() {
$this->view->assign('records', $this->leiRepository->paginateRequest());
//$this->view->assign('records', $this->leiRepository->findAll());
}
...查询和分页符,尽管我使用的是 f:widget.paginate 。根据文档 https://fluidtypo3.org/viewhelpers/fluid/master/Widget/PaginateViewHelper.html 我希望我只能通过记录呈现 itemsPerPage 和 'parginate' ...
List.hmtl
<f:if condition="{records}">
<f:widget.paginate objects="{records}" as="paginatedRecords" configuration="{itemsPerPage: 100, insertAbove: 0, insertBelow: 1, maximumNumberOfLinks: 10}">
<f:for each="{paginatedRecords}" as="record">
<tr>
<td><f:link.action action="show" pageUid="43" arguments="{record:record}"> {record.name}</f:link.action></td>
<td><f:link.action action="show" pageUid="43" arguments="{record:record}"> {record.lei}</f:link.action></td>
</tr>
</f:for>
</f:widget.paginate>
型号:
class 磊延伸 \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
...
/**
* abc
*
* @lazy
* @var string
*/
protected $abc = '';
...
您要分页的对象有多大/多复杂?如果它们有您在列表视图中不需要的子对象,请将@lazy 注释添加到模型中的那些关系。
由于记录量很大,您应该在列表视图中使它们尽可能简单。您可以尝试仅使用 $this->leiRepository->findAll()->toArray()
或 return 将结果作为数组提供给列表视图,仅将存储库中的原始结果添加到 execute(true) 中。
您还可以在控制器的 foreach 中自己创建一个列表项数组,并只在列表中添加您真正需要的属性。
如果您的问题是性能,只需使用默认的 findAll()-方法。
\TYPO3\CMS\Extbase\Persistence\Repository 中的内置 defaultQuerySettings 根据分页小部件设置它们的偏移量和限制,如果没有另外设置的话。
如果性能问题仍然存在,您可能需要考虑为您的数据库请求编写一个自定义查询,它只请求您的视图实际显示的数据。文档中描述了该过程:https://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html
我用的是TYPO3 9.5。存储库中的下一个函数:
public function paginated($page = 1, $size = 9){
$query = $this->createQuery();
$begin = ($page-1) * $size;
$query->setOffset($begin);
$query->setLimit($size);
return $query->execute();
}
并且在控制器中,我使用参数作为参数来发送要在 Rest 操作中加载的页面。
public function listRestAction()
{
$arguments = $this->request->getArguments();
$totalElements = $this->repository->total();
$pages = ceil($totalElements/9);
$next_page = '';
$prev_page = '';
#GET Page to load
if($arguments['page'] AND $arguments['page'] != ''){
$page_to_load = $arguments['page'];
} else {
$page_to_load = 1;
}
#Configuration of pagination
if($page_to_load == $pages){
$prev = $page_to_load - 1;
$prev_page = "http://example.com/rest/news/page/$prev";
} elseif($page_to_load == 1){
$next = $page_to_load + 1;
$next_page = "http://example.com/rest/news/page/$next";
} else {
$prev = $page_to_load - 1;
$prev_page = "http://example.com/rest/news/page/$prev";
$next = $page_to_load + 1;
$next_page = "http://example.com/rest/news/page/$next";
}
$jsonPreparedElements = array();
$jsonPreparedElements['info']['count'] = $totalElements;
$jsonPreparedElements['info']['pages'] = $pages;
$jsonPreparedElements['info']['next'] = $next_page;
$jsonPreparedElements['info']['prev'] = $prev_page;
$result = $this->repository->paginated($page_to_load);
$collection_parsed_results = array();
foreach ($result as $news) {
array_push($collection_parsed_results, $news->parsedArray());
}
$jsonPreparedElements['results'] = $collection_parsed_results;
$this->view->assign('value', $jsonPreparedElements);
}
这样做的结果是 JSON 这样的:
{
"info": {
"count": 25,
"pages": 3,
"next": "",
"prev": "http://example.com/rest/news/page/2"
},
"results": [
{ ....}
] }