根据当天的访问次数和日期查询帖子的最有效方式是什么?

时间:2014-11-13 作者:Gixty

我将为我的网站开发一段代码,以显示当天最受欢迎的帖子,这些帖子已经发布了X天了。我希望您能提供一些帮助,以最有效的方式实现这一目标。

这就是我打算做的,请告诉我是否有更有效的方法。

将每个帖子视图保存在只存在于当前日期的帖子元中。我已经启用了jetpack,所以我可以使用它来获取每个帖子的视图。

通过包含当天访问量的帖子元查询帖子(使用WP\\u查询)。

  • 按日期应用筛选(以获取X天以前的帖子)。所以我可以选择帖子的年龄。例如,我可以显示最受欢迎的帖子,这些帖子最多发布一个月。查询时不考虑一个月以上的帖子。

    将查询保存在一个每小时更新一次的临时文件中(这样我就不会每次显示popularposts时都调用查询)。我希望每小时都这样,因为我想每小时向访问者展示新内容。

    第二天,当用户访问帖子时,帖子元将被删除,并为当天创建一个新的元。

    注:我有成千上万的帖子。

    如果我遗漏了什么,请告诉我。

  • 1 个回复
    最合适的回答,由SO网友:gmazzap 整理而成

    我认为你可以提高绩效

    将视图信息保存在单个选项中,而不是保存在post meta中,在保存时而不是检索时应用筛选日期创建标记并在瞬态中保存,而不是在类中保存查询(片段缓存

    class PopularPosts
    {
    
      const OPT = \'myplugin_popular_posts\';
    
      /**
       * After checking post date to see if save or not, increment a counter in a option
       * as an array where keys are post ids and values number of views
       */
      public function save(WP_Post $post)
      {
        if ( ! $this->shouldSave($post))
            return;
        $opt = get_option(self::OPT, array());
        if ( ! isset($opt[$post->ID]) ) {
           $opt[$post->ID] = 0;
        }
        $opt[$post->ID]++;
        update_option(self::OPT, $opt);
      }
    
    
      /**
       * Get markup from cache or rebuild it.
       * In latter case setup an action on shutdown to defer cache of the markup.
       * @return string
       */
      public static function getMarkup()
      {
        $key = self::OPT . date(\'Yz\'); // change everyday
        $cached = get_transient($key);
        if ( ! empty($cached))
            return $cached; // if cache is available just output it
    
        $instance = new static;
        $markup = $instance->buildMarkup();
        if (empty($markup))
            return \'\'; // return without cache empty results
    
        add_action(\'shutdown\', function() use($markup,$key) {
          set_transient($key, $markup, HOUR_IN_SECONDS);
        });
    
        return $markup;
      }
    
    
      /**
       * Get popular posts and return proper markup
       * @return string
       */
      public function buildMarkup()
      {
        $opt = get_option(self::OPT);
        if(empty($opt))
            return; // nothing to get and show
    
        $posts = $this->getPosts($opt); // obtain posts
        $out = \'\';
    
        $format = \'<li><a href="%s">%s</a><span>(%d %s)</span></li>\';
    
        foreach($posts as $post) { 
          $title = apply_filters(\'the_title\', $post->post_title);
          $plink = get_permalink($post);
          $out .= sprintf($format, $plink, $title, $opt[$post->ID], __(\'views\', \'txdmn\'));
        }
    
        return \'<ul class="popular_posts">\' . $out . \'</ul>\';
      }
    
    
      /**
       * Return true if the posts is not older than X days, where X is filterable
       * @return boolean
       */
      private function shouldSave( WP_Post $post )
      {
        $max_old = apply_filters( \'myplugin_popular_posts_max_days\', 31 );
        $ptime = DateTime::createFromFormat(\'Y-m-d H:i:s\', $post->post_date);
        $now = new DateTime(\'now\');
    
        return (int) $now->diff($ptime)->days <= (int) $max_old;
      }
    
    
      /**
       * Return X popular posts, where X number is filterable
       * @return array
       */
      private function getPosts($opt)
      {
        arsort($opt); // reverse order: more to less popular
        $num = apply_filters(\'myplugin_popular_posts_num\', 5);
        $ids = array_keys(array_slice($opt, 0, $num));
    
        return (array) get_posts(array(\'post__in\' => $ids));
      }
    
    }
    
    用法update posts views 计数器:

    add_action(\'shutdown\', function() {
      if (is_single()) { // maybe check for post type using is_singular()
        $popularposts = new PopularPosts;
        $popularposts->save(get_queried_object());
      }     
    });
    
    和至show markup 在模板中:

    <?= PopularPosts::getMarkup() ?>
    
    计数器选项的问题和可能的改进should be reset evey day, 这里没有提供这方面的代码,但应该很容易实现。

    使用lib-likeWP-TLC-Transient 您可以改进getMarkup 方法使用软过期和后台更新。类似这样:

      public static function getMarkup()
      {
        $key = self::OPT . date(\'Yz\'); // change everyday
    
        return tlc_transient( $key )
          ->updates_with(array(new static, \'buildMarkup\'))
          ->expires_in(HOUR_IN_SECONDS)
          ->get();
      }
    
    请注意,我不熟悉Jetpack,所以我不知道如何从中获取post统计数据。为了方便起见,我用了一个钩子\'shutdown\' 只需增加选项中的计数器。这并不理想,因为即使用户只是刷新页面,计数器也会以这种方式递增。。。当然你可以改进它。

    请注意,代码为completely untested.

    结束

    相关推荐

    tax_query showing no results

    我正在创建一个音乐数据库网站,其中包含两种自定义帖子类型:曲目和专辑。我已经将这些曲目链接到各自的专辑,并为专辑的slug定制了分类法。在每个相册页面上,我都试图通过检索所有曲目来获取相册的曲目列表dub_album_slug 与当前相册的slug匹配的分类法。以下是我的查询代码:global $post; $post_slug = $post->post_name; $args = array ( \'post_type\' => \'dub_track\',