开发者

wordpress show random post that hasn't been shown earlier

I created this really simple function following the documentary of WordPress and as I understood it, this code should be working just fine

query_posts(array('orderby' => 'rand', 'post__not_in' => $_SESSION['watch开发者_如何学编程ed'], 'showposts' => 1));

and the code for the session is no more advanced then this

if(!in_array($post->ID, $_SESSION['watched'])){
    array_push($_SESSION['watched'],$post->ID);
}

If you know of any other solution or how to fix this specific one all answers are very much appreciated... If I missed something out just tell me and I'll add that information.


This topic on wordpress.org seems relevant to your question - there are obviously some rather weird issues with post__not_in.

Try this:

function removeSeenPosts ($where) {
    global $wpdb;
    if (count($_SESSION['watched']) > 0) {
        $where .= ' AND ' . $wpdb->posts . '.ID NOT IN(' . implode (',', $_SESSION['watched']) . ') ';
    }
    return $where;
}

add_filter('posts_where', 'removeSeenPosts');
query_posts(array('orderby' => 'rand', 'showposts' => 1));
remove_filter('posts_where', 'removeSeenPosts');

If that doesn't help (which I actually suspect), the problem is clearly related to the post ids' storage in the session.

Two things come to mind:

  • Can $_SESSION be populated after anything but headers has been sent? I don't remember …
  • Storing the posts in a proper cookie seems like a viable alternative and would, as an added bonus, make the storage persistent across sessions.

Untested implementation as a plugin:

function setViewedPostCookies() {
    if (is_single())
    {
        global $wp_query;
        if (!isset($_COOKIE['watched']))
        {
            $excluded_posts = array();
        }
        else
        {
            $excluded_posts = implode(',', $_COOKIE['watched']);
        }
        $excluded_posts[] = $wp_query->post->ID;
        $excluded_posts = array_unique($excluded_posts);
        setcookie('watched', explode(',', $excluded_posts), time() + 3600000, '/');
    }
}

add_action( 'get_header', 'setViewedPostCookies' );


This can't work with $_SESSION['watched'] array because $_SESSION variable not linked to the MySQL table and as result formatted query didn't know how many posts it should return.

I see only one solution to solve this task correctly:

You need to create one more table in database that can store session_id and post_id variables. For example we name this table wp_watched.

For example structure of our table will be:

CREATE TABLE wp_watched (
    `watched_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `watched_SID` varchar(255) DEFAULT NULL,
    `watched_POST_ID` bigint(20) NOT NULL DEFAULT '0',
    PRIMARY KEY (`watched_ID`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

And data will store on our table like this:

`watched_ID` |           `watched_SID`          | `watched_POST_ID`
---------------------------------------------------------------------------------
1            | 098f6bcd4621d373cade4e832627b4f6 | 345 
2            | 88578edf8458ce06fbc5bb76a58c5ca4 | 123
3            | 1a36591bceec49c832079e270d7e8b73 | 5
4            | 2b1d3a6249c2d223c620393fa6420868 | 98
5            | 793560d7e4ef27db84dfe776fed9cea5 | 12
...

Then your code for session you need to rewrite for something like this, using custom queries:

$watchedrows = $wpdb->get_row("SELECT watched_ID FROM wp_watched WHERE watched_SID = " . session_id() . " AND watched_POST_ID = " . $post->ID);
if(!$watchedrows->watched_ID) {
    $wpdb->insert('wp_watched', array('watched_SID' => session_id(), 'watched_POST_ID' => $post->ID), array('%s', '%d'));
}

Then you need to create your own custom query to get posts based on connection between wp_posts table and wp_watched table:

$querystr = "
    SELECT 
        $wpdb->posts.* 
    FROM 
        $wpdb->posts, 
        wp_watched
    WHERE 
        $wpdb->posts.post_status = 'publish' 
        AND $wpdb->posts.post_type = 'post'
        AND $wpdb->posts.post_date < NOW()
        AND wp_watched.watched_SID = " . session_id() . "
        AND $wpdb->posts.ID != wp_watched.watched_POST_ID
    ORDER BY RAND()
    LIMIT 1";
$randompost = $wpdb->get_row($querystr, OBJECT);

Then if everything is ok variable $randompost will contain your random post.

Not sure if code I provide works, I didn't test it. Maybe some SQL selects need to be rewritten.

Just to show you direction where you need to go.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜