Open alexmglover opened 6 years ago
I don't know of any way to convert an EntryModel
(which is typically what you'd end up with after performing a custom query) into an ElementCriteriaModel
. In one instance where I needed pagination on a custom query result, I ended up writing a plugin and template to build the pagination element manually.
I built pagination for a custom search within the comments plugin for craft 2
<?php
namespace Craft;
class Comments_PaginationService extends BaseApplicationComponent
{
// Properties
// =========================================================================
public $activeComment;
/**
* @var integer
*/
public $elementsPerPage;
/**
* @var integer
*/
public $totalElements;
/**
* @var string
*/
public $pageParam;
/**
* @var integer
*/
public $totalPages;
/**
* @var integer
*/
public $currentPage;
/**
* @var integer
*/
public $count;
/**
* @var
*/
public $first;
/**
* @var
*/
public $last;
// Public Methods
// =========================================================================
/**
* Get curret page for use in the pagination
*
* @return [type] [description]
*/
public function getCurrentPage()
{
$currentPage = craft()->request->getQuery($this->pageParam, 1);
if (is_numeric($currentPage) && $currentPage > $this->totalPages)
{
$currentPage = $this->totalPages > 0 ? $this->totalPages : 1;
}
else if (!is_numeric($currentPage) || $currentPage < 0)
{
$currentPage = 1;
}
return (int) $currentPage;
}
/**
* Returns previous page URLs up to a certain distance from the current page.
*
* @param int $dist
*
* @return array
*/
public function getPrevUrls($dist = null, $currentPage, $totalPages)
{
$this->currentPage = $currentPage;
$this->totalPages = $totalPages;
if ($dist)
{
$start = $this->currentPage - $dist;
}
else
{
$start = 1;
}
return $this->getRangeUrls($start, $this->currentPage - 1);
}
/**
* Returns next page URLs up to a certain distance from the current page.
*
* @param int $dist
*
* @return array
*/
public function getNextUrls($dist = null, $currentPage, $totalPages)
{
$this->currentPage = $currentPage;
$this->totalPages = $totalPages;
if ($dist)
{
$end = $this->currentPage + $dist;
}
else
{
$end = $this->totalPages;
}
return $this->getRangeUrls($this->currentPage + 1, $end);
}
/**
* Returns the URL to a specific page
*
* @param int $page
*
* @return string|null
*/
public function getPageUrl($page, $totalPages = false)
{
if ($totalPages)$this->totalPages = $totalPages;
if ($page >= 1 && $page <= $this->totalPages)
{
$path = craft()->request->getPath();
$params = array();
if ($page != 1)
{
// $pageTrigger = craft()->config->get('pageTrigger');
$pageTrigger = '?page';
if (!is_string($pageTrigger) || !strlen($pageTrigger))
{
$pageTrigger = 'p';
}
// Is this query string-based pagination?
if ($pageTrigger[0] === '?')
{
$pageTrigger = trim($pageTrigger, '?=');
if ($pageTrigger === 'p')
{
// Avoid conflict with the main 'p' param
$pageTrigger = 'pg';
}
$params = array($pageTrigger => $page);
}
else
{
if ($path)
{
$path .= '/';
}
$path .= $pageTrigger.$page;
}
}
return UrlHelper::getUrl($path, $params);
}
}
/**
* Returns a range of page URLs.
*
* @param int $start
* @param int $end
*
* @return array
*/
public function getRangeUrls($start, $end)
{
if ($start < 1)
{
$start = 1;
}
if ($end > $this->totalPages)
{
$end = $this->totalPages;
}
$urls = array();
for ($page = $start; $page <= $end; $page++)
{
$urls[$page] = $this->getPageUrl($page);
}
return $urls;
}
}
Set this within the same service (as the code you see below this code block) that returns the comments and the pagination data:
$this->elementsPerPage = $limit;
$this->totalElements = $total;
$this->pageParam = 'page';
$this->totalPages = (int) ceil($this->totalElements / $this->elementsPerPage);
$this->currentPage = craft()->comments->getCurrentPage();
Then in the return, I set the pagination like this:
$result = [
'comments' => $comments,
'pagination' => [
'total' => $total,
'currentPage' => $this->currentPage,
'totalPages' => $this->totalPages,
'nextUrl' => craft()->comments_pagination->getPageUrl($this->currentPage + 1, $this->totalPages),
'prevUrl' => craft()->comments_pagination->getPageUrl(($this->currentPage > 1 ? $this->currentPage - 1 : 1), $this->totalPages),
'prevUrls' => craft()->comments_pagination->getPrevUrls(5, $this->currentPage, $this->totalPages),
'nextUrls' => craft()->comments_pagination->getNextUrls(5, $this->currentPage, $this->totalPages),
'offset' => $offset,
]
];
return $result;
Yeah, that’s what I ended up doing. I actually had to write a field type to get my particular use case working. Thanks so much for responding!
On Jan 18, 2018, at 9:40 AM, Keith Damiani notifications@github.com wrote:
I don't know of any way to convert an EntryModel (which is typically what you'd end up with after performing a custom query) into an ElementCriteriaModel. In one instance where I needed pagination on a custom query result, I ended up writing a plugin and template to build the pagination element manually.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/tightenco/craft-build-query/issues/5#issuecomment-358665978, or mute the thread https://github.com/notifications/unsubscribe-auth/AAW71WwYPP8YYFfiTz83ZnY6zg2qw--yks5tL1fFgaJpZM4Rh4gF.
Pagination is expecting
ElementCriteriaModel
. Is there a way around this?