¿Pasar argumentos a una devolución de llamada de la página del menú de administración?

14

Situación: estoy trabajando en un complemento y lo estoy desarrollando como una clase, todo funcionó bien hasta que me encontré con esta situación. Quería hacer las cosas un poco más limpias y probé esto ...

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

He probado un montón de opciones diferentes, pero nada funciona, tal vez estoy frente a él, pero no puedo verlo.

Por supuesto, esta es una recreación, he prefijado todas mis funciones y no son exactamente como las escribí aquí, pero espero que sepas la idea que estoy pidiendo.

Gracias por adelantado.

PD: Si desea ver el código fuente original, me complacerá pegarlo y darle el enlace.

Luis
fuente

Respuestas:

8

No puede pasar un argumento a la función de devolución de llamada. add_menu_page()lo agrega como un manejador de acciones y admin.phpdispara la acción , sin ningún argumento.

Veo dos soluciones simples a este problema. Una es almacenar todos los nombres de archivo en una matriz en su clase, indexados por nombre de gancho. Luego puede usar esto para buscar qué archivo necesita cargar (también puede almacenar datos adicionales en esta matriz).

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

El otro es omitir el argumento de devolución de llamada, por lo que WordPress incluirá el archivo indicado por el nombre del slug, como sugiere Brady en su respuesta.

Jan Fabry
fuente
ah-ha por qué no pensé en hacerlo de esa manera :(
Brady
¡¡SI!! salvaste a docenas de gatitos hoy ... nunca escuché de esa función a través de 'current_filter'. Solución muy inteligente. Muchas gracias por su ayuda @Brady @Jan Fabry
Luis
4

Siempre puede usar una función anónima (o cierre). Algo que afecta a:

add_menu_page( $page, $menu, $capability, $slug, function() { print_my_admin_page($with_args); }, $icon, $position);
usuario35752
fuente
1
Esto no funciona para mi. Estoy usando WordPress 4.1 (y a partir de hoy 4.1.1)
Jeff Vdovjak
¡Inteligente! Y funciona. Aquí hay un ejemplo más completo: hastebin.com/segibugice que generaría una URL como example.com/wp-admin/admin.php?page=my-slug
Quinn Comendant
Debería haber mencionado que al pasar variables al alcance de una función anónima, debe usar la palabra clave "use". function() use ($my_var) { // now you can use $my_var }
user35752
0

¿La función load_view debería ser así ?:

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

y en su archivo de inclusión debe hacer eco de cualquier contenido para la página que se muestra.

EDITAR:

Esto es lo que dice el códice al respecto:

$menu_slug (string) (required)El nombre del slug para referirse a este menú (debe ser único para este menú). Antes de la Versión 3.0, esto se llamaba parámetro de archivo (o identificador). Si se omite el parámetro de función, menu_slug debe ser el archivo PHP que maneja la visualización del contenido de la página del menú. Predeterminado: Ninguno

$function La función que muestra el contenido de la página para la página del menú. Técnicamente, el parámetro de función es opcional, pero si no se proporciona, WordPress básicamente asumirá que incluir el archivo PHP generará la pantalla de administración, sin llamar a una función. La mayoría de los autores de complementos eligen colocar el código de generación de páginas en una función dentro de su archivo principal de complementos: en el caso de que se especifique el parámetro de función, es posible usar cualquier cadena para el parámetro de archivo. Esto permite el uso de páginas como? Page = my_super_plugin_page en lugar de? Page = my-super-plugin / admin-options.php.

Entonces, lo que puedo deducir de esto es que si deja la función vacía, intenta incluir un archivo php basado en lo que ha configurado menu_slug .

EDITAR 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')
                 );
}
Brady
fuente
@Brady, lo sé, y la función "load_view" funciona bien y genera el contenido correctamente cuando se usa un valor estático. Por ejemplo: incl .... / views / my-panel.php ');
Luis
@ Luis - Entonces, ¿cuál es el problema?
Brady,
@Brady array (& $ this, 'load_view') // ¿Dónde especifico el valor de $ filename ??. No puedo hacer algo como array (& $ this, 'load_view ("my-value")') Quiero encontrar una manera de pasar parámetros a la función a la que estoy llamando
Luis
Oh Ahora lo entiendo. Desea pasar una función de clase pero con un parámetro. Bueno, he mirado y mirado y no puedo encontrar cómo lo haces. Pero dado que estás pasando la clase, ¿no puedes hacer lo que he puesto en EDIT 2?
Brady
@Brady: su segunda edición no ayudará mucho, simplemente anula la filenamevariable para que siempre lo sea "somethingelse". Su primera edición podría ser el truco aquí: si load_viewno hace nada excepto incluir el archivo, no debería pasar una función de devolución de llamada y WordPress intentará cargar la página que pasó como la babosa.
Jan Fabry
0

Resolví este problema simplemente agregando la ID (o cualquier información que necesite) a la babosa del menú.

Por ejemplo:

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

Esto creará una URL con 'my-plugin-settings-filename' (como ejemplo), y puedo analizar esa parte de la URL (con $ _GET o filter_input).

Jeff Vdovjak
fuente
También puede usar un parámetro de URL, pero debe crear un elemento de menú (y luego puede ocultarlo si lo desea).
Jeff Vdovjak
Gracias por poner mi código en un bloque de código toscho. Cuando hago una pregunta, hay un botón para ello, pero no estoy familiarizado con el marcado para hacerlo en una respuesta.
Jeff Vdovjak
0

Según la respuesta del usuario 35752 , incluso puede usar un método de objeto con parámetros como devolución de llamada.

$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)
Lordgretix
fuente