"त्रुटि: विकल्प पृष्ठ नहीं मिला" सेटिंग्स पृष्ठ पर एक ओओपी प्लगइन के लिए सबमिशन


19

मैं टॉम मैकफर्लिन के बॉयलरप्लेट का उपयोग करके एक प्लगइन विकसित कर रहा हूं एक टेम्पलेट के रूप में रिपॉजिटरी , जो ओओपी प्रथाओं का उपयोग करता है। मैं यह जानने की कोशिश कर रहा हूं कि मैं अपनी सेटिंग्स को सही ढंग से प्रस्तुत करने में असमर्थ क्यों हूं। मैंने एक्शन विशेषता को एक खाली स्ट्रिंग पर सेट करने की कोशिश की है, जैसा कि यहाँ एक और प्रश्न पर सुझाव दिया गया है, लेकिन इससे कोई मदद नहीं मिली है ...

नीचे सामान्य कोड सेटअप का उपयोग किया जा रहा है ...

फॉर्म (/ साक्षात्कार / आधार / एफपी):

<div class="wrap">
    <h2><?php echo esc_html( get_admin_page_title() ); ?></h2>
    <form action="options.php" method="post">
        <?php
        settings_fields( $this->plugin_slug );
        do_settings_sections( $this->plugin_slug );
        submit_button( 'Save Settings' );
        ?>
    </form>
</div>

निम्नलिखित कोड के लिए, add_settings_field () और add_settings_section () मौजूद हैं, 'विकल्प_सूची_सेलेक्शन' को छोड़कर सभी कॉलबैक मान लें।

प्लगइन व्यवस्थापक वर्ग (/ {plugin_name} -class-admin.php):

namespace wp_plugin_name;

class Plugin_Name_Admin
{
    /**
     * Note: Some portions of the class code and method functions are missing for brevity
     * Let me know if you need more information...
     */

    private function __construct()
    {
        $plugin              = Plugin_Name::get_instance();

        $this->plugin_slug   = $plugin->get_plugin_slug();
        $this->friendly_name = $plugin->get_name(); // Get "Human Friendly" presentable name

        // Adds all of the options for the administrative settings
        add_action( 'admin_init', array( $this, 'plugin_options_init' ) );

        // Add the options page and menu item
        add_action( 'admin_menu', array( $this, 'add_plugin_admin_menu' ) );


    }

    public function add_plugin_admin_menu()
    {

        // Add an Options Page
        $this->plugin_screen_hook_suffix =
        add_options_page(
            __( $this->friendly_name . " Options", $this->plugin_slug ),
            __( $this->friendly_name, $this->plugin_slug ),
            "manage_options", 
            $this->plugin_slug,
            array( $this, "display_plugin_admin_page" )
        );

    }

    public function display_plugin_admin_page()
    {
        include_once( 'views/admin.php' );
    }

    public function plugin_options_init()
    {
        // Update Settings
        add_settings_section(
            'maintenance',
            'Maintenance',
            array( $this, 'maintenance_section' ),
            $this->plugin_slug
        );

        // Check Updates Option
        register_setting( 
            'maintenance',
            'plugin-name_check_updates',
            'wp_plugin_name\validate_bool'
        );

        add_settings_field(
            'check_updates',
            'Should ' . $this->friendly_name . ' Check For Updates?',
            array( $this, 'check_updates_field' ),
            $this->plugin_slug,
            'maintenance'
        );

        // Update Period Option
        register_setting(
            'maintenance',
            'plugin-name_update_period',
            'wp_plugin_name\validate_int'
        );

        add_settings_field(
            'update_frequency',
            'How Often Should ' . $this->friendly_name . ' Check for Updates?',
            array( $this, 'update_frequency_field' ),
            $this->plugin_slug,
            'maintenance'
        );

        // Plugin Option Configurations
        add_settings_section(
            'category-option-list', 'Widget Options List',
            array( $this, 'option_list_section' ),
            $this->plugin_slug
        );
    }
}

कुछ आवश्यक अपडेट:

क्रिया की विशेषता बदलना:

<form action="../../options.php" method="post">

... बस एक 404 त्रुटि में परिणाम। नीचे दिए गए अपाचे लॉग्स का अंश है। ध्यान दें कि डिफ़ॉल्ट वर्डप्रेस स्क्रिप्ट और सीएसएस एन-क्यू हटा दिए जाते हैं:

# Changed to ../../options.php
127.0.0.1 - - [01/Apr/2014:15:59:43 -0400] "GET /wp-admin/options-general.php?page=pluginname-widget HTTP/1.1" 200 18525
127.0.0.1 - - [01/Apr/2014:15:59:43 -0400] "GET /wp-content/plugins/PluginName/admin/assets/css/admin.css?ver=0.1.1 HTTP/1.1" 304 -
127.0.0.1 - - [01/Apr/2014:15:59:43 -0400] "GET /wp-content/plugins/PluginName/admin/assets/js/admin.js?ver=0.1.1 HTTP/1.1" 304 -
127.0.0.1 - - [01/Apr/2014:15:59:52 -0400] "POST /options.php HTTP/1.1" 404 1305
127.0.0.1 - - [01/Apr/2014:16:00:32 -0400] "POST /options.php HTTP/1.1" 404 1305

#Changed to options.php
127.0.0.1 - - [01/Apr/2014:16:00:35 -0400] "GET /wp-admin/options-general.php?page=pluginname-widget HTTP/1.1" 200 18519
127.0.0.1 - - [01/Apr/2014:16:00:35 -0400] "GET /wp-content/plugins/PluginName/admin/assets/css/admin.css?ver=0.1.1 HTTP/1.1" 304 -
127.0.0.1 - - [01/Apr/2014:16:00:35 -0400] "GET /wp-content/plugins/PluginName/admin/assets/js/admin.js?ver=0.1.1 HTTP/1.1" 304 -
127.0.0.1 - - [01/Apr/2014:16:00:38 -0400] "POST /wp-admin/options.php HTTP/1.1" 500 2958

जब WP_DEBUG सत्य है, तो php-त्रुटियाँ.लॉग फ़ाइल और डीबग.लॉग फ़ाइल दोनों खाली हैं।

प्लगिन क्लास (/ ग्लासप्लागिन-name Ideal-class.php)

namespace wp_plugin_name;

class Plugin_Name
{
    const VERSION = '1.1.2';
    const TABLE_VERSION = 1;
    const CHECK_UPDATE_DEFAULT = 1;
    const UPDATE_PERIOD_DEFAULT = 604800;

    protected $plugin_slug = 'pluginname-widget';
    protected $friendly_name = 'PluginName Widget';

    protected static $instance = null;

    private function __construct()
    {

        // Load plugin text domain
        add_action( 'init',
                    array(
            $this,
            'load_plugin_textdomain' ) );

        // Activate plugin when new blog is added
        add_action( 'wpmu_new_blog',
                    array(
            $this,
            'activate_new_site' ) );

        // Load public-facing style sheet and JavaScript.
        add_action( 'wp_enqueue_scripts',
                    array(
            $this,
            'enqueue_styles' ) );
        add_action( 'wp_enqueue_scripts',
                    array(
            $this,
            'enqueue_scripts' ) );

        /* Define custom functionality.
         * Refer To http://codex.wordpress.org/Plugin_API#Hooks.2C_Actions_and_Filters
         */

    }

    public function get_plugin_slug()
    {
        return $this->plugin_slug;
    }

    public function get_name()
    {
        return $this->friendly_name;
    }

    public static function get_instance()
    {

        // If the single instance hasn't been set, set it now.
        if ( null == self::$instance )
        {
            self::$instance = new self;
        }

        return self::$instance;

    }

    /**
     * The member functions activate(), deactivate(), and update() are very similar.
     * See the Boilerplate plugin for more details...
     *
     */

    private static function single_activate()
    {
        if ( !current_user_can( 'activate_plugins' ) )
            return;

        $plugin_request = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';

        check_admin_referer( "activate-plugin_$plugin_request" );

        /**
         *  Test to see if this is a fresh installation
         */
        if ( get_option( 'plugin-name_version' ) === false )
        {
            // Get the time as a Unix Timestamp, and add one week
            $unix_time_utc = time() + Plugin_Name::UPDATE_PERIOD_DEFAULT;

            add_option( 'plugin-name_version', Plugin_Name::VERSION );
            add_option( 'plugin-name_check_updates',
                        Plugin_Name::CHECK_UPDATE_DEFAULT );
            add_option( 'plugin-name_update_frequency',
                        Plugin_Name::UPDATE_PERIOD_DEFAULT );
            add_option( 'plugin-name_next_check', $unix_time_utc );

            // Create options table
            table_update();

            // Let user know PluginName was installed successfully
            is_admin() && add_filter( 'gettext', 'finalization_message', 99, 3 );
        }
        else
        {
            // Let user know PluginName was activated successfully
            is_admin() && add_filter( 'gettext', 'activate_message', 99, 3 );
        }

    }

    private static function single_update()
    {
        if ( !current_user_can( 'activate_plugins' ) )
            return;

        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';

        check_admin_referer( "activate-plugin_{$plugin}" );

        $cache_plugin_version         = get_option( 'plugin-name_version' );
        $cache_table_version          = get_option( 'plugin-name_table_version' );
        $cache_deferred_admin_notices = get_option( 'plugin-name_admin_messages',
                                                    array() );

        /**
         * Find out what version of our plugin we're running and compare it to our
         * defined version here
         */
        if ( $cache_plugin_version > self::VERSION )
        {
            $cache_deferred_admin_notices[] = array(
                'error',
                "You seem to be attempting to revert to an older version of " . $this->get_name() . ". Reverting via the update feature is not supported."
            );
        }
        else if ( $cache_plugin_version === self::VERSION )
        {
            $cache_deferred_admin_notices[] = array(
                'updated',
                "You're already using the latest version of " . $this->get_name() . "!"
            );
            return;
        }

        /**
         * If we can't determine what version the table is at, update it...
         */
        if ( !is_int( $cache_table_version ) )
        {
            update_option( 'plugin-name_table_version', TABLE_VERSION );
            table_update();
        }

        /**
         * Otherwise, we'll just check if there's a needed update
         */
        else if ( $cache_table_version < TABLE_VERSION )
        {
            table_update();
        }

        /**
         * The table didn't need updating.
         * Note we cannot update any other options because we cannot assume they are still
         * the defaults for our plugin... ( unless we stored them in the db )
         */

    }

    private static function single_deactivate()
    {

        // Determine if the current user has the proper permissions
        if ( !current_user_can( 'activate_plugins' ) )
            return;

        // Is there any request data?
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';

        // Check if the nonce was valid
        check_admin_referer( "deactivate-plugin_{$plugin}" );

        // We'll, technically the plugin isn't included when deactivated so...
        // Do nothing

    }

    public function load_plugin_textdomain()
    {

        $domain = $this->plugin_slug;
        $locale = apply_filters( 'plugin_locale', get_locale(), $domain );

        load_textdomain( $domain,
                         trailingslashit( WP_LANG_DIR ) . $domain . '/' . $domain . '-' . $locale . '.mo' );
        load_plugin_textdomain( $domain, FALSE,
                                basename( plugin_dir_path( dirname( __FILE__ ) ) ) . '/languages/' );

    }

    public function activate_message( $translated_text, $untranslated_text,
                                      $domain )
    {
        $old = "Plugin <strong>activated</strong>.";
        $new = FRIENDLY_NAME . " was  <strong>successfully activated</strong> ";

        if ( $untranslated_text === $old )
            $translated_text = $new;

        return $translated_text;

    }

    public function finalization_message( $translated_text, $untranslated_text,
                                          $domain )
    {
        $old = "Plugin <strong>activated</strong>.";
        $new = "Captain, The Core is stable and PluginName was <strong>successfully installed</strong> and ready for Warp speed";

        if ( $untranslated_text === $old )
            $translated_text = $new;

        return $translated_text;

    }

}

संदर्भ:


इनाम विवरण रिपोर्ट करता है: "कृपया सर्वोत्तम प्रथाओं पर कुछ जानकारी प्रदान करें " । निजी कंस्ट्रक्टरों और उनके अंदर क्रियाओं का एक समूह के साथ एकल का उपयोग करना: खराब अभ्यास और कठिन परीक्षण, न कि आपकी गलती।
gmazzap

1
अपने कोड का परीक्षण करने के बाद ../../options.php का उपयोग करें।
रावी पटेल

क्या आप कृपया get_plugin_slug () दिखा सकते हैं।
vancoder

@vancoder मैंने प्रासंगिक जानकारी के साथ पोस्ट को ऊपर संपादित किया है ...
गेट_इंजीनियर

आपके register_settings में आपके स्वच्छता कॉलबैक में बैकस्लैश क्यों हैं? मुझे नहीं लगता कि यह काम करेगा।
ब्योर्न

जवाबों:


21

"त्रुटि: विकल्प पृष्ठ नहीं मिला" बग

यह WP सेटिंग्स एपीआई में एक ज्ञात मुद्दा है। वर्षों पहले खोला गया एक टिकट था, और इसे हल के रूप में चिह्नित किया गया था - लेकिन बग वर्डप्रेस के नवीनतम संस्करणों में बनी हुई है। यह (अब हटा दिया गया) कोडेक्स पृष्ठ ने इस बारे में क्या कहा :

"त्रुटि: विकल्प पृष्ठ नहीं मिला।" समस्या (एक समाधान और स्पष्टीकरण सहित):

तब समस्या यह है, कि 'वाइटेलिस्ट_ओप्शन्स' फ़िल्टर को आपके डेटा के लिए सही इंडेक्स नहीं मिला है। यह options.php # 98 (WP 3.4) पर लागू हो जाता है।

register_settings()अपना डेटा वैश्विक में जोड़ता है $new_whitelist_options। इसके बाद ((। ) कॉलबैक (ओं) के $whitelist_optionsअंदर वैश्विक के साथ विलय हो जाता है । वे कॉलबैक आपके डेटा को सूचकांक के साथ वैश्विक रूप से जोड़ते हैं । जब आपका सामना "त्रुटि: विकल्प पृष्ठ नहीं मिला।" इसका मतलब है कि आपके सूचकांक को मान्यता नहीं मिली है। भ्रामक बात यह है कि पहली दलील का उपयोग सूचकांक और नाम के रूप में किया जाता है , जब विकल्प में वास्तविक जांच होती है। एफपी # 112 के खिलाफ होता है , जो कि है , जिसे आप @ ग्रेट से मान के रूप में प्राप्त करते हैं ।option_update_filter()add_option_whitelist()$new_whitelist_options$option_group$options_group$options_page$hook_suffixadd_submenu_page()

संक्षेप में, एक आसान समाधान $option_groupमैच बनाना है $option_name। इस त्रुटि का एक अन्य कारण $pageपैरामीटर के लिए add_settings_section( $id, $title, $callback, $page )या तो कॉल करते समय अमान्य मान है add_settings_field( $id, $title, $callback, $page, $section, $args )

संकेत: फ़ंक्शन संदर्भ से जोड़ना $pageचाहिए $menu_slug/ थीम पृष्ठ जोड़ें।

सिंपल फिक्स

कस्टम पृष्ठ नाम (आपके मामले में:) का उपयोग करते हुए, $this->plugin_slugजैसा कि आपकी अनुभाग आईडी समस्या के आसपास हो जाएगा। हालाँकि, आपके सभी विकल्पों को एक ही खंड में समाहित करना होगा।

समाधान

अधिक मजबूत समाधान के लिए, अपनी Plugin_Name_Adminकक्षा में ये बदलाव करें :

निर्माता में जोड़ें:

// Tracks new sections for whitelist_custom_options_page()
$this->page_sections = array();
// Must run after wp's `option_update_filter()`, so priority > 10
add_action( 'whitelist_options', array( $this, 'whitelist_custom_options_page' ),11 );

इन विधियों को जोड़ें:

// White-lists options on custom pages.
// Workaround for second issue: http://j.mp/Pk3UCF
public function whitelist_custom_options_page( $whitelist_options ){
    // Custom options are mapped by section id; Re-map by page slug.
    foreach($this->page_sections as $page => $sections ){
        $whitelist_options[$page] = array();
        foreach( $sections as $section )
            if( !empty( $whitelist_options[$section] ) )
                foreach( $whitelist_options[$section] as $option )
                    $whitelist_options[$page][] = $option;
            }
    return $whitelist_options;
}

// Wrapper for wp's `add_settings_section()` that tracks custom sections
private function add_settings_section( $id, $title, $cb, $page ){
    add_settings_section( $id, $title, $cb, $page );
    if( $id != $page ){
        if( !isset($this->page_sections[$page]))
            $this->page_sections[$page] = array();
        $this->page_sections[$page][$id] = $id;
    }
}

और परिवर्तन add_settings_section()करने के लिए कॉल: $this->add_settings_section()


आपके कोड पर अन्य नोट

  • आपका फॉर्म कोड सही है। आपके फॉर्म में options.php को सबमिट करना है, जैसा कि @Chris_O द्वारा मुझे बताया गया है, और WP WP API दस्तावेज़ में संकेत दिया गया है ।
  • नेमस्पेसिंग के फायदे हैं, लेकिन यह इसे डिबग करने के लिए और अधिक जटिल बना सकता है, और आपके कोड की संगतता को कम कर सकता है (इसके लिए PHP> = 5.3, अन्य प्लगइन्स / थीम की आवश्यकता होती है जो ऑटोलराइज़र, आदि का उपयोग करते हैं)। तो अगर आपकी फ़ाइल को नाम स्थान देने का कोई अच्छा कारण नहीं है, तो न करें। आप पहले से ही एक वर्ग में अपने कोड को लपेटकर नामकरण संघर्ष से बच रहे हैं। अपनी कक्षा के नाम को और अधिक विशिष्ट बनाएं, और अपनी validate()कॉलबैक को सार्वजनिक तरीकों के रूप में कक्षा में लाएं ।
  • अपने कोड के साथ अपने उद्धृत प्लगइन बॉयलरप्लेट की तुलना करते हुए , ऐसा लगता है कि आपका कोड वास्तव में फोर्क या बॉयलरप्लेट के पुराने संस्करण पर आधारित है। यहाँ तक कि फिल्म के नाम और रास्ते भी अलग हैं। आप अपने प्लगइन को नवीनतम संस्करण में माइग्रेट कर सकते हैं, लेकिन ध्यान दें कि यह प्लगइन बॉयलरप्लेट आपकी आवश्यकताओं के लिए सही नहीं हो सकता है। यह एकल के उपयोग करता है, जो आम तौर पर हतोत्साहित किया जाता है । ऐसे मामले हैं जहां सिंगलटन पैटर्न समझदार है , लेकिन यह सचेत निर्णय होना चाहिए, गोटो समाधान नहीं।

1
यह जानकर अच्छा लगा कि एपी में एक बग है। मैं हमेशा उन कोड के माध्यम से देखने की कोशिश करता हूं जो मैं बग के लिए लिखता हूं जो मैं पेश कर सकता हूं। बेशक, मुझे लगता है कि मैं एक या दो बात जानता हूं।
गेट_इंजीनियर

इस मुद्दे पर आने वाले किसी व्यक्ति के लिए: कोड में OOP उदाहरण देखें: codex.wordpress.org/Creating_Options_Pages#Example_.232
maysi

5

मुझे बस इसी मुद्दे की तलाश करते हुए यह पोस्ट मिला। समाधान दिखने में जितना आसान है उससे कहीं अधिक सरल है क्योंकि दस्तावेज़ भ्रामक है: register_setting () में पहला तर्क नाम $option_groupआपका पृष्ठ स्लग है, न कि वह अनुभाग जिसमें आप सेटिंग प्रदर्शित करना चाहते हैं।

ऊपर दिए गए कोड में आपको उपयोग करना चाहिए

    // Update Settings
    add_settings_section(
        'maintenance', // section slug
        'Maintenance', // section title
        array( $this, 'maintenance_section' ), // section display callback
        $this->plugin_slug // page slug
    );

    // Check Updates Option
    register_setting( 
        $this->plugin_slug, // page slug, not the section slug
        'plugin-name_check_updates', // setting slug
        'wp_plugin_name\validate_bool' // invalid, should be an array of options, see doc for more info
    );

    add_settings_field(
        'plugin-name_check_updates', // setting slug
        'Should ' . $this->friendly_name . ' Check For Updates?', // setting title
        array( $this, 'check_updates_field' ), //setting display callback
        $this->plugin_slug, // page slug
        'maintenance' // section slug
    );

यह सही नहीं है। कृपया इस कार्य उदाहरण को देखें (मेरा नहीं) - gist.github.com/annalinneajohansson/5290405
Xdg

2

विकल्प पृष्ठ को पंजीकृत करते समय:

add_submenu_page( string $parent_slug, string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '' )

और के साथ सेटिंग रजिस्टर करना

register_setting( string $option_group, string $option_name );

$option_group उतना ही होना चाहिए $menu_slug


1

मेरे पास एक ही त्रुटि थी, लेकिन इसे एक अलग तरीके से प्राप्त किया:

// no actual code
// this failed
add_settings_field('id','title', /*callback*/ function($arguments) {
    // echo $htmlcode; 
    register_setting('option_group', 'option_name');
}), 'page', 'section');

मुझे नहीं पता कि ऐसा क्यों हुआ, लेकिन ऐसा लगता है कि register_settingइसमें कॉलबैक नहीं होना चाहिएadd_settings_field

// no actual code
// this worked
add_settings_field('id','title', /*callback*/ function($arguments) {echo $htmlcode;}), 'page', 'section');
register_setting('option_group', 'option_name');

आशा है कि ये आपकी मदद करेगा


0

मैं कुछ दिनों से इस समस्या का सामना कर रहा हूँ, यह त्रुटि तब रुकी थी जब मैंने टिप्पणियों की लाइन डाली:

// settings_fields($this->plugin_slug);

उसके बाद मैं options.php पर रीडायरेक्ट कर रहा हूं, लेकिन मैं setting_fieldsअभी तक समस्या का समाधान नहीं कर सकता ।


मैं सत्यापन समारोह से यह तय !! ;)
जी कर्ल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.