Passing arguments to a admin menu page callback?

Situation: I’m working on a plugin and I’m developing it as a class, everything worked fine until I run into this situation. I wanted to make things a bit cleaner and tried this..

class MyPlugin {
    function __construct() {
        add_action('admin_menu', array(&$this, 'myplugin_create_menus');
    }        

    //I don't want to write a function for every options page I create
    //so I prefer to just load the content from an external file.        
    function load_view($filename) {
        $view = require(dirname(__FILE__).'/views/'.$filename.'.php');
        return $view;
    }

    //Here is where the problem comes
    function myplugin_create_menus() {
        add_menu_page( 'Plugin name',
                       'Plugin name',
                       'manage_options',
                       'my-plugin-settings',
                       array(&$this, 'load_view') // Where do I specify the value of $filename??
                     );
    }

}#end of class

I’ve tried a bunch of different options but nothing works, maybe I’m in front of it but I can’t see it.

Read More

Of course this is a re-creation, I’ve prefixed all my functions and they are not exactly as I wrote here but I hope you got the idea of I’m asking for.

Thanks in advance.

P.D.: If you want to see the original source code I’ll be glad to paste it and give you the link.

Related posts

Leave a Reply

5 comments

  1. You can’t pass an argument to the callback function. add_menu_page() adds it as an action handler, and admin.php fires the action, without any arguments.

    I see two simple solutions to this problem. One is to store all filename in an array in your class, indexed by hook name. Then you can use this to look up what file you need to load (you can also store additional data in this array).

    class WPSE16415_Plugin
    {
        protected $views = array();
    
        function load_view() {
            // current_filter() also returns the current action
            $current_views = $this->views[current_filter()];
            include(dirname(__FILE__).'/views/'.$current_views.'.php');
        }
    
        function myplugin_create_menus() {
            $view_hook_name = add_menu_page( 'Plugin name',
                'Plugin name',
                'manage_options',
                'my-plugin-settings',
                array(&$this, 'load_view'),
            );
            $this->views[$view_hook_name] = 'options';
        }
    }
    

    The other is to skip the callback argument, so WordPress will include the file indicated by the slug name itself, as Brady suggests in his answer.

  2. You could always just use an anonymous function (or closure). Something to the affect of:

    add_menu_page( $page, $menu, $capability, $slug, function() { print_my_admin_page($with_args); }, $icon, $position);
    
  3. the function load_view should be like this?:

    function load_view($filename) {
        include(dirname(__FILE__).'/views/'.$filename.'.php');
    }
    

    and in your include file it should echo any content for the page being displayed.

    EDIT:

    Here is what the codex says on the matter:

    $menu_slug
    (string) (required)
    The slug name to refer to this menu by (should be unique for this menu). Prior to Version 3.0 this was called the file (or handle) parameter. If the function parameter is omitted, the menu_slug should be the PHP file that handles the display of the menu page content.
    Default: None

    $function
    The function that displays the page content for the menu page. Technically, the function parameter is optional, but if it is not supplied, then WordPress will basically assume that including the PHP file will generate the administration screen, without calling a function. Most plugin authors choose to put the page-generating code in a function within their main plugin file.:In the event that the function parameter is specified, it is possible to use any string for the file parameter. This allows usage of pages such as ?page=my_super_plugin_page instead of ?page=my-super-plugin/admin-options.php.

    So what I can gather from this is that if you leave function empty it tries to include a php file based on what you have set the menu_slug to.

    EDIT 2

    function load_view() {
        include(dirname(__FILE__).'/views/'.$this->filename.'.php');
    }
    
    function myplugin_create_menus() {
        $this->filename = "something";
        add_menu_page( 'Plugin name',
                       'Plugin name',
                       'manage_options',
                       'my-plugin-settings',
                       array(&$this, 'load_view')
                     );
        $this->filename = "somethingelse";
        add_menu_page( 'Plugin name',
                       'Plugin name',
                       'manage_options',
                       'my-plugin-settings',
                       array(&$this, 'load_view')
                     );
    }
    
  4. I solved this problem by just appending the ID (or whatever data you need to) to the menu slug.

    For example:

     add_menu_page( 'Plugin name',
                           'Plugin name',
                           'manage_options',
                           'my-plugin-settings-' . $identifier,
                           'setting-function-callback'
                         );
    

    This will then create a URL with ‘my-plugin-settings-filename’ (as an example), and I can just parse that part of the URL (with the $_GET or filter_input).

  5. Based on user35752 answer, you can even use an object method with params as callback.

    $args = [ [new Foo(), 'bar'], [$param1, $param2, ...] ];
    
    $callback = function () use ($args){
                    call_user_func_array($args[0], $args[1]);
                };
    add_menu_page( $page, $menu, $capability, $slug, $callback , $icon, $position)