OOP Eklentisi için Ayarlar Sayfası Gönderimi'nde “Hata: Seçenekler Sayfası Bulunamadı”


19

Tom McFarlin'in Boilerplate deposunu OOP uygulamalarını kullanan bir şablon olarak kullanarak bir eklenti geliştiriyorum . Ayarlarımı neden doğru bir şekilde gönderemediğimi tam olarak anlamaya çalışıyorum. Burada başka bir soruya önerildiği gibi boş bir dize eylem özniteliğini ayarlamaya çalıştım, ama bu yardımcı olmadı ...

Aşağıda kullandığım genel kod kurulumu ...

Form (/views/admin.php):

<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>

Aşağıdaki kod için, 'option_list_selection' dışında, add_settings_field () ve add_settings_section () için tüm geri çağrıların var olduğunu varsayın.

Eklenti Yönetici Sınıfı (/ {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
        );
    }
}

İstenen Bazı Güncellemeler:

Action özelliğini şu şekilde değiştirir:

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

... sadece 404 hatası verir. Aşağıdakiler Apache Günlüklerinin alıntısıdır. Varsayılan WordPress komut dosyalarının ve CSS en sıralarının kaldırıldığını unutmayın:

# 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 doğru olduğunda hem php-error.log dosyası hem de debug.log dosyası boştur.

Eklenti Sınıfı (/{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 < 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;

    }

}

Referanslar:


Ödül açıklaması şunları bildirir: "Lütfen en iyi uygulamalar hakkında bilgi verin " . Özel yapımcılarla singletonları ve içindeki bir sürü eylemi kullanmak: ancak, hatalı uygulama ve test edilmesi zor, hatanız değil.
gmazzap

1
kodunuzu test ettikten sonra ../../options.php kullanın.
ravi patel

Lütfen get_plugin_slug () 'i gösterebilir misiniz?
vancoder

@vancoder Yukarıdaki
yazıyı

Register_settings içindeki sanitization geri aramalarınızda neden ters eğik çizgiler var? Bunun işe yarayacağını sanmıyorum.
Bjorn

Yanıtlar:


21

"Hata: Seçenekler Sayfası Bulunamadı" Hatası

Bu WP Ayarları API'sında bilinen bir sorundur . Orada bir bilet açıldı yıl önce ve çözülmesi gibi kutlandı - ama WordPress'in son sürümlerinde hata devam ederse. Bu nedir (şimdi kaldırıldı) Codex sayfa Bu konuda adı geçen :

"Hata: seçenekler sayfası bulunamadı." sorun (bir çözüm ve açıklama dahil):

O zaman sorun, 'beyaz liste_seçenekleri' filtresinin verileriniz için doğru dizine sahip olmamasıdır. Options.php # 98 (WP 3.4) üzerine uygulanır.

register_settings()verilerinizi global alana ekler $new_whitelist_options. Bu daha sonra küresel ( geri) geri arama (lar) ın $whitelist_optionsiçinde birleştirilir . Bunlar geri aramaları küresel için veri eklemek ile olduğu gibi indeksi. "Hata: seçenekler sayfası bulunamadı." İle karşılaştığınızda bu, dizininizin tanınmadığı anlamına gelir. Yanıltıcı şey ilk argüman endeksi olarak kullanılan ve adlandırılmış olmasıdır , ne zaman # 112 karşı olur options.php gerçek çek olduğunu sizden @return değer olarak almak, .option_update_filter()add_option_whitelist()$new_whitelist_options$option_group$options_group$options_page$hook_suffixadd_submenu_page()

Kısacası, kolay bir çözüm $option_groupbulmaktır $option_name. Bu hatanın başka bir nedeni, veya $pageparametresini çağırırken parametre için geçersiz bir değere sahip olmaktır .add_settings_section( $id, $title, $callback, $page )add_settings_field( $id, $title, $callback, $page, $section, $args )

İpucu: İşlev Başvurusu / tema ekle sayfasından $pageeşleşmelidir $menu_slug.

Basit Düzeltme

$this->plugin_slugBölüm kimliğiniz olarak özel sayfa adını (sizin durumunuzda :) kullanmak sorunu çözer. Ancak, tüm seçeneklerinizin tek bir bölümde yer alması gerekir.

Çözüm

Daha sağlam bir çözüm için Plugin_Name_Adminsınıfınızda şu değişiklikleri yapın :

Yapıcıya ekle:

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

Bu yöntemleri ekleyin:

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

Ve değişim add_settings_section()çağrılarını: $this->add_settings_section().


Kodunuzla ilgili diğer notlar

  • Form kodunuz doğru. Formunuzun @Chris_O tarafından bana işaret edildiği ve WP Ayarları API dokümanlarında belirtildiği gibi options.php adresine gönderilmesi gerekir .
  • Ad alanı açıklamanın avantajları vardır, ancak hata ayıklamayı daha karmaşık hale getirebilir ve kodunuzun uyumluluğunu azaltabilir (PHP> = 5.3, otomatik yükleyicileri kullanan diğer eklentiler / temalar vb. Gerektirir). Bu nedenle, dosyanızı ad alanı oluşturmak için iyi bir neden yoksa, yapmayın. Kodunuzu bir sınıfa kaydırarak adlandırma çakışmalarını zaten engelliyorsunuz. Sınıf adlarınızı daha spesifik hale getirin ve validate()geri çağrılarınızı genel yöntemler olarak sınıfa getirin .
  • Belirtilen eklenti kazan plakasını kodunuzla karşılaştırdığınızda, kodunuzun aslında bir çatalı veya kazan plakasının eski bir versiyonunu temel aldığı anlaşılıyor. Dosya adları ve yollar bile farklı. Eklentinizi en son sürüme geçirebilirsiniz, ancak bu eklenti kazan plakasının ihtiyaçlarınız için doğru olmayabileceğini unutmayın. Genellikle cesareti kırılmış tektonları kullanır . Singleton paterninin mantıklı olduğu durumlar vardır , ancak bu, goto çözümünün değil, bilinçli bir karar olmalıdır.

1
API'de bir hata olduğunu bilmek güzel. Ben her zaman ben tanıtabilir hatalar için yazıyorum kodu bakmak için girişimde bulunun. Tabii ki, bu bir ya da iki şey bildiğimi varsayar.
gate_engineer

Bu sorunla karşılaşan herkes için: codex'taki
maysi

5

Aynı soruyu ararken bu gönderiyi yeni buldum. Çözüm, belgelerin yanıltıcı olması nedeniyle göründüğünden çok daha basittir: register_setting ()$option_group öğesinde ilk argüman , ayarı görüntülemek istediğiniz bölüm değil, sayfa bilginizdir.

Yukarıdaki kodda şunu kullanmalısınız:

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

Bu doğru değil. Lütfen bu çalışma örneğine bakın (benim değil) - gist.github.com/annalinneajohansson/5290405
Xdg

2

Seçenekler sayfasını aşağıdakilerle kaydederken:

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

Ve ayarları ile kaydetme

register_setting( string $option_group, string $option_name );

$option_group ile aynı olmalı $menu_slug


1

Aynı hatayı aldım ama farklı bir yoldan aldım:

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

Bunun neden bilmiyorum, ama gibi görünüyor register_settingarasında callback'inde olmamalı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');

Umarım bu yardımcı olur


0

Ben de birkaç gündür bu sorunla karşı karşıya kaldım, ben satır satır yorum koymak zaman bu hata durmuştu:

// settings_fields($this->plugin_slug);

Bundan sonra ben options.php yönlendiriyorum ama setting_fieldshenüz sorunu çözemiyorum .


Ben doğrulama işlevinden sabit !! ;)
G.Karles
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.