• 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

LPH

Well-known member
#1
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.
 

Daniel Hood

Well-known member
#2
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.
 

LPH

Well-known member
#3
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.
 

Brogan

XenForo moderator
Staff member
#4
Had no idea that adding getModelFromCache() is redundant
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

Well-known member
#5
Had no idea that adding getModelFromCache() is redundant and will have many places to fix.
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?
 

LPH

Well-known member
#6
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($threads, true) . '</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:

wang

Well-known member
#7
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:

LPH

Well-known member
#8
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'] != 0 && 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:

Jeremy

Well-known member
#9
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.
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.
 

rellect

Well-known member
#10
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)
 

LPH

Well-known member
#11
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)
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
        }
 

Jeremy

Well-known member
#12
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
}
 

LPH

Well-known member
#13
@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 !!