扩展WP_USER类并在整个生命周期中使用此子类

时间:2015-04-28 作者:Daniel

我正在努力实现以下目标:对于我们网站上的每个用户,我想对服务(与另一个数据库交互的本地REST API)执行一次API请求,然后将结果缓存在WP\\u User(sub)类中,直到用户将注销并再次登录(因为此值在应用程序的每个页面上都使用一次,否则每次页面加载都必须检索一次,这在性能方面是非常不理想的)。

迄今为止,在分离关注点方面,我发现最优雅的方法是根据Brian Messenlehner和;杰森·科尔曼。

示例代码如下所示:see this file on the author\'s GitHub.

然而,问题是,我们的代码中仍然没有这个学生(扩展WP\\u用户,所以子类),我们仍然需要通过以下方式实例化它,为当前用户获取一个学生实例:

$student = new Student($current_user->ID);
如果我们在页面上这样做,实例将始终再次创建(因此我在标题中提到了生命周期),并调用$student->assignments 似乎永远不会缓存在WP_User 导航到新页面和/或重新加载页面后,将其自身子类化,因此对于每一次页面加载,我们都会使用API和数据库,这在高流量的生产环境中可能永远不会执行。

这个$current_user 但是WordPress本身中的全局变量(它是WP_User 实例)似乎是在登录后直接创建的,据我所知,它可以在整个应用程序中使用。我真正想要的是,在整个应用程序中都具有相同的可用性,但对于我的子类(Student),而不是WP_User 类,但更重要的是,我想确保对于每个登录的用户,API命中只执行一次(就像$current_user->user_login 哪个在WP_User 例如)。

我还研究了添加user_metaWP_User, 并查看了与此相关的问题,该问题似乎有部分帮助:Does WordPress cache get_user_meta() results?

但是,这是通过wp_cache_get 这是WordPress对象缓存,它明确指出:

非持久缓存仅在加载当前页面期间可用;加载下一页后,它将再次为空在创建页面时,我们不会多次使用Student子类中的值,但是,该值在应用程序的每个页面上都会使用一次,因此每次页面加载都必须检索一次。

我只是在错误的方向上思考,还是在WordPress中这怎么可能?我真的需要一个良好的长期解决方案,应该在高流量的生产环境中执行。提前感谢所有的输入和帮助!

3 个回复
SO网友:JBoulhous

如果我确实理解得很好,我们需要缓存从另一个REST服务检索到的值,从用户在wordpress安装上的登录到注销,因此我们将连接到此wp_login 获取值并使用缓存Transient API, Options API 或apersistent caching 插件。

add_action(\'wp_login\', \'my_get_and_cache_rest_value\');
function my_get_and_cache_rest_value ($user_login, $user) {
    // do your rest call
    // cache it using Transient API, Options API or a persistent caching plugin
}
然后我们可以扩展WP_User 对象并设置我们的魔术调用,以从缓存中获取所需的数据。

class MY_User extends WP_User {
    // no constructor so WP_User\'s constructor is used

    // method to get cached data
    function getMyCachedData() {
        // get data via my cache solution
        if ( ! isset( $this->data->myData ) )
            $this->data->myData = my_get_cached_data( $this->ID );

        return $this->data->myData;
    }

    // magic method to detect $user->my_data
    function __get( $key ) {
        if ( $key == \'my_data\' )
        {
            return $this->getMyCachedData();
        }
        else
        {
            // fallback to default WP_User magic method
            return parent::__get( $key );
        }
    }    
}
我希望这能帮助别人,为“丹尼尔”干杯。

SO网友:cjbj

你的问题有点宽泛,但主要的问题似乎是,对于每一个想接触外部API的新生来说,只有一次。

要做到这一点,你必须wp_insert_user, 这是注册新用户的核心功能。根据定义,此函数对于每个新用户只调用一次。在这个函数的末尾,您会看到一个钩子user_register, 这是您可以接近API的地方。

add_action (\'user_register\',\'wpse185731_approach_api\');
function wpse185731_approach_api ($user_id) {
  $userdata = get_userdata( $user_id );
  if ( some condition based on $userdata) {
    ... approach API with $userdata, then store with:
    add_user_meta( $user_id, $meta_key, $meta_value, $unique );
    }
  }
您可能希望在插件中执行此操作,而不是在主题中。

SO网友:Matthew Clark

下面的内容并不能回答整个问题,但它确实解决了这一部分:

@丹尼尔:这个$current_user 全局变量。。。据我所知,在整个应用程序中都可以使用。我真正想要的是在整个应用程序中保持相同的可用性。。。

我也有类似的需求,这就是我想到的。

有一个set_current_user 挂钩(在wp_set_current_user() 函数),并且因为$current_user 全局变量被设置为WP\\u User的一个实例,在触发操作时,您可以使用此挂钩对其“执行操作”。

调用到wp_get_current_user() 基本上返回全局$current_user, 但最终可能会打电话wp_set_current_user() 在某些情况下,这将导致您的自定义操作触发。

因此,在自定义插件中(我认为这在theme function.php文件中不起作用),您可以定义一个动作:

add_action( \'set_current_user\', \'extend_current_user\', PHP_INT_MAX );
然后您的操作可以覆盖全局$current_user:

public function extend_current_user()
{
    global $current_user;

    if( $current_user->ID == 0 )
        return;

    $current_user = new Student( $current_user->ID );
}
然后,您的学生班级可以实现Transient API 缓存RESTful数据并提供将公开该数据的方法或属性。因为全球$current_user 将作为Student的实例保留,这些方法/属性将始终可从wp_get_current_user() 任何时候你需要它们。

当然,通过这样做defensive programmer 将要验证对wp_get_current_user() 在调用任何方法之前,返回Student的实例。

结束

相关推荐

Cache Get_posts

我有一个查询(见下文),它提供了一个由10个新闻项组成的列表,这些新闻项按元值“event\\u date”排序,并经过筛选,以便只显示比今天更早的帖子。处理此查询需要两秒钟,因此我正在寻找一种简单的方法来缓存结果,以加快加载时间。我已经使用了WPEngine,所以我不需要任何缓存插件。提前感谢您的帮助。<?php $today = time();?> <?php $args = array( \'numberposts\' => 10, \'orderb