背景
臭名昭著的;
Headers already sent"E;如果在服务器响应的HTTP头已经发送到浏览器之后,有人试图修改服务器响应的HTTP头,那么这个错误就很可怕了,也就是说,服务器应该只生成响应的主体。
这通常以以下两种方式之一发生:
在WordPress完成头文件的编写之前,代码过早地打印内容-这会将HTTP响应推送到浏览器,并强制在过程中调度HTTP头文件。WordPress或第三方代码通常会正确修改标题的任何尝试都会随后产生错误wp_safe_redirect() 函数通过设置300
-范围HTTP状态标头。由于的回调函数参数add_menu_page()
和add_submenu_page()
用于在已生成仪表板侧栏和浮动工具栏后打印自定义标记,但在WordPress执行回调时太晚,无法使用wp_safe_redirect()
作用如评论中所述,解决方案是移动$wpdb->update()
和wp_safe_redirect()
在您的views/edit.php
查看模板和;挂钩“;将它们转换为在发送HTTP标头之前(在将任何HTML发送到浏览器之前)发生的操作。
解决问题the action reference for the typical admin-page request, 有理由假设\'send_headers\'
action是可以可靠修改HTTP头的最新版本。因此,可以通过将一个函数附加到该操作或之前包含重定向逻辑的函数来实现所需的结果,但您需要手动检查显示的管理页面,以确保只处理$wpdb->update()
以及随后的重定向views/edit.php
样板
WordPress为这种上下文功能提供了一个快捷方式the \'load-{page hook}\'
action, 对于加载的每个管理页面,它都会动态触发。当您呼叫add_submenu_page()
将返回{page hook}
值,该值用于钩住要执行的操作当您的自定义模板加载时,可以按照以下格式推断页面钩子{parent page slug}_page_{child page slug}
. 从代码中获取值,然后,我们最终得到\'load-bv_before_afters_main_page_bv_before_afters_edit\'
操作,仅在加载views/edit.php
样板
最后一个问题是是否$wpdb->update()
给您的views/edit.php
用于确定是否显示错误消息的模板。这可以使用全局变量或自定义操作来完成,但是更好的解决方案是附加一个函数,将错误打印到\'admin_notices\'
正是由于这个原因而存在的操作。\'admin_notices\'
将在WordPress呈现自定义视图模板之前触发,确保错误消息最终出现在页面顶部。
Note
这个
$wpdb->update()
方法返回更新的行数或
false
如果遇到错误-这意味着成功的更新查询不能更改任何行并返回
0
, 你的
if()
条件将惰性地计算为
false
并显示错误消息。因此,如果您希望仅在调用实际失败时显示错误,则应比较
$wpdb->update()
\'s返回值
false
使用标识比较运算符
!==
.
实施结合以上所有内容,一个解决方案可能如下所示。在这里,为了便于参考,我使用了一个额外的数组来保存管理页面的页面段塞,以确保没有与打字错误相关的问题,并在必要时使段塞更容易更改。
的整个部分views/edit.php
您最初发布的文件现在将驻留在操作挂钩中,以及用于处理编辑表单的任何其他业务逻辑中。
Plugin File:
$bv_admin_page_slugs = [
\'main\' => \'bv_before_afters_main\',
\'edit\' => \'bv_before_afters_edit\',
\'add\' => \'bv_before_afters_add\'
];
add_action( \'admin_menu\', \'bv_register_admin_pages\' );
// Create page in WP Admin
function bv_register_admin_pages() {
add_menu_page(
\'Before & After Photos\',
\'Before & Afters\',
\'edit_posts\',
$bv_admin_page_slugs[\'main\'],
\'bv_before_afters_main\',
\'dashicons-format-gallery\',
58
);
add_submenu_page(
$bv_admin_page_slugs[\'main\'],
\'Add set\',
\'Add set\',
\'edit_posts\',
$bv_admin_page_slugs[\'add\'],
\'bv_before_afters_add\'
);
add_submenu_page(
$bv_admin_page_slugs[\'main\'],
\'Edit set\',
\'Edit set\',
\'edit_posts\',
$bv_admin_page_slugs[\'edit\'],
\'bv_before_afters_edit\'
);
}
// Process the update/redirect logic whenever the the custom edit page is visited
add_action(
\'load-\' . $bv_admin_page_slugs[\'main\'] . \'_page_\' . $bv_admin_page_slugs[\'edit\'],
\'bv_update_before_after\'
);
// Performs a redirect on a successful update, adds an error message otherwise
function bv_update_before_after() {
// Don\'t process an edit if one was not submitted
if( /* (An edit was NOT submitted) */ )
return;
$result = $wpdb->update( /* (Your Arguments) */ );
if( $result !== false ) {
wp_safe_redirect(\'/wp-admin/admin.php?page=\' . $bv_admin_page_slugs[\'main\'] . \'&updated=1\');
exit;
}
else {
// Tell WordPress to print the error when it usually prints errors
add_action(
\'admin_notices\',
function() {
echo \'<div class="notice notice-error is-dismissible"><p>Could not be updated!</p></div>\';
}
);
}
}
// Apply stylesheets
function bv_before_afters_styles(){
wp_enqueue_style( \'bv_before_after_styles\', plugins_url( \'/bv_before_afters.css\', __FILE__ ) );
}
add_action(\'admin_print_styles\', \'bv_before_afters_styles\');
// Display the main page
function bv_before_afters_main(){
include_once plugin_dir_path( __FILE__ ).\'/views/view_all.php\';
}
// Display the edit page
function bv_before_afters_edit(){
include_once plugin_dir_path( __FILE__ ).\'/views/edit.php\';
}
// Display the add page
function bv_before_afters_add(){
include_once plugin_dir_path( __FILE__ ).\'/views/add.php\';
}