使用init钩子设置Cookie会导致“已发送标头”

时间:2019-01-06 作者:Rick Hellewell

根据这里和其他地方的研究,我有以下代码可以在站点上设置cookie:

add_action( \'init\', \'my_set_cookie\',1 );

function my_set_cookie() {
    if (! $_COOKIE[\'mycookie\']) {
       $guid = \'xxxx\'; // normally a real guid value so it will be unique
       setcookie(\'mycookie\', $guid, time()+(3600*24*30),\'/\');
    }
return;
}
但即使init 使用了hook,并且优先级为“1”,我仍然会收到“setcookie”语句的“headers ready sent”错误。使用另一个优先级(例如“99”)也会产生错误。

是否有其他挂钩用于设置cookie?

4 个回复
最合适的回答,由SO网友:Rick Hellewell 整理而成

在尝试各种挂钩以尝试在主题加载其标题之前设置cookie之后。php文件(没有一个钩子起作用,即使是在“加载周期”的早期),我想我可能会暂时禁用该错误,以便可以设置cookie。我的回答基于this question.

现在,我意识到这不是一种标准的做法,可能也不推荐这样做,但我的理由是,如果主题没有“正常”或“正确”地执行操作,因此导致“headers ready sent”(标题已发送)错误消息显示在屏幕上,然后快速绕过错误显示(然后恢复任何错误捕获设置),这是一个在我的情况下都可以使用的解决方案。

从我的测试中可以看出,即使发生了“headers ready sent”,cookie也设置正确。这听起来似乎不应该奏效,但在我的测试中似乎奏效了。

所以,我使用的技术是

获取当前错误设置以供以后使用

关闭错误显示

执行导致错误的操作(在我的情况下,设置cookie)

将错误设置恢复为原始值

以下是我使用的代码。再说一次,可能不是“犹太教”,但在我的情况下是有效的。

// some themes cause a \'headers already sent\' message, so we bypass it here
// by turning off that error message while we set the cookie.
// see https://stackoverflow.com/a/26154061/1466973
//  $random_guid is a guid set previously
$previousErrorLevel = error_reporting();
error_reporting(\\E_ERROR);
setcookie(\'cookie_name\', $random_guid,time()+(3600*24*30),\'/\');
error_reporting($previousErrorLevel);
由于它对我的情况有效,我将我的答案标记为正确,尽管另一个答案是有效的。我预计会有几票反对票,因为这不符合犹太教。但它解决了我的问题和环境。

SO网友:Krzysiek Dróżdż

这是一个和WP一样古老的问题,甚至更古老。。。

如果网站的任何内容已发送,则无法设置Cookie或发送任何其他标题。

您尝试使用init 钩而且在大多数情况下都可以,因为还不应该打印输出。但是并非所有代码都编写正确。

以前做过很多其他事情init. 看看actions run during a typical request.

正如你所看到的。。。主题在之前加载init 钩插件也是如此。

因此,如果他们的代码导致任何警告/通知(并且调试已启动),或者他们生成任何其他输出,那么您在设置cookie时将出现错误。

造成此问题的另一个常见原因是使用关闭PHP标记(?>) 在文件末尾。如果在结束标记之后有任何白色字符,那么它也被视为输出。

SO网友:nikelone

以下是关于此主题的另一篇帖子,其中包含一些解决此问题的建议:https://stackoverflow.com/questions/50205548/setcookie-not-working-wordpress-because-of-header

我使用了send\\u headers挂钩。但如果有人能详细说明一下,如果这真的是设置cookie的正确挂钩,那就太好了。

SO网友:Lars Flieger

您可以通过以下方式解决此问题checking if the header is already sent:

headers_sent()

function cc_set_cookie() {
    if(!headers_sent())
        setcookie(\'COOKIE_NAME\', \'COOKIE_VALUE\', time()+31556926, \'/\');
}
add_action(\'init\', \'cc_set_cookie\');

相关推荐

OOP development and hooks

我目前正在为Wordpress编写我的第一个OOP插件。为了帮助我找到一点结构,a boiler plate 这为我奠定了基础。在里面Main.php 有一种方法可以为管理员加载JS和CSS资产:/** * Register all of the hooks related to the admin area functionality * of the plugin. * * @since 0.1.0 * @access private