【问题标题】:how to force drupal function to not use DB cache?如何强制drupal函数不使用数据库缓存?
【发布时间】:2010-12-28 15:35:05
【问题描述】:

我有一个模块,我正在使用 node_load(array('nid' => arg(1))); 现在的问题是这个函数不断从数据库缓存中获取 node_load 的数据。
如何强制此函数不使用数据库缓存?
示例
我的链接是http://mydomain.com/node/344983
现在:
$node=node_load(array('nid'=>arg(1)),null,true);
回声 $node->nid 。 " -- " arg(1);
输出
435632 -- 435632
这是一个随机的节点 ID(在系统上可用)
每次我 ctrl+F5 我的浏览器我都会得到新的nid!

感谢您的帮助

【问题讨论】:

  • 如果这是在一个模块中,请发布您的 _menu 钩子
  • 函数 custom_node_menu(){ $items = array(); $items['node'] = array ('title' => 'node', 'page callback' => 'drupal_not_found', 'access callback' => TRUE, 'type' => MENU_CALLBACK, );返回$项目; }
  • node_load(arg(1)) 是否显示类似问题? print arg(1) 输出什么?您是否有可能为匿名用户启用了缓存,而您只是看到页面的早期输出?
  • 上面写的是 (435632),,, 问题是 arg(1) 得到不正确的值... node_load 使用 $reset=true 时没有任何问题 但问题是使用 arg api 本身!!!我不知道为什么它的值不正确!!
  • 我非常怀疑问题出在arg() 本身,否则 Drupal 将完全停止运行。请参阅我关于缓存的编辑 - 尝试使用 devel.module 清除缓存。

标签: database drupal caching


【解决方案1】:

你在哪里称呼它?例如,您是否将其用作 template.php 文件的一部分、页面的一部分或外部模块?

除非您将其包装在具有自己命名空间的函数中,否则请尝试以不同于$node 的方式命名该变量——例如,将其命名为$my_node。根据上下文,“节点”名称很可能被 Drupal 核心和其他模块访问和修改。

如果这发生在函数内部,请尝试以下操作并告诉我输出是什么:

$test_node_1 = node_load(344983); // Any hard-coded $nid that actually exists
echo $test_node_1->nid;

$test_node_2 = node_load(arg(1)); // Consider using hook_menu loaders instead of arg() in the future, but that's another discussion
echo $test_node_2->nid;

$test_node_3 = menu_get_object(); // Another method that is better than arg()
echo $test_node_3->nid;

编辑:

由于您使用的是 hook_block,我想我看到了您的问题 - 块本身正在被缓存,而不是节点。

根据http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_block/6 的文档,尝试在 hook_block 中设置BLOCK_NO_CACHEBLOCK_CACHE_PER_PAGE

您还应该尽可能避免使用 arg() —— 这会带来一点安全风险,并且有更好的方法可以完成 arg() 在模块环境中所做的任何事情。

编辑:*

显示我所指内容的一些示例代码:

function foo_block ($op = 'list', $delta = 0, $edit = array()) {
    switch ($op) {
      case 'list':
        $blocks[0] = array(
          'info' => 'I am a block!',
          'status' => 1,
          'cache' => BLOCK_NO_CACHE // Add this line
        );
        return $block;
      case 'view':
       .....
    }
}

【讨论】:

  • 看来我的问题出在 arg 本身
  • 它在钩子块中。如果我通过运行以下 mysql 查询从数据库中清除缓存,结果将变为正确:从 cache_content 中删除;从 cache_block 中删除; ....它为我浏览的第一页提供了正确的结果,然后它继续为下一页提供相同的 nid
  • 我不确定我是否得到了你......但即使我使用两种不同的浏览器......我也得到了我在清除缓存后浏览的第一个节点的 nid......还有如果我以管理员身份登录,结果总是正确的!仅当我是匿名用户时才会发生此错误
  • 是的 - 绝对是块缓存。尝试使用我上面提供的示例代码编辑您的 hook_block 实现——这将禁用该块上的缓存
  • 除了设置 BLOCK_NO_CACHE 之外,您还需要做一个额外的问题,即运行此查询 update blocks set cache=-1 where module='YourModuleName';这是必须的,如果你没有运行它,BLOCK_NO_CACHE 将不会像你期望的那样工作;)
【解决方案2】:

node_load 使用db_query,后者使用mysql_query——因此无法通过该函数轻松更改数据库的缓存。

但是,node_load 确实使用了 Drupal 的 static $nodes 缓存——这可能是您的问题,而不是数据库的缓存。您可以通过使用$reset = TRUE (node_load($nid, NULL, TRUE) 调用node_load 来让node_load 清除该缓存。

完整的文档在 node_load 手册页http://api.drupal.org/api/drupal/modules--node--node.module/function/node_load/6

【讨论】:

  • 我已经尝试将 $reset 设置为 True... 但这不起作用:(
  • Hrm ...你能描述一下你看到的具体行为吗? node_load 可能从许多不同的表中提取...您可以编辑您的响应以提供一些示例代码以及您希望看到的示例吗?
  • 我在下面添加了另一个答案——我相信缓存不是您问题的一部分。
【解决方案3】:

我很幸运地将节点 ID 传递给 node_load,而不是在数组中。

node_load(1);

根据Druapl's api,这是可以接受的,看起来如果您将数组作为第一个变量传入,它会作为条件数组加载,以便在数据库查询中匹配。

【讨论】:

  • 我的回答的主要部分是关于如何将第一个变量作为变量而不是数组传递,这是正确的。我不知道为什么我被否决了。
  • 我不知道谁投了你的票!!我真的很感谢你的帮助。然而,我投票赞成你妥协它:D ;) 最好的问候 Alaa
【解决方案4】:

问题不在于arg(),您的问题是您为匿名用户启用了缓存。

您可以关闭缓存,也可以使用 cache exclude module 从缓存中排除模块的菜单项。

编辑:正如您现在解释的那样,这是一个块,您可以在 hook_block 中使用 BLOCK_NO_CACHE 将您的块从块缓存中排除。

【讨论】:

  • 非常感谢您的帮助,但是这个模块是为了排除页面......这里这是一个出现在所有超过 10K 页的页面上的块。那么我怎样才能从缓存中排除这个块(或显示这个块的模块)。非常感谢您的帮助
  • 这是在一个块中是非常相关的信息,在问题本身中会很高兴。 @Andrew Sledge 要求您提供 hook_menu 代码是有原因的...答案已更新。
猜你喜欢
  • 2019-06-03
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 2017-10-03
  • 2011-08-09
  • 1970-01-01
相关资源
最近更新 更多