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

Best Method for checking existence of thread_id

Discussion in 'XenForo Development Discussions' started by LPH, Dec 12, 2015.

  1. LPH

    LPH Well-Known Member

    xf_post includes thread_id.

    Which is the most efficient method for checking if a particular thread_id exists?

    Code uses thread_id to build a link but if that thread has been deleted then an error is going to happen, therefore, a thread_id check is necessary.

    I'm thinking of starting with this model but is there a better way?

    PHP:
                    /** @var  $threadModel XenForo_Model_Thread */
                    
    $threadModel XenForo_Model::create('XenForo_Model_Thread')->getModelFromCache'XenForo_Model_Thread' );
                    
    $threads     $threadModel->getThreadsByIds$thread_ids );
    This returns an array, then use a foreach looking for the thread_id. This seems rather intensive if there are over a million threads.

    Any suggestions? Thank you.
     
    Digital Doctor likes this.
  2. Daniel Hood

    Daniel Hood Well-Known Member

    There's no reason to loop through the results. $threadModel->getThreadsByIds($threadIds); returns the existant thread ids as the array keys. Therefore all you have to do is use http://php.net/array_key_exists to check if the thread id is in the existant threads array (you could really also do if (!empty($threads[$threadId])).

    Also just so you know, XenForo_Model::create('XenForo_Model_Thread'); is all you need. Adding the getModelFromCache() call is just redundant.
     
  3. LPH

    LPH Well-Known Member

    As always Daniel, thank you.

    I've never worked with array_key_exists and will read up on it. Had no idea that adding getModelFromCache() is redundant and will have many places to fix.

    In terms of this code, using $threads = $threadModel->getThreadsByIds($threadIds); in the file leads to the page not loading. Simply comment out that line and the content returns. Very strange because no error is being logged.
     
  4. Brogan

    Brogan XenForo Moderator Staff Member

    Although it's redundant in the case you posted, it does actually have a valid use and is quite important.

    If you already have a model call then you can use getModelFromCache in other functions, rather than having multiple XenForo_Model::create.
     
    Daniel Hood likes this.
  5. Daniel Hood

    Daniel Hood Well-Known Member

    Its only redundant because you're already creating the model. Like brogan said, when the function is available it's very important and should be used. In your case though, you're forcing it to exist by creating the model anyways.

    For the line that's errorimg, are you sure $threadIds is an array of ids?
     
  6. LPH

    LPH Well-Known Member

    Thank you both. Since I'm bouncing between motel room and my new home -- my focus is fixing a bug (lack of a feature to error check) -- I haven't read up on the getModelFromCache so no code has been changed. Code will have to be reviewed, though, based on looking for anything redundant. I'm fairly certain my main file calling XenForo (externally) should have the XenForo_Model::create so that getModelFromCache is used throughout the widgets.

    Now -- in terms of my original issue -- the check for existence of a thread_id. The $threadIds was returning a blank page but without an error. After dinking around a bit, slurping on var_export and a few other head-scratching maneuvers ... this appears to work. But I don't like how the array is being pulled ($threads['1']['thread_id'].

    PHP:
                    /**
                    * Check if thread_id exists in XenForo
                    * @since 3.0.0.07
                    * @var $threadModel XenForo_Model_Thread
                    */
                    
    $threadModel XenForo_Model::create('XenForo_Model_Thread');
                    
    $forumId $post['forum_id'];
                 
                    
    // echo '<pre>' . var_export($post, true) . '</pre>';

                    
    $threads $threadModel->getThreadsInForum$forumId );
                 
                    
    //$threads = $threadModel->getThreadsByIds($threadIds);
         
                    
    echo '<pre>' var_export($threads['1']['thread_id'], true) . '</pre>';
                 
                    
    // echo '<pre>' . var_export($threads['thread_id'], true) . '</pre>';
                 
                    // $post['thread_id'] is pulled from WP db
                    
    if ( $post['thread_id'] == $threads['1']['thread_id'] ) {
                        echo 
    '<pre>' var_export($threadstrue) . '</pre>';
                    }
    If the thread is present then the var_export shows, if no thread_id then var_export doesn't show. The $threads['1']['thread_id'] is pretty gross.

    Update: I was fiddling with this var_dump

    PHP:
    var_dump(array_key_exists($post['thread_id'],$threads));  // (bool) TRUE
    Now that is cool !
     
    Last edited: Dec 13, 2015
  7. wang

    wang Well-Known Member

    I think that you can accomplish that with this code. It displays only threads that are visible.

    PHP:
    $threadModel XenForo_Model::create'XenForo_Model_Thread' );

    $threads $threadModel->getThreads( array(
    'discussion_state' => 'visible',
    ), array(
    'limit' => 5,
    'order' => 'thread_id',
    'direction' => 'desc'
    ) );

    foreach ( 
    $threads AS $thread )
    {
    echo(
    "<div class='entry-meta'><a href='"
    XenForo_Link::buildPublicLink'canonical:threads',
    $thread )
    "'>"
    XenForo_Helper_String::wholeWordTrim$thread['title'],
    20 )
    "</a></div>"
    );
    }
     
    Last edited: Dec 13, 2015
  8. LPH

    LPH Well-Known Member

    Thank you @wang but that's a long way around the intent to check existence. This appears to be working:

    PHP:
    /**
    * Check if thread_id exists in XenForo
    * @since 3.0.0.07
    * @var $threadModel XenForo_Model_Thread 
    */
    $threadModel XenForo_Model::create('XenForo_Model_Thread');

    // Pull forum_id from WordPress database                
    $forumId $post['forum_id'];

    // Pull array from XenForo database
    $threads $threadModel->getThreadsInForum$forumId, array( 'discussion_state' => 'visible' ) );
                   
     if ( 
    $post['thread_id'] != && array_key_exists($post['thread_id'],$threads) ) {
         
    // Code to only run if thread_id exists in the XenForo and WordPress databases and is visible.
    }
    I've always been curious, though, if it is best to use != 0 or to use > 0. Guess that is a good question to search.
     
    Last edited: Dec 14, 2015
  9. Jeremy

    Jeremy XenForo Moderator Staff Member

    The two comparisons have different means and could potentially have unexpected outcomes in situations. If you are always sure that thread_id is going to be 0 or a positive integer, they essentially mean the same thing. However, if per chance, you come up with a negative number, $post['thread_id'] != 0 would be true, while $post['thread_id'] > 0 would be false.

    You should use the one that guarantees what you want to occur to occur.
     
  10. rellect

    rellect Well-Known Member

    Unless I'm misunderstanding the situation, why do you use getThreadsInForum()? If all you need is simply to check if thread_id exists, just use getThreadById($thread_id)
     
  11. LPH

    LPH Well-Known Member

    Unfortunately, and maybe it is something that I'm doing wrong, the getThreadById is not honoring the array needed for discussion_state => 'visible'

    This is the code attempt. The challenge is that the thread_id exists but removed from public view -- and it still shows the discussion link to show in the conditional.

    PHP:
            /**
            * Check if thread_id exists in XenForo and is visible
            * @since 3.0.0.07
            * @var $threadModel XenForo_Model_Thread
            */
            
    $threadModel XenForo_Model::create('XenForo_Model_Thread');

            
    $thread $threadModel->getThreadById($post['thread_id'], array( 'discussion_state' => 'visible' ) );

            
    /** Are we displaying comments in WP? */
            
    if ( $xenword_options['display_comments_in_wp'] == true && $thread != false ) {
                 
    // Show discussion link
            
    }
     
  12. Jeremy

    Jeremy XenForo Moderator Staff Member

    XenForo_Model_Thread::getThreadById() doesn't call XenForo_Model_Thread::prepareThreadConditions, nor does it take a $conditions array in. discussion_state is a condition.

    You should be able to simplify your logic (and avoid multiple queries) by doing this:
    PHP:
           /**
    * Check if thread_id exists in XenForo and is visible
    * @since 3.0.0.07
    * @var $threadModel XenForo_Model_Thread
    */
    $threadModel XenForo_Model::create('XenForo_Model_Thread');

    $thread $threadModel->getThreadById($post['thread_id']);

    /** Are we displaying comments in WP? */
    if ( $xenword_options['display_comments_in_wp'] == true && $thread != false && $thread['discussion_state'] == 'visible') {
    // Show discussion link
    }
     
  13. LPH

    LPH Well-Known Member

    @Jeremy -- Dang I need a new brain. May I borrow yours for the next few decades? I should have thought about putting it in the conditional.

    Create thread from WP, then remove thread from public view:

    http://preview.7sm9f3nwe01z6w29cqbo...3/create-thread-then-remove-from-public-view/

    Works !

    Create thread from WP, then delete thread permanently

    http://preview.7sm9f3nwe01z6w29cqbo...ere.com/2015/12/11/create-thread-then-delete/

    Now the link doesn't show in either case. Cool.

    Next issue is to fix the comment_form() mess that is made when the thread is deleted. At least this nasty mistake made in my code years ago is partially fixed.

    Onward !! I love XenForo !!
     

Share This Page