我正在努力实现以下目标:对于我们网站上的每个用户,我想对服务(与另一个数据库交互的本地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_meta
到WP_User
, 并查看了与此相关的问题,该问题似乎有部分帮助:Does WordPress cache get_user_meta() results?
但是,这是通过wp_cache_get
这是WordPress对象缓存,它明确指出:
非持久缓存仅在加载当前页面期间可用;加载下一页后,它将再次为空存储大小受服务器上PHP可用内存总量的限制。不要存储大型数据集,否则可能会出现“内存不足”消息只有在创建页面时多次重复的操作才有意义使用这种类型的缓存在创建页面时,我们不会多次使用Student子类中的值,但是,该值在应用程序的每个页面上都会使用一次,因此每次页面加载都必须检索一次。
我只是在错误的方向上思考,还是在WordPress中这怎么可能?我真的需要一个良好的长期解决方案,应该在高流量的生产环境中执行。提前感谢所有的输入和帮助!
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的实例。