$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>post meta - Views count with time limit per IP|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

post meta - Views count with time limit per IP

matteradmin7PV0评论

I've been looking for function about post views count. I found this simple functions using update and get post meta.

function setPostViews($postID) {
    $count_key = 'views';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        $count = 0;
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
    }else{
        $count++;
        update_post_meta($postID, $count_key, $count);
    }
}

What I want is, to add functions to limit the count added per IP by given time - a day for example. So when the IP visiting on the same day, it would not counted, just once.

Any idea? Thanks.

I've been looking for function about post views count. I found this simple functions using update and get post meta.

function setPostViews($postID) {
    $count_key = 'views';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        $count = 0;
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
    }else{
        $count++;
        update_post_meta($postID, $count_key, $count);
    }
}

What I want is, to add functions to limit the count added per IP by given time - a day for example. So when the IP visiting on the same day, it would not counted, just once.

Any idea? Thanks.

Share Improve this question asked Sep 15, 2012 at 12:09 rizqyhirizqyhi 1231 silver badge10 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 9

A very basic solution would be to use the Transients API, an example...

function setPostViews($postID) {

    $user_ip = $_SERVER['REMOTE_ADDR']; //retrieve the current IP address of the visitor
    $key = $user_ip . 'x' . $postID; //combine post ID & IP to form unique key
    $value = array($user_ip, $postID); // store post ID & IP as separate values (see note)
    $visited = get_transient($key); //get transient and store in variable

    //check to see if the Post ID/IP ($key) address is currently stored as a transient
    if ( false === ( $visited ) ) {

        //store the unique key, Post ID & IP address for 12 hours if it does not exist
        set_transient( $key, $value, 60*60*12 );

        // now run post views function
        $count_key = 'views';
        $count = get_post_meta($postID, $count_key, true);
        if($count==''){
            $count = 0;
            delete_post_meta($postID, $count_key);
            add_post_meta($postID, $count_key, '0');
        }else{
            $count++;
            update_post_meta($postID, $count_key, $count);
        }


    }

}

The example above works, although it can be expanded to exclude administrators, editors or any other logged in user class/role you would like. This is just to get you going!


Step by step for those that want know what's happening, where.

Using the Transients API we can store values for a predefined period of time, in this example we are storing the result for 12 hours, for 24 hours you would do,

set_transient( $key, $value, 60*60*24 );

What happens when the visitor lands on the post is that we store their IP address in the variable $user_ip.

Then we create a unique key value for our transient which combines the post ID and user IP (i.e. $user_ip . $postID) together, an example would look like,

192.160.0.5x333

Where 192.160.0.5 is the IP and 333 is the Post ID (x is just an example separator to help distinguish the two segments should you need to use those values for any other purpose such as debugging etc)

We then create a $value variable which is an array of any values you wish to store for the transient. In this case we store the IP and Post ID as separate values. You don't need to store them as an array, you could concatenate them together into one string if you would like but by storing them in an array it allows you to more easily iterate over the results of the transient and return the values separate for any purpose you would like, such as logging the results. (modify to suit)

Now we get the transient using get_transient($key) and store it in a variable named $visited. If the transient does not exist or is expired it will return FALSE.

From the Codex;

If the transient does not exist, or has expired, then get_transient will return false. This should be checked using the identity operator instead of the normal equality operator, because an integer value of zero (or other "empty" data) could be the data you're wanting to store. Because of this "false" value, transients should not be used to hold plain boolean values. Put them into an array or convert them to integers instead.

...and that's why we check the existence of our transient value using the identify operator === like so,

if ( false === ( $visited ) ) ...

Now at this point if $visited (our transient) does not exist (evaluates to FALSE) we run our conditional statement and its contents.

First we set the transient value using the variable data we set up outside of our conditional statement,

set_transient( $key, $value, 60*60*12 );

...which adds the unique key and values to the database for 12 hours.

Next we actually run the function which will store a unique post view for the given post that's being served.

Lastly, if and when the user returns to this post within a given 12 hour period our setPostViews function will fire off but this time, since $visited now holds a $key value and is no longer FALSE, the conditional statement will not run and store additional post views.

UPDATE

If you want to exclude views from a certain user role, like the admin, wrap the function within a current_user_can conditional statement like;

function setPostViews($postID) {

    //check if user not administrator, if so execute code block within
    if( !current_user_can('administrator') ) {

       //all code goes here...

    }

}

Functions used in addition to OP,

  • Transients API -> read more

    • set_transient -> read more
    • get_transient -> read more

  • Roles and Capabilities -> read more

    • current_user_can -> read more

I came across this question while looking for something else, but I do have something to add.

The suggested solution is great, except for one minor flaw. Expired transients are only cleared from the options table when they are accessed. So with this solution, your options table will be getting longer and longer. Eventually with hundreds of megs stored in the options table from spammers exploring the blog creating records, your site will start to slow down.

One possible solution is to store a list of ip addresses in a single transient the post ID as the key. Then if the ip address isn't in that list, you add it to the meta options. That still might get to be pretty big per post, but at least it won't result in millions of records. If you write the date as the first line of the transient value, you can check to see if the date is today's date and if it isn't, start a fresh list with the current IP address.

There are probably other solutions involving storing the date in the key or storing an array in the function key valued to IP and date. There are lots of options. But you can't let the transient list simply grow without consequences.

Articles related to this article

Post a comment

comment list (0)

  1. No comments so far