“Fehler: Optionen Seite nicht gefunden” auf der Einstellungsseite für ein OOP-Plugin

Ich entwickle ein Plugin mit Tom McFarlins Boilerplate- Repository als Vorlage, die OOP-Praktiken verwendet. Ich habe versucht herauszufinden, warum ich meine Einstellungen nicht richtig übermitteln kann. Ich habe versucht, das action-Attribut auf eine leere Zeichenfolge zu setzen, wie es hier auf einer anderen Frage vorgeschlagen wird, aber das hat nicht geholfen …

Unten ist die allgemeine Code-Konfiguration, die ich verwende …

Das Formular (/views/admin.php):

plugin_slug ); do_settings_sections( $this->plugin_slug ); submit_button( 'Save Settings' ); ?>

Nehmen Sie für den folgenden Code an, dass alle Callbacks für add_settings_field () und add_settings_section () existieren, mit Ausnahme von ‘option_list_selection’.

Die Plugin Admin class (/ {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 ); } } 

Einige angeforderte Updates:

Ändern des Aktionsattributs zu:

 

… führt einfach zu einem 404 Fehler. Im Folgenden finden Sie den Ausschnitt der Apache Logs. Beachten Sie, dass die Standard-WordPress-Skripts und CSS-Warteschlangen entfernt werden:

 # 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 

Sowohl die Datei php-errors.log als auch die Datei debug.log, wenn WP_DEBUG wahr ist, sind leer.

Die Plugin-class (/{plugin-name}-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 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 activated."; $new = FRIENDLY_NAME . " was successfully activated "; if ( $untranslated_text === $old ) $translated_text = $new; return $translated_text; } public function finalization_message( $translated_text, $untranslated_text, $domain ) { $old = "Plugin activated."; $new = "Captain, The Core is stable and PluginName was successfully installed and ready for Warp speed"; if ( $untranslated_text === $old ) $translated_text = $new; return $translated_text; } }

Verweise:

  • Die Einstellungs-API

    • add_settings_section ()
    • add_settings_field ()
    • register_setting ()
  • Erstellen von Optionen Seiten

Solutions Collecting From Web of "“Fehler: Optionen Seite nicht gefunden” auf der Einstellungsseite für ein OOP-Plugin"

“Fehler: Optionen Seite nicht gefunden” Fehler

Dies ist ein bekanntes Problem in der WP-Einstellungs-API. Vor Jahren wurde ein Ticket geöffnet, und es wurde als getriggers markiert – aber der Fehler bleibt in den neuesten Versionen von WordPress bestehen. Das sagt die (jetzt entfernte) Codex-Seite dazu :

Die “Fehler: Optionen Seite nicht gefunden.” Problem (einschließlich einer Lösung und Erklärung):

Das Problem ist dann, dass der ‘whitelist_options’ Filter nicht den richtigen Index für Ihre Daten hat. Es wird auf options.php # 98 (WP 3.4) angewendet.

register_settings() fügt Ihre Daten zu den globalen $new_whitelist_options . Dies wird dann mit den globalen $whitelist_options option_update_filter() in den option_update_filter() (bzw. add_option_whitelist() ) zusammengeführt. Diese Callbacks fügen Ihre Daten den globalen $new_whitelist_options mit der $option_group als Index hinzu. Wenn Sie auf “Fehler: Optionen Seite nicht gefunden.” Es bedeutet, dass Ihr Index nicht erkannt wurde. Die irreführende Sache ist, dass das erste Argument als Index verwendet wird und $options_group , wenn das eigentliche Einchecken von options.php # 112 gegen $options_page geschieht, was $hook_suffix , das man als @return Wert von add_submenu_page() .

Kurz gesagt, eine einfache Lösung besteht darin, $option_group zu $option_name zu machen. Eine weitere Ursache für diesen Fehler ist ein ungültiger Wert für den Parameter $page beim Aufruf von add_settings_section( $id, $title, $callback, $page ) oder add_settings_field( $id, $title, $callback, $page, $section, $args ) .

Hinweis: $page sollte $menu_slug von functionsreferenz / $menu_slug hinzufügen entsprechen.

Einfache Lösung

Die Verwendung des benutzerdefinierten Seitennamens (in Ihrem Fall: $this->plugin_slug ) als Sektions-ID würde das Problem $this->plugin_slug . Alle Ihre Optionen müssten jedoch in einem einzigen Abschnitt enthalten sein.

Lösung

Für eine Plugin_Name_Admin Lösung nehmen Sie diese Änderungen an Ihrer class Plugin_Name_Admin :

Zum Konstruktor hinzufügen:

 // 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 ); 

Fügen Sie diese Methoden hinzu:

 // 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; } } 

Und ändern Sie add_settings_section() Aufrufe an: $this->add_settings_section() .


Weitere Hinweise zu Ihrem Code

  • Ihr Formularcode ist korrekt. Ihr Formular muss an options.php gesendet werden, wie von @Chris_O angegeben und in der API- Dokumentation von WP-Einstellungen angegeben.
  • Namespacing hat seine Vorteile, aber es kann das Debuggen komplexer machen und die Kompatibilität Ihres Codes verringern (erfordert PHP> = 5.3, andere Plugins / Themes, die Autoloader verwenden, usw.). Wenn es keinen guten Grund gibt, Ihre Datei mit einem Namespace zu versehen, tun Sie dies nicht. Sie vermeiden bereits Namenskonflikte, indem Sie Ihren Code in eine class einfügen. Machen Sie Ihre classnnamen spezifischer und bringen Sie Ihre validate() -callbacke als öffentliche Methoden in die class ein.
  • Vergleicht man die zitierte Plug- in-Codebeispiel mit Ihrem Code, sieht es so aus, als ob Ihr Code tatsächlich auf einer Gabel oder einer alten Version des Boilerplate basiert. Sogar die Dateinamen und Pfade sind unterschiedlich. Sie können Ihr Plugin auf die neueste Version migrieren, aber beachten Sie, dass dieses Plugin nicht für Ihre Bedürfnisse geeignet ist. Es verwendet Singletons, die im Allgemeinen entmutigt werden . Es gibt Fälle, in denen das Singleton-Muster sinnvoll ist , aber dies sollte eine bewusste Entscheidung sein, nicht die Goto-Lösung.

Ich habe gerade diesen Beitrag gefunden, als ich nach demselben Problem gesucht habe. Die Lösung ist viel einfacher als es aussieht, weil die Dokumentation irreführend ist: In register_setting () ist das erste Argument mit dem Namen $option_group Ihr Seiten-Slug, nicht der Bereich, in dem Sie die Einstellung anzeigen möchten.

In dem obigen Code sollten Sie verwenden

  // 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 );