XF 2.2 Limit Finder results and limitByPage

Idhae

Active member
Hey togther,
i need some advice.
How can I get a limited number of threads from thread finder and use the pagination stuff at the same time?

PHP:
public function actionMostLiked()
    {
        $limitThreadsResults = 10; // for performance reasons
 
        $page = $this->filterPage();
        $perPage = $this->options()->discussionsPerPage;

        $threadFinder = $this->getThreadRepo()->findThreadsWithMostLiked();
        $threadFinder->limitByPage($page, $perPage )->limit($limitThreadsResults);

        $total = $threadFinder->total();

If i do the ->limit in the repository of my custom findThreadsWithMostLiked the limitByPage in the controller overwrides the custom limit.
That line $threadFinder->limitByPage... seems to work but $total is not limited, $total gets all threads mathing without ->limit.
 
Last edited:
extended XF\Pub\Controller:
PHP:
<?php
class FindThreads extends XFCP_FindThreads
{
    public function actionMostLiked()
    {
//        $limitThreadsResults = $this->options()->maximumSearchResults; // for performance reasons
        $limitThreadsResults = 10; // 10 for debugging reasons
        $page = $this->filterPage();
        $perPage = $this->options()->discussionsPerPage;

        $threadFinder = $this->getThreadRepo()->findThreadsWithMostLiked();
        $threadFinder->limitByPage($page, $perPage )->limit($limitThreadsResults);
        \XF::dumpSimple($threadFinder->getQuery()); // debugging reasons

        $total = $threadFinder->total(); /**todo doesnt work, $total is unlimited!!*/
        \XF::dump($total); // debugging reasons

        $threads = $threadFinder->fetch()->filterViewable();

        /** @var \XF\Entity\Thread $thread */
        $canInlineMod = false;
        foreach ($threads AS $threadId => $thread)
        {
            if ($thread->canUseInlineModeration())
            {
                $canInlineMod = true;
                break;
            }
        }

        $viewParams = [
            'page' => $page,
            'perPage' => $perPage,
            'total' => $total,
            'threads' => $threads->filterViewable(),
            'canInlineMod' => $canInlineMod,
            'user' => $this->user,
            'pageSelected' => 'mostliked',
        ];
        return $this->view('XF:FindThreads\List', 'find_threads_list', $viewParams);
    }
}

extended XF\Repository:
PHP:
<?php

class Thread extends XFCP_Thread
{
    public function findThreadsWithMostLiked()
    {
        return $this->finder('XF:Thread')
            ->where('discussion_state', 'visible')
            ->where('discussion_type', '<>', 'redirect')
            ->where('first_post_reaction_score', '>=', 1)
            ->order('first_post_reaction_score', 'DESC');
    }
}
 
\XF\Mvc\Entity\Finder::total is for counting all possible results. You might want $threads->count() instead if you're just trying to count fetched results.
 
\XF\Mvc\Entity\Finder::total is for counting all possible results. You might want $threads->count() instead if you're just trying to count fetched results.
That works for $total but on page two in pagination the limit is not working for the threads, it shows again all results.
 
Last edited:
You are calling limit after limitByPage. limitByPage is just a convenience method for calculating the limit and offset from the page and per-page values, so calling limit afterwards will wind up overriding those values.
 
Do not call limit after limitByPage. If you want to only fetch 10 threads per page, set $perPage to 10.
 
i think we don't understand each other...sry for my bad english ;)

At first i want LIMIT the whole RESULT, i think 200 Results ($this->options()->maximumSearchResults) over all threads are enaugh.
Then i need for these 200 maximumSearchResults a working pagination and that is the problem, i don't get it to work.
I tried many thinks from what you pointed out.
 
Last edited:
I need something like this query.
For example $limitThreadsResults = $this->options()->discussionsPerPage;

PHP:
$offset = ($page - 1) * $perPage;

return $db->fetchAll("
    SELECT resulsts.*
    FROM (
            SELECT `xf_thread`.*
            FROM `xf_thread`
            WHERE (`xf_thread`.`discussion_state` = 'visible') AND (`xf_thread`.`discussion_type` <> 'redirect') AND (`xf_thread`.`first_post_reaction_score` >= 1)
            ORDER BY `xf_thread`.`first_post_reaction_score` DESC
            LIMIT ?
        ) AS resulsts
    LIMIT ?,?
", [$limitThreadsResults, $perPage, $offset]);
 
Fetch the total separately and upper bound it to your maximum pages to build the pagination itself, then use the normal limitByPage after you ensured that the given page lies within the custom maximum number of pages.
 
Thanks for your advice, i tried something like this and others many times, but on page 2 i have more results as i have to.
Just for clarification, my development environment has 26 results without cutom limit, thats why i limit $limitThreadsResults to 21 in the code below. On page 2 im getting then 6 results an not 1 as it should so.

findThreadsMostLikedTotal to get $total with my cutom limitThreadsResults
findThreadsMostLikedByPage to get $threads by page

extended XF\Pub\Controller:
PHP:
class FindThreads extends XFCP_FindThreads
{
    public function actionMostLiked()
    {
//        $limitThreadsResults = $this->options()->maximumSearchResults; // for performance reasons
        $limitThreadsResults = 21;
        $page = $this->filterPage();
        $perPage = $this->options()->discussionsPerPage;

        $threadFinder = $this->getThreadRepo()->findThreadsMostLikedTotal($limitThreadsResults);
        $total = $threadFinder->fetch()->count();
\XF::dump($total); //for debugging


        $threadFinder = $this->getThreadRepo()->findThreadsMostLikedByPage();
        $threadFinder->limitByPage($page, $perPage);

        $threads = $threadFinder->fetch()->filterViewable();
\XF::dump($threads); //for debugging


        /** @var \XF\Entity\Thread $thread */
        $canInlineMod = false;
        foreach ($threads AS $threadId => $thread)
        {
            if ($thread->canUseInlineModeration())
            {
                $canInlineMod = true;
                break;
            }
        }

        $viewParams = [
            'page' => $page,
            'perPage' => $perPage,
            'total' => $total,
            'threads' => $threads->filterViewable(),
            'canInlineMod' => $canInlineMod,
            'user' => $this->user,
            'pageSelected' => 'mostliked',
        ];
        return $this->view('XF:FindThreads\List', 'find_threads_list', $viewParams);
    }

}


extended XF\Repository
PHP:
class Thread extends XFCP_Thread
{
    public function findThreadsMostLikedTotal($limitThreadsResults)
    {
        return $this->finder('XF:Thread')
            ->where('discussion_state', 'visible')
            ->where('discussion_type', '<>', 'redirect')
            ->where('first_post_reaction_score', '>=', 1)
            ->order('first_post_reaction_score', 'DESC')
            ->limit($limitThreadsResults);
    }
    public function findThreadsMostLikedByPage()
    {
        return $this->finder('XF:Thread')
            ->where('discussion_state', 'visible')
            ->where('discussion_type', '<>', 'redirect')
            ->where('first_post_reaction_score', '>=', 1)
            ->order('first_post_reaction_score', 'DESC');
    }
}
 
So no ideas anymore :rolleyes: i do it now like that and looking for performance issues on big forums.

extended XF\Pub\Controller:
PHP:
class FindThreads extends XFCP_FindThreads
{
    public function actionMostLiked()
    {
        $threadFinder = $this->getThreadRepo()->findThreadsMostLiked();

        return $this->getThreadResults($threadFinder, 'mostliked');
    }

    protected function getThreadResults(\XF\Finder\Thread $threadFinder, $pageSelected)
    {
        $parent = parent::getThreadResults($threadFinder, $pageSelected);
        if($pageSelected == 'mostliked'){
             $limitThreadsResults = $this->options()->maximumSearchResults; // for performance reasons
             $threadFinder = $this->getThreadRepo()->findThreadsMostLiked($limitThreadsResults);
             $total = $threadFinder->fetch()->count();
             $parent->setParam('total', $total);
        }
        return $parent;
    }
}

extended XF\Repository
PHP:
class Thread extends XFCP_Thread
{
    public function findThreadsMostLiked($limitThreadsResults = null)
    {
        return $this->finder('XF:Thread')
            ->where('discussion_state', 'visible')
            ->where('discussion_type', '<>', 'redirect')
            ->where('first_post_reaction_score', '>=', 1)
            ->order('first_post_reaction_score', 'DESC')
            ->limit($limitThreadsResults);
    }
}

Edit: add if condition in protected function getThreadResults.
 
Last edited:
Top Bottom