重定向期间忽略自定义ADMIN_NOTICES消息

时间:2011-06-16 作者:Ian Dunn

我在中设置了错误处理机制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。插件中的phptrunk 以防有人想看到完整的工作副本。下一个stable release 那就是1.2

Update 2: 我已将此功能抽象为a self-contained library 您可以将其包含在插件中。Core正在讨论在#11515.

2 个回复
最合适的回答,由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;
?>
试试看。:)

结束

相关推荐

Add new post redirection

我不知道我的网站出了什么问题,这是第二个重定向问题,每当我添加一篇新文章,在添加标题后,当我尝试添加内容时,我自己的网站主页会出现在内容框旁边的一个红色边框框中,一个页面试图加载,这个页面一直在加载,没有任何内容,加载页面的url是“http://mywebsite.com/wp-admin/post-new.php“”