1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Model returns list of thread ID's, what now?

Discussion in 'XenForo Development Discussions' started by Marcel, Jan 9, 2014.

  1. Marcel

    Marcel Active Member

    Im on my way with this plugin

    At the moment I have the following

    A ControllerPublic with the following code

    PHP:
    <?php

    class MaB_NewPosts_ControllerPublic_NewPosts extends XenForo_ControllerPublic_FindNew {
     
    public function 
    actionIndex()
    {
        
    $threadIds $this->getModelFromCache('MaB_NewPosts_Model_NewPosts')->getUnreadThreads();
        If (!
    $threadIds){
            return 
    $this->responseMessage(new XenForo_Phrase('mab_np_noresults'));
        }

        
    // If we're at this point then     there must be results.
     
        
    $viewParams = array('threads' => $threadIds);
        return 
    $this->responseView('MaB_NewPosts_ViewPublic_NewPosts''mab_np_main',$viewParams);
        }

     
    }
    and a model which extends XenForo_Model_Thread

    PHP:
    <?php

    class MaB_NewPosts_Model_NewPosts extends XenForo_Model_Thread
    {


    /**
    * Gets the IDs of threads
    *
    * @param integer $userId
    * @return array List of thread IDs
    */
        
    public function getUnreadThreads()
        {
        return 
    $this->_getDb()->fetchAll('
                        SELECT thread.*
                        FROM xf_thread AS thread
                        LEFT JOIN xf_node AS node ON
                            (node.node_id = thread.node_id)
                        LEFT JOIN xf_thread_read AS thread_read ON
                            (thread_read.thread_id = thread.thread_id AND thread_read.user_id = 1
                            AND thread_read.thread_read_date >= thread.last_post_date)
                        LEFT JOIN xf_forum_read AS forum_read ON
                            (forum_read.node_id = thread.node_id AND forum_read.user_id = 1
                            AND forum_read.forum_read_date >= thread.last_post_date)
                        WHERE thread_read.thread_read_date IS NULL
                        ORDER BY thread.last_post_date DESC
                LIMIT 50'
    );
     
        }
    }
    Now this works. It returns an array $threads filled with the relevant (unread) thread ID's and all the fields from the xf_thread table corresponding to each row selected.

    Now, I want to parse this into a viewable list of results.
    I've passed it to my template (which is a copy of thread_list with some bumpf taken out )
    This shows some of the data needed. However, it doesn't for example, pull out the thread starter avatar, the node title etc.
    How would I add these? I understand theyre from a different table, and my controller and model don't retrieve this data....
    I tried with very limited knowledge of SQL to add it to the query in the model, but got stuck.

    I know the whole structure is very primitive, but it's something I plan on building on. Naturally there will be permissions checks, pagination of results etc.
    I also tried extending both the ControllerPublic class and the Model class via the XFCP method, but it didn't work, so I hope this is the correct way to do it!
    This is executed by a route prefix /newposts
    I hope to build on this with newposts/discussion ..... newposts/images etc etc. Hence doing it via a route controller :)
     
    Last edited: Jan 9, 2014
  2. Marcel

    Marcel Active Member

    Forgot to add, I can't remember why I extended ControllerPublic_FindNew.
     
  3. Marcel

    Marcel Active Member

    Been looking at this again today. I've changed the ControllerPublic to extend XenForo_ControllerPublic_Thread
    After the $threadIds array is filled with a list of thread_Id's I've then added the following

    $threads = $this->getModelFromCache('XenForo_Model_Thread')->getThreadsbyIds($threadIds,$fetchOptions);

    Then I was planning on returning $threads to the template, as I assumed that would have all the thread details in.
    Nope...it actually returns a bigger list of threads (I think it's all of them).

    So in a nutshell, after pulling a list of thread ID's, how do I then use that to pull last poster, avatar, replies, views node information, etc etc for each row.
     
  4. Brogan

    Brogan XenForo Moderator Staff Member

    Have you tried dumping the param either in the php or the template to see what's available?

    Zend_Debug::dump($param); or {xen:helper dump, $param}
     
  5. Marcel

    Marcel Active Member

    Thanks Brogan. I did use the dump helper to have a look at the data passed back.
    I've looked at Andy's plugin (thanks for that!), and it seems an update in the Model is the way to go.
    I've modified the SQL statement, selecting
    xf_user.user_id, xf_user.avatar_date
    then adding
    INNER JOIN xf_user ON xf_user.user_id = xf_thread.user_id

    It works, so I'm now building it properly to pull correct visitor information, and then I'll work on the permissions etc.

    Thank you both for your replies, much appreciated :)
    I must say Andy, I'm learning alot from the threads you've started and the questions you've asked on what I assume is the same journey as I am on :)

    One further question

    My ControllerPublic extends XenForo_ControllerPublic_Thread
    and my Model extends XenForo_Model_Thread. It all works, but Im not using the Class Proxy system for either.
    When I do try to extend the XFCP etc etc, I get an error.
    I can understand why this happens if I try and use the XFCP with the Controller, as I'm not actually hooking into anything with it, it's because I'm creating a new Controller.
    Is this the right way to do it? Should I be extended a different controller other than Thread?
     
  6. Brogan

    Brogan XenForo Moderator Staff Member

    If you are extending the thread controller then it should be: class Your_Class_ControllerPublic_Thread extends XFCP_Your_Class_ControllerPublic_Thread
     
  7. Marcel

    Marcel Active Member

    I tried that but I just get the error

    An exception occurred: Cannot load class using XFCP. Load the class using the correct loader first.
    Am I right in thinking that this error is generated because it's expecting XenForo_ControllerPublic_Thread to already be loaded when it loads myaddon_ControllerPublic_Thread....and this plugin doesn't rely on that.

    As I'm not actually building on any methods or functionality in XenForo_ControllerPublic_Thread, I shouldn't really be extending it.
    The question is, I don't know what I should be extending.

    All I'm doing is running a custom query using my thread model and returning a list of results.
    I've not extended ControllerPublic_Search (as that was too messy and unnecessary).
     
    Last edited: Jan 11, 2014
  8. Brogan

    Brogan XenForo Moderator Staff Member

    What is your actual code and the structure of your files?
     
  9. Marcel

    Marcel Active Member

    This is the file structure
    (Ignore the Option folder)
    NewPostsStructure.jpg

    Contents of ControllerPublic/NewPosts.php
    PHP:
    <?php

    class MaB_NewPosts_ControllerPublic_NewPosts extends XenForo_ControllerPublic_Thread {

    public function 
    actionIndex()
    {
        
    $threads $this->getModelFromCache('MaB_NewPosts_Model_NewPosts')->getUnreadThreads();

        If (!
    $threads){
            return 
    $this->responseMessage(new XenForo_Phrase('mab_np_noresults'));
        }
        
    $viewParams = array('threads' => $threads);
        return 
    $this->responseView('MaB_NewPosts_ViewPublic_NewPosts''mab_np_results',$viewParams);
    }

    // end class
    Contents of Listener/Extend.php
    PHP:
    <?php
    class MaB_NewPosts_Listener_Extend
    {
        public static function 
    loadClassController($class, array &$extend)
        {
            
    $extend[] = 'MaB_NewPosts_ControllerPublic_NewPosts';
        }

    }
    Contents of Listener/NavTabs.php
    PHP:
    <?php
    class MaB_NewPosts_Listener_NavTabs
    {
        public static function 
    addNavTab(array &$extraTabs$selectedTabId)
        {
            
    $extraTabs['NewPosts'] = array (
                
    'title' => new XenForo_Phrase('mab_np_newposts'),
                
    'href' => XenForo_Link::buildPublicLink('newposts'),
                
    'position' => 'end',
                
    'selected' =>  ($selectedTabId == 'newposts'),
                
    'linksTemplate' => 'mab_np_navtab'
            
    );

        }
    }
    Contents of Model/NewPosts.php
    PHP:
    <?php

    class MaB_NewPosts_Model_NewPosts extends XenForo_Model_Thread
    {
        public function 
    getUnreadThreads()
        {
        
    $userId '1';
        
    $maxResults XenForo_Application::get 'options' )->get 'maximumSearchResults' );
        
    /* if $newPostsType = 'discussion'
        {
        }*/


        
    $extraConditions "AND xf_thread.node_id = 8";
        
    //$extraConditions = "";
        
    return $this->_getDb()->fetchAll("
    SELECT xf_thread.thread_id,
            xf_thread.title,
            xf_thread.reply_count,
            xf_thread.view_count,
            xf_thread.username,
            xf_node.title AS nodeTitle,
            xf_thread_user_post.post_count AS user_post_count,
            xf_user.user_id,
            xf_user.avatar_date
            FROM xf_thread
            INNER JOIN xf_node ON xf_node.node_id = xf_thread.node_id
            LEFT JOIN xf_thread_user_post
                ON (xf_thread_user_post.thread_id = xf_thread.thread_id
                AND xf_thread_user_post.user_id = " 
    $userId ")
            INNER JOIN xf_user ON xf_user.user_id = xf_thread.user_id
            LEFT JOIN xf_thread_read
                ON (xf_thread_read.thread_id = xf_thread.thread_id AND xf_thread_read.user_id = " 
    $userId "
                AND xf_thread_read.thread_read_date >= xf_thread.last_post_date)
            WHERE xf_thread_read.thread_read_date IS NULL
            " 
    $extraConditions "
            ORDER BY xf_thread.view_count DESC
                LIMIT ?"
    $maxResults);

        }
    }
    Contents of Route/Prefix/NewPosts.php
    PHP:
    <?php



    class MaB_NewPosts_Route_Prefix_NewPosts implements XenForo_Route_Interface

    {



    public function 
    match($routePathZend_Controller_Request_Http $requestXenForo_Router $router)

    {

    //return $router->getRouteMatch('MaB_NewPosts_ControllerPublic_NewPosts', $routePath, 'newposts');

    $action $router->resolveActionWithIntegerParam($routePath$request'search_id');

    return 
    $router->getRouteMatch('MaB_NewPosts_ControllerPublic_NewPosts'$action'newposts');

    }



    }
     
  10. Marcel

    Marcel Active Member

    Sorry if there is something wrong in there. I've been changing it back and forth, I changed MaB_NewPosts_ControllerPublic_NewPosts, to MaB_NewPosts_ControllerPublic_Thread after your post above (I thought you could name the last part of the class anything you wanted until you posted, then thought "It's because I called it "NewPosts" instead of "Thread", so I changed it ......still didn't work, so I changed it back :))
     
  11. Brogan

    Brogan XenForo Moderator Staff Member

    If you are extending the thread controller, why is your file/class called NewPosts?
     
  12. Marcel

    Marcel Active Member

    I thought you could name it whatever you wanted :$.
     
  13. Brogan

    Brogan XenForo Moderator Staff Member

    Well typically if you are extending the thread controller it would be like so:
    upload_2014-1-11_19-12-23.png
     
  14. Marcel

    Marcel Active Member

    Cheers. I'll rename it all now, if that's the proper way of doing it.
    However, I'm still getting that error when I try and load it via the XFCP system.
    I think it's because my listener isn't triggering because the thread controller is not being loaded.
    So the question is, with the above code, what *should* I be listening for / extending?
     
  15. Brogan

    Brogan XenForo Moderator Staff Member

    In the ACP you would have an event hint of: XenForo_ControllerPublic_Thread

    Then just the standard listener code:
    PHP:
    public static function extendThreadController($class, array &$extend)
    {
        
    $extend[] = 'CTA_FeaturedThreads_ControllerPublic_Thread';
    }
     
  16. Marcel

    Marcel Active Member

    Already tried that :) Still get the same error.
    Infact, I think the correct way to do this would be to have no listener, and to extend XenForo_Controller_Abstract, no?
    I'm not sure which Controller I should be hooking into/extending (If any)
     
  17. Brogan

    Brogan XenForo Moderator Staff Member

    What does your add-on actually do?

    Does it utilise the threads route?
    Do you need to extend an existing function?
     
  18. Marcel

    Marcel Active Member

    It doesn't, I've created my own route 'newposts'
    Basically, it pulls a list of unread threads with different criteria.
    At the moment, it does all forums, all threads with unread posts.
    It will eventually have many choices which correspond to different sets of criteria
    For example :

    Link 1 will return all threads with unread posts from forum x and y.
    Link 2 will return all threads with unread posts from forum y and z
    Link 3 will return all threads with unread posts from forum y, and prefix 1
    Link 4 will return all threads with zero replies from forum x, y and z with prefix 1

    etc
    Extending the search controller to do this was too difficult (as that was expecting searches from an input form, searching for particular data PLUS criteria)
    The same with extending new-posts, I didn't think it was suitable for what I wanted to do.
    Hence why I went down this path.
    It has its own route prefix, and therefore it's own controller.
     
  19. Marcel

    Marcel Active Member

    Actually, I've just been reading through the original Thread model.
    I should be able to do this by using that, rather than my own model.

    I could use the following functions :
    getUnreadThreadIds, getThreadsByIds, prepareThreadFetchOptions

     

Share This Page