Function for displaying posts by number of views

Today I want to share with you another function for displaying posts. The function is a direct addition to the article "Counting page views on WordPress without plugins". The task of the function is to display posts sorted by a custom field that collects the number of views for each post. In simpler terms, the function displays the most viewed posts of the blog/site on WordPress.

However, in order to apply this function, it is necessary to first use the code from the article, the link to which I provided above. This code will count the number of page views and record them in a custom field. The function from this article will then display the posts based on this custom field, i.e., by the highest number of views.

So, let's get acquainted.

Also take a look at the premium plugin Kama Postviews.

Function for displaying the most viewed posts

/**
 * Function for displaying posts based on a custom field containing a numerical value.
 *
 * Example usage:
 *     kama_get_most_viewed( "num=5 &key=views &cache=1 &format={a}{title}{/a} - {date:j.M.Y} ({views}) ({comments})" );
 *
 * @param string $args {
 *
 *     @type string     $key    (views)  The key of the custom field, based on which the selection will be made.
 *     @type int|string $num    (10)     Number of posts or offset for pagination - 10 or 20,10.
 *     @type string     $order  (desc)   Order of posts. Can be: asc|desc.
 *     @type string     $format  ('')    Format of displayed links. By default: ({a}{title}{/a}).
 *                                       You can use, for example, this format:
 *                                       {date:j.M.Y} - {a}{title}{/a} ({views}, {comments}).
 *     @type int        $days   (0)      Number of recent days from which posts need to be displayed
 *                                       based on the number of views. If a year is specified (2011, 2010),
 *                                       popular posts for that year will be selected.
 *     @type int        $cache  (0)      Use cache or not. Options: 1 - caching enabled, 0 - disabled (default).
 *     @type string     $echo   (1)      Display on the screen or not. Options: 1 - display (default), 0 - return for processing.
 *     @type string     $return (string) Can be: string|array. Allows to return an array of post objects, rather than ready-made HTML.
 * }
 *
 * @return string|array Depends on `return` argument.
 *
 * @ver 1.3
 */
function kama_get_most_viewed( $args = '' ){
	global $wpdb, $post;

	parse_str( $args, $i );

	$num    = isset( $i['num'] )    ? preg_replace( '/[^0-9,\s]/', '', $i['num'] ) : 10; // 20,10 | 10
	$key    = isset( $i['key'] )    ? sanitize_text_field( $i['key'] ) : 'views';
	$order  = isset( $i['order'] ) && ( strtoupper( $i['order'] ) === 'ASC' ) ? 'ASC' : 'DESC';
	$days   = isset( $i['days'] )   ? (int) $i['days'] : 0;
	$format = isset( $i['format'] ) ? stripslashes( $i['format'] ) : '';
	$cache  = isset( $i['cache'] );
	$echo   = isset( $i['echo'] )   ? (int) $i['echo'] : 1;
	$return = isset( $i['return'] ) ? $i['return'] : 'string';

	if( $cache ){
		$cache_key = md5( __FUNCTION__ . serialize( $args ) );

		if( $cache_out = wp_cache_get( $cache_key ) ){
			if( $echo ){
				return print( $cache_out );
			}

			return $cache_out;
		}
	}

	$AND_days = $days ? "AND post_date > CURDATE() - INTERVAL $days DAY" : '';
	if( 4 === strlen( $days ) ){
		$AND_days = "AND YEAR(post_date)=$days";
	}

	$esc_key = esc_sql( $key );

	$sql = "SELECT *, (pm.meta_value+0) AS views
	FROM $wpdb->posts p
		LEFT JOIN $wpdb->postmeta pm ON (pm.post_id = p.ID)
	WHERE pm.meta_key = '$esc_key' $AND_days
		AND p.post_type = 'post'
		AND p.post_status = 'publish'
	ORDER BY views $order LIMIT $num";

	$posts = $wpdb->get_results( $sql );
	if( ! $posts ){
		return false;
	}

	if( 'array' === $return ){
		return $posts;
	}

	$out = $x = '';
	preg_match( '!{date:(.*?)}!', $format, $date_m );

	foreach( $posts as $pst ){

		$x = ( $x === 'li1' ) ? 'li2' : 'li1';

		if( $pst->ID == $post->ID ){
			$x .= ' current-item';
		}

		$Title    = $pst->post_title;
		$a1       = '<a href="' . get_permalink( $pst->ID ) . "\" title=\"{$pst->views} просмотров: $Title\">";
		$a2       = '</a>';
		$comments = $pst->comment_count;
		$views    = $pst->views;

		if( $format ){

			$date    = apply_filters( 'the_time', mysql2date( $date_m[ 1 ], $pst->post_date ) );
			$Sformat = str_replace( $date_m[0], $date, $format );
			$Sformat = str_replace( [ '{a}', '{title}', '{/a}', '{comments}', '{views}' ], [ $a1, $Title, $a2, $comments, $views, ], $Sformat );
		}
		else {
			$Sformat = $a1 . $Title . $a2;
		}

		$out .= "<li class=\"$x\">$Sformat</li>";
	}

	if ( $cache ) {
		wp_cache_add( $cache_key, $out );
	}

	if ( $echo ) {
		echo $out;
	}

	return $out;
}
/**
 * 1.3 - Minor edits.
 * 1.2 - Added the 'return' parameter and slight refactoring.
 * 1.1 - Offset can now be specified in `num`.
 */

As usual, you need to place this code in your theme's functions.php file or where you will use this function. If you don't have such a file, you can and probably should create it!

Once the function is copied into functions.php, you can use it. How? Very simple: open the template file and where you want to display the list of most viewed posts, call the function (insert the following code):

<ul>
	 <?php kama_get_most_viewed("num=10"); ?>
</ul>

where, num=10 — specifies how many posts to show in the list.

That's all, the function should work.

Advanced Usage

Those who looked into the function code probably noticed the line "Parameters passed to the function" at the beginning, and guessed that the function is not simple. The display can be customized a bit, and I will definitely explain how to do it.

Parameters that can be passed to the function:
  • num - the number of links (posts) to display in the list. By default, it displays 10;

  • key - the name of the custom field key, based on which the selection will be made. Since the key "Views" is used in the function for counting views, this parameter defaults to "Views".

  • format - Format of displayed links. By default, the format is: {a}{title}{/a}. When changing the format, the following shortcodes can be used:
  • {comments} - displays the number of comments for the article;
  • {title} - article title;
  • {date:j.M.Y} - date in the j.M.Y format (11.Apr.2010);
  • {a} and {/a} - link tags. Opens and closes.
  • {views} - number of post views.

  • days - the number of recent days from which posts need to be displayed based on the number of views. If a year is specified (2011, 2010), popular posts for that year will be selected.

  • cache - whether to use cache or not. Options: 1 - caching enabled, 0 - disabled (default). Caching will work only with query caching plugins. Caching is disabled by default.

  • echo - display on the screen or return for further processing. 1 - display on the screen (default), 0 - return for processing.

Usage Examples

#1. List of the 15 most viewed posts

In this case, the list should include the post date and the number of views. Implemented as follows:

<ul>
	 <?php kama_get_most_viewed("num=15 &format={a}{title}{/a} - {date:j.M.Y} ({views}, {comments})"); ?>
</ul>

will display the list in the format: Article Title - 11.Apr.2010 (2300, 25) where, 2300 - views, 25 - comments.

#2. Change the custom field key

To do this, add &key=<new key name> to the parameters

<ul>
	 <?php kama_get_most_viewed("num=15 &format={a}{title}{/a} - {date:j.M.Y} ({views}, {comments}) &key=views"); ?>
</ul>

will display the list in the format: Article Title - 11.Apr.2010 (2300, 25). The posts will be selected based on the custom field with the value "views".

#3. Display the 15 most viewed posts in the last 3 months (90 days):

<ul>
	 <?php kama_get_most_viewed("num=15 &days=90"); ?>
</ul>

That's all.

If you have any questions while reading or when installing this function, the blog comments are just for that.