admin管理员组

文章数量:1207756

Even though I have years of software development experience, I am new to WP & PHP development, so please bear with me.

After reading through the plugin manual, I started with a WP plugin boiler plate, made all the required field and name changes, added a custom capability, and, as a first real functionality, tried to add a simple admin interface for the plugin like so:

<?php

class Plugin_Name_Admin {

    // some code ommitted, the actual code uses my plugin's name, slugs, and fields

    public function init() {
        add_action('admin_menu', array($this, 'add_plugin_admin_menu'));
    }

    function add_plugin_admin_menu() {
            add_menu_page(
                'Plugin Name',
                'Plugin Menu',
                PLUGIN_USER_CAPABILITY,
                'plugin-name-admin',
                array( $this, 'admin_page' ),
                null,
                1
            );
        }
    
    function admin_page() {
        if ( current_user_can( PLUGIN_USER_CAPABILITY ) ) {
            require_once plugin_dir( __FILE__ ) . 'partials/plugin-name-admin-display.php';
        }
    }
}

The menu shows up for the users that have the assigned capability and the URL looks like /wp-admin/admin.php?page=plugin-name-admin but neither an administrator nor another user with the PLUGIN_USER_CAPABILITY can access that page. The error message is "Sorry, you are not allowed to access this page." and the error occurs in wp-admin/includes/plugin.php in the function user_can_access_admin_page where WP checks the following:

        if ( ! isset( $_registered_pages[ $hookname ] ) ) {
            return false;
        }

The hookname it uses is admin_page_plugin-name-admin-admin.

What am I missing?

Also, any pointers on how to properly debug WP code in PhpStorm would be greatly appreciated. So far, I've just been muddling around with added error messages.

EDIT: The Plugin_Name_Admin class is instantiated in the boilerplate code's main class in the define_admin_hooks function, which also adds the hook for the init function:

    private function define_admin_hooks() {

        $plugin_admin = new Plugin_Name_Admin( $this->get_plugin_name(), $this->get_version() );

        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
        $this->loader->add_action( 'admin_init', $plugin_admin, 'init' );

    }

This function is called from the constructor of the main class and uses the boiler plate's loader approach to create hooks.

As I mention in my answer below, changing the call to add_plugin_admin_menu from a hook for admin_menu to a direct call solved the permission error.

EDIT2: I got PhpStorm to work with XDebug using this write-up.

Even though I have years of software development experience, I am new to WP & PHP development, so please bear with me.

After reading through the plugin manual, I started with a WP plugin boiler plate, made all the required field and name changes, added a custom capability, and, as a first real functionality, tried to add a simple admin interface for the plugin like so:

<?php

class Plugin_Name_Admin {

    // some code ommitted, the actual code uses my plugin's name, slugs, and fields

    public function init() {
        add_action('admin_menu', array($this, 'add_plugin_admin_menu'));
    }

    function add_plugin_admin_menu() {
            add_menu_page(
                'Plugin Name',
                'Plugin Menu',
                PLUGIN_USER_CAPABILITY,
                'plugin-name-admin',
                array( $this, 'admin_page' ),
                null,
                1
            );
        }
    
    function admin_page() {
        if ( current_user_can( PLUGIN_USER_CAPABILITY ) ) {
            require_once plugin_dir( __FILE__ ) . 'partials/plugin-name-admin-display.php';
        }
    }
}

The menu shows up for the users that have the assigned capability and the URL looks like http://wp.localhost/wp-admin/admin.php?page=plugin-name-admin but neither an administrator nor another user with the PLUGIN_USER_CAPABILITY can access that page. The error message is "Sorry, you are not allowed to access this page." and the error occurs in wp-admin/includes/plugin.php in the function user_can_access_admin_page where WP checks the following:

        if ( ! isset( $_registered_pages[ $hookname ] ) ) {
            return false;
        }

The hookname it uses is admin_page_plugin-name-admin-admin.

What am I missing?

Also, any pointers on how to properly debug WP code in PhpStorm would be greatly appreciated. So far, I've just been muddling around with added error messages.

EDIT: The Plugin_Name_Admin class is instantiated in the boilerplate code's main class in the define_admin_hooks function, which also adds the hook for the init function:

    private function define_admin_hooks() {

        $plugin_admin = new Plugin_Name_Admin( $this->get_plugin_name(), $this->get_version() );

        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
        $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
        $this->loader->add_action( 'admin_init', $plugin_admin, 'init' );

    }

This function is called from the constructor of the main class and uses the boiler plate's loader approach to create hooks.

As I mention in my answer below, changing the call to add_plugin_admin_menu from a hook for admin_menu to a direct call solved the permission error.

EDIT2: I got PhpStorm to work with XDebug using this write-up.

Share Improve this question edited Feb 3, 2022 at 19:01 helgew asked Feb 3, 2022 at 17:16 helgewhelgew 1113 bronze badges 4
  • can you enable the logs and get a full error? might give you a better idea. – abestrad Commented Feb 3, 2022 at 17:29
  • 1 Where and when is Plugin_Name_Admin created? Your question only shows the definition of the class, not how it's used/created/instantiated, when you do it matters, so does where. Also what is the value of PLUGIN_USER_CAPABILITY and where does it come from? Have you eliminated this as a possibility by using a known capability that comes in standard WordPress installs rather than a custom capability? e.g. manage_options which administrators have would provide a test case for that theory – Tom J Nowell Commented Feb 3, 2022 at 17:39
  • I had the WP_DEBUG log enabled but it remained empty. The WP code doesn't seem to contain any debug or error generating lines either. As for where Plugin_Name_Admin is created, I had assumed some familiarity with the boilerplate code but I'll edit the question to make it clearer. PLUGIN_USER_CAPABILITY is, as stated, a custom capability used as a string constant. manage_options would not give me a menu for either the administrator nor any other user. – helgew Commented Feb 3, 2022 at 18:09
  • Just looked at the source code of WP Plugin Boilerplate and I don't like it at all (my personal opinion). It uses a lot of things I consider bad practice and would block if anyone of my colleagues tried to do. E.g. "class-X.php" filenames manually required, instead of using PSR-4 autoloading. Also the way classes are used makes it a testing nightmare as well as abstracts some important parts heavily away. I can't find a better boilerplate right now, but being a fan of Roots.io work I recommend checking Soil source code. – kero Commented Feb 4, 2022 at 9:55
Add a comment  | 

1 Answer 1

Reset to default 1

Well, as it usually goes, after banging my head on this for hours yesterday and then finally deciding to ask for help, I was able to solve it within a few minutes. Here is what I needed to change:

    public function init() {
        // add_action('admin_menu', array($this, 'add_plugin_admin_menu'));
        $this-> add_plugin_admin_menu();
    }

Clearly, I have much to learn about the call chain in WP.

本文标签: Unable to get a simple plugin admin page to work