我创建了一个自定义模块,可以根据各种自定义规则重定向用户.我的问题是找出放置代码的位置.现在,我有:
function mymodule_init() {
mymodule_redirect_now();
}
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,"mymodule_redirect_now"通常不会执行任何操作,但有时可能会导致"drupal_goto"被触发.这在实践中有效,但会导致其他问题:
哪个是最正确的放置这样的重定向逻辑的地方,以避免单元测试失败和cron作业失败?
UPDATE
我试图简化这个问题,把它归结为一个更简单的问题.基本上,我想知道如何阻止cron执行以下代码:
function mymodule_init() {
mymodule_redirect_now();
}
Run Code Online (Sandbox Code Playgroud)
Cron总是在init中执行任何操作,但在这种情况下,让我们假设重定向具有以下逻辑:
function mymodule_redirect_now()
{
if (!$currentPathIsUS && $ipIsUS) { // lets pretend for now this always happens...
drupal_goto("us");
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,如果使用具有US IP且当前路径不是US路径,则必须将它们重定向到/ us路径.
问题是,如果我从命令行或浏览器运行cron,它会在转到任何其他函数之前点击上面的代码,但由于"drupal_goto",它实际上并不执行cron代码.
hook_init()正如您所注意到的,它将始终在请求开始时运行。
当您说“\xe2\x80\xa6 根据各种自定义规则重定向用户”时。你是什么意思?用户在提交包含某些内容的表单时是否被重定向?如果访问一个(或一组)特定 URL,用户是否会被重定向?有什么条件呢?是规则模块吗?
\n根据您所指的自定义规则,会有不同的答案。例如,如果规则与节点有关(加载、查看、编辑、\xe2\x80\xa6),则必须使用hook_node_$op()where$op可以是“查看”、“加载”或“提交”。举个例子:
// Redirect user when submitting a node of type \'book\'\nfunction mymodule_node_submit($node, $form, &$form_state) {\n if ($node->type === \'book\') {\n drupal_goto("some/place/else");\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n在我看来,这里有两个问题在起作用。一是在代码中放置重定向逻辑的位置,在 Drupal 7(和 6)中并没有真正好的简短答案,这完全取决于上下文。它可以响应表单加载或表单提交或节点加载或查看或编辑(等)或许多其他条件。这些条件要求重定向逻辑位于代码中的不同位置。这就是我上面集中回答的内容。
\n第二个问题是不同类型的,在阅读您的澄清后似乎是罪魁祸首。Cron 和单元测试不会拥有普通网络浏览器访问者拥有的所有信息。
\n您必须检测cron 是否正在运行,并且在发生这种情况时不进行重定向。正如您在上面的链接中看到的,cron 创建一个临时(匿名)用户,并且不会保存任何会话数据。这有可能破坏许多 cron 运行。因为drupal_exit()或多或少会杀死一切。
至于单元测试drupal_goto(),我在这里不太确定,但我相信它会因为同样的原因而崩溃。您可以尝试模拟部分函数以实际上不重定向。
作为旁注,您可能需要考虑使用hook_url_inbound_alter()(更多信息)。它可能与您想要做的事情完全兼容,也可能不兼容。看看Redirect模块做了什么,特别是函数redirect_can_redirect()。