我在中设置了错误处理机制one of my plugins 向管理区域添加通知和错误,就像核心一样。它在大多数情况下都能正常工作,但在某些情况下(如保存自定义帖子类型)却不能正常工作。我猜重定向是在幕后发生的,消息是在重定向发生之前打印的,因此它们似乎永远不会出现。
所以,我猜这就是发生的事情
用户编辑自定义帖子类型并点击Publish(发布)调用My post\\u updated(我的帖子更新)回调,该回调验证并保存自定义字段。回调添加错误消息。Wordpress重定向到某个页面以进行某些处理。调用My admin\\u notices(我的管理员通知)回调,它会打印并清除消息,Wordpress会重定向回帖子,再次调用我的admin\\u通知回调,但没有要打印的消息,因为它们是在步骤5中打印的,在正常情况下,步骤4和5不会发生,所以一切正常,但我想Wordpress保存帖子时会引入额外的重定向。我能做些什么来确保这一切都正常吗?我想我可能可以检查printMessages()中的某些内容,如果是在步骤4,则可以立即返回,但我不确定是什么。
这两个问题可能会对问题有所帮助,但不能完全给出解决方案:Add validation and error handling when saving custom fields?, How to display admin error notice if settings saved succesfully?.
代码如下:
/**
* Constructor
* @author Ian Dunn <[email protected]>
*/
public function __construct()
{
// Initialize variables
$defaultOptions = array( \'updates\' => array(), \'errors\' => array() );
$this->options = array_merge( get_option( self::PREFIX . \'options\', array() ), $defaultOptions );
$this->updatedOptions = false;
$this->userMessageCount = array( \'updates\' => 0, \'errors\' => 0 );
// more
add_action( \'admin_notices\', array($this, \'printMessages\') );
add_action( \'post_updated\', array($this, \'saveCustomFields\') );
// does other stuff
}
/**
* Saves values of the the custom post type\'s extra fields
* @author Ian Dunn <[email protected]>
*/
public function saveCustomFields()
{
// does stuff
if( true ) // if there was an error
$this->enqueueMessage( \'foo\', \'error\' );
}
/**
* Displays updates and errors
* @author Ian Dunn <[email protected]>
*/
public function printMessages()
{
foreach( array(\'updates\', \'errors\') as $type )
{
if( $this->options[$type] && ( self::DEBUG_MODE || $this->userMessageCount[$type] ) )
{
echo \'<div id="message" class="\'. ( $type == \'updates\' ? \'updated\' : \'error\' ) .\'">\';
foreach($this->options[$type] as $message)
if( $message[\'mode\'] == \'user\' || self::DEBUG_MODE )
echo \'<p>\'. $message[\'message\'] .\'</p>\';
echo \'</div>\';
$this->options[$type] = array();
$this->updatedOptions = true;
$this->userMessageCount[$type] = 0;
}
}
}
/**
* Queues up a message to be displayed to the user
* @author Ian Dunn <[email protected]>
* @param string $message The text to show the user
* @param string $type \'update\' for a success or notification message, or \'error\' for an error message
* @param string $mode \'user\' if it\'s intended for the user, or \'debug\' if it\'s intended for the developer
*/
protected function enqueueMessage($message, $type = \'update\', $mode = \'user\')
{
array_push($this->options[$type .\'s\'], array(
\'message\' => $message,
\'type\' => $type,
\'mode\' => $mode
) );
if($mode == \'user\')
$this->userMessageCount[$type . \'s\']++;
$this->updatedOptions = true;
}
/**
* Destructor
* Writes options to the database
* @author Ian Dunn <[email protected]>
*/
public function __destruct()
{
if($this->updatedOptions)
update_option(self::PREFIX . \'options\', $this->options);
}
罢工
Update: 已将更新的代码和接受的答案提交给core。插件中的php
trunk 以防有人想看到完整的工作副本。下一个
stable release 那就是1.2罢工>
Update 2: 我已将此功能抽象为a self-contained library 您可以将其包含在插件中。Core正在讨论在#11515.
最合适的回答,由SO网友:Hameedullah Khan 整理而成
我在下面的代码中也指出了一些事情:
您正在覆盖从中读取的选项get_option
使用array_merge
您已对邮件计数进行了硬编码保存选项__destruct
只是不起作用。(我还没有任何线索,可能专家们会对此有所了解。我已经用HKFIX, 有一点描述:
/**
* Constructor
* @author Ian Dunn <[email protected]>
*/
public function __construct()
{
// Initialize variables
$defaultOptions = array( \'updates\' => array(), \'errors\' => array() );
/* HKFIX: array_merge was overwriting the values read from get_option,
* moved $defaultOptions as first argument to array_merge */
$this->options = array_merge( $defaultOptions, get_option( self::PREFIX . \'options\', array() ) );
$this->updatedOptions = false;
/* HKFIX: the count for update and error messages was hardcoded,
* which was ignoring the messages already in the options table read above
* later in print the MessageCounts is used in loop
* So I updated to set the count based on the options read from get_option */
$this->userMessageCount = array();
foreach ( $this->options as $msg_type => $msgs ) {
$this->userMessageCount[$msg_type] = count( $msgs );
}
// more
add_action( \'admin_notices\', array($this, \'printMessages\') );
add_action( \'post_updated\', array($this, \'saveCustomFields\') );
// does other stuff
}
/**
* Saves values of the the custom post type\'s extra fields
* @author Ian Dunn <[email protected]>
*/
public function saveCustomFields()
{
// does stuff
/* HKFIX: this was false, so changed it to true, may be not a fix but thought I should mention ;) */
if( true )
$this->enqueueMessage( \'foo\', \'error\' );
}
/**
* Displays updates and errors
* @author Ian Dunn <[email protected]>
*/
public function printMessages()
{
foreach( array(\'updates\', \'errors\') as $type )
{
if( $this->options[$type] && ( self::DEBUG_MODE || $this->userMessageCount[$type] ) )
{
echo \'<div id="message" class="\'. ( $type == \'updates\' ? \'updated\' : \'error\' ) .\'">\';
foreach($this->options[$type] as $message)
if( $message[\'mode\'] == \'user\' || self::DEBUG_MODE )
echo \'<p>\'. $message[\'message\'] .\'</p>\';
echo \'</div>\';
$this->options[$type] = array();
$this->updatedOptions = true;
$this->userMessageCount[$type] = 0;
}
}
/* HKFIX: Save the messages, can\'t wait for destruct */
if ( $this->updatedOptions ) {
$this->saveMessages();
}
}
/**
* Queues up a message to be displayed to the user
* @author Ian Dunn <[email protected]>
* @param string $message The text to show the user
* @param string $type \'update\' for a success or notification message, or \'error\' for an error message
* @param string $mode \'user\' if it\'s intended for the user, or \'debug\' if it\'s intended for the developer
*/
protected function enqueueMessage($message, $type = \'update\', $mode = \'user\')
{
array_push($this->options[$type .\'s\'], array(
\'message\' => $message,
\'type\' => $type,
\'mode\' => $mode
) );
if($mode == \'user\')
$this->userMessageCount[$type . \'s\']++;
/* HKFIX: save the messages, can\'t wait for destruct */
$this->saveMessages();
}
/* HKFIX: Dedicated funciton to save messages
* Can also be called from destruct if that is really required */
public function saveMessages()
{
update_option(self::PREFIX . \'options\', $this->options);
}
/**
* Destructor
* Writes options to the database
* @author Ian Dunn <[email protected]>
*/
public function __destruct()
{
/* HKFIX: Can\'t rely on saving options in destruct, this just does not work */
// its very late to call update_options in destruct
//update_option(self::PREFIX . \'options\', $this->options);
}
SO网友:kaiser
我目前不知道你的插件是怎么回事,所以我给你指出两件事:
wp_parse_args()
是将默认值与其他参数合并的好方法。
private $defaults;
function wpse20130_parse_us( $args );
{
$new_args = wp_parse_args( $this->defaults, $args );
return $new_args;
}
这个插件更接近core处理错误的方式(直接从我脑海中浮现——可能包含错误本身):
EDIT: Test Plugin
<?php
/**
Plugin Name: WPSE Show Error on post
Plugin URI: https://github.com/franz-josef-kaiser/
Description: Example for the useage of the WP Error class in a plugin
Author: Franz Josef Kaiser
Author URI: https://github.com/franz-josef-kaiser
Version: 0.1
License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
// Secure: doesn\'t allow to load this file directly
if( ! class_exists(\'WP\') )
{
header( \'Status: 403 Forbidden\' );
header( \'HTTP/1.1 403 Forbidden\' );
exit;
}
if ( ! class_exists(\'wpse20130Error\') )
{
class wpse20130Error
{
private $args = array();
private $error_msg;
const TEXTDOMAIN = \'textdomain\';
function __construct()
{
$this->wpse20130_input( $this->args );
add_action( \'admin_notices\', array($this, \'wpse20130_trigger_error\') );
}
function wpse20130_input( $args )
{
if ( ! isset( $args[\'some_important_value\'] ) )
$this->error_msg = sprintf(
__(
\'You have to specify the some_important_value inside the %2$s function.\'.\'<br />\'.
\'Error triggered inside: file name %1$s (line number %3$s)\'
,self::TEXTDOMAIN
)
,__FILE__
,__FUNCTION__
,__LINE__
);
}
function wpse20130_trigger_error()
{
// Trigger Errors if we got some
if ( isset( $this->error_msg ) )
{
$error = new WP_Error( \'input_data\', $this->error_msg );
if ( is_wp_error( $error ) )
{
$output =
\'<div id="error-\'.$error->get_error_code().\'" class="error error-notice">\'.
$error->get_error_message().
\'</div>\';
// die & print error message
echo $output;
}
}
}
} // END Class wpse20130Error
new wpse20130Error();
} // endif;
?>
试试看。:)