You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Drupal Cache API缓存User对象的有效性问询

Drupal Cache API 缓存用户对象的疑问

我正在学习Drupal Cache API,有一个关于在数据库(即cache_default MySQL表)中缓存用户(或一般对象)的问题。

请参考以下用于获取User对象的简单函数(我知道这类代码应放在自定义服务中,此处用函数仅为清晰展示):

<?php 

/** 
 * Get a user object
 * @param Integer
 * @return User 
 */
function get_user_data($uid)
{
    if ($uid) {
        $cache_id = 'my_user:' . $uid;
        $user = NULL;
        if ($cache = \Drupal::cache()->get($cache_id)) {
            // Read user object from the default cache.
            $user = $cache->data; 
        }
        else {
            // user not found in the cache.
            $user = \Drupal\user\Entity\User::load($uid);

            // Cache tags from User object, to tell Drupal to invalidate the cache
            // data after any change to the user.
            $user_cache_tags = $user->getCacheTags();

            // Store a serialized user object in the default cache.
            \Drupal::cache()->set($cache_id, $user, Cache::PERMANENT, $user_cache_tags);
        }
        return $user; 
    }

    return FALSE;
}

我的目标是缓存一个依赖于多个Profile(使用Profiles模块)中大量数据的Drupal User对象。

我的场景中User可能需要更多属性,或与Profile对象交互的方式,因此可能需要扩展User(如“MyUser”类等),但对象设计不在本次问题范围内。

核心问题

上述代码是否有实际作用?(或者Drupal已在某处缓存User对象,该代码毫无意义?)

场景假设

  • 无法使用Redis或Memcached。
  • 每次获取用户数据时,Drupal应用必须执行大量繁琐的数据库查询(读取用户表、Profile表)。

回答

你的代码有实际作用,但需要结合场景做针对性调整,具体分析如下:

  1. Drupal原生实体缓存的局限性
    Drupal确实会自动缓存User实体,但原生缓存仅覆盖用户核心表(如users_field_data)的基础数据。当你需要关联多个Profile对象的大量数据时,原生缓存不会自动包含这些关联内容——每次调用User::load($uid)后,读取关联Profile数据仍会触发额外的数据库查询,这正是你要避免的“繁琐查询”场景。

  2. 你的代码的核心价值

  • 它可以把**包含关联Profile数据的完整用户对象(或自定义扩展后的MyUser对象)**一次性缓存,避免重复执行用户表+多个Profile表的查询操作,直接从cache_default读取序列化后的完整对象,有效降低数据库负载。
  • 你正确使用了$user->getCacheTags(),这意味着当用户实体本身被修改时,Drupal会自动失效对应的缓存条目,保证数据一致性。
  1. 需要优化的关键点
  • 如果缓存对象包含Profile数据,仅依赖User的缓存标签不够——当关联的Profile对象被修改时,你的缓存不会自动失效。需要将Profile的缓存标签也加入缓存条目:
    // 假设通过字段关联获取用户的Profile对象
    $profile_cache_tags = [];
    foreach ($user->get('field_profile')->referencedEntities() as $profile) {
      $profile_cache_tags = array_merge($profile_cache_tags, $profile->getCacheTags());
    }
    $combined_tags = array_merge($user_cache_tags, $profile_cache_tags);
    \Drupal::cache()->set($cache_id, $user, Cache::PERMANENT, $combined_tags);
    
  • 遵循Drupal最佳实践,避免直接使用\Drupal::cache(),建议通过依赖注入获取cache.default服务(你提到知道要放在自定义服务中,这点没问题)。
  • 如果缓存自定义扩展的MyUser对象,要确保该对象可安全序列化(无无法序列化的资源,如数据库连接句柄)。

内容的提问来源于stack exchange,提问作者jtarleton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 04:36:26