Passando argumentos para um retorno de chamada da página de menu do administrador?

14

Situação: estou trabalhando em um plug-in e desenvolvendo-o como uma classe, tudo funcionou bem até eu me deparar com essa situação. Eu queria tornar as coisas um pouco mais limpas e tentei isso ..

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

Eu tentei várias opções diferentes, mas nada funciona, talvez eu esteja na frente, mas não consigo vê-lo.

É claro que isso é uma recriação, prefixei todas as minhas funções e elas não são exatamente como eu escrevi aqui, mas espero que você tenha a idéia de que estou pedindo.

Desde já, obrigado.

PD: Se você quiser ver o código fonte original, ficarei feliz em colá-lo e fornecer o link.

Luis
fonte

Respostas:

8

Você não pode passar um argumento para a função de retorno de chamada. add_menu_page()adiciona-o como um manipulador de ações e admin.phpdispara a ação , sem argumentos.

Eu vejo duas soluções simples para esse problema. Uma é armazenar todo o nome do arquivo em uma matriz da sua classe, indexada pelo nome do gancho. Em seguida, você pode usar isso para procurar qual arquivo você precisa carregar (também é possível armazenar dados adicionais nessa 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';
    }
}

A outra é ignorar o argumento de retorno de chamada, para que o WordPress inclua o arquivo indicado pelo próprio nome da lesma, como Brady sugere em sua resposta.

Jan Fabry
fonte
ah-ha, por que não pensei em fazê-lo dessa maneira :(
Brady
SIM!! você salvou dezenas de gatinhos hoje .. nunca ouviu falar dessa função no 'current_filter'. Solução muito inteligente. Muito obrigado pela sua ajuda @Brady @Jan Fabry
Luis
4

Você sempre pode usar apenas uma função anônima (ou fechamento). Algo que afeta:

add_menu_page( $page, $menu, $capability, $slug, function() { print_my_admin_page($with_args); }, $icon, $position);
user35752
fonte
1
Isso não funciona para mim. Estou usando o WordPress 4.1 (e a partir de hoje 4.1.1)
Jeff Vdovjak
Esperto! E isso funciona. Aqui está um exemplo mais completo: haste.bin / segibugice, que geraria um URL como exemplo.com/wp-admin/admin.php?page=my-slug
Comendador Quinn
Eu deveria ter mencionado ao passar variáveis ​​para o escopo de uma função anônima, você deve usar a palavra-chave "use". function() use ($my_var) { // now you can use $my_var }
User35752
0

a função load_view deve ser assim ?:

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

e no seu arquivo de inclusão, ele deve ecoar qualquer conteúdo da página que está sendo exibida.

EDITAR:

Aqui está o que o códice diz sobre o assunto:

$menu_slug (string) (required)O nome do slug ao qual se referir a este menu (deve ser exclusivo para este menu). Antes da versão 3.0, isso era chamado de parâmetro file (ou handle). Se o parâmetro de função for omitido, o menu_slug deve ser o arquivo PHP que lida com a exibição do conteúdo da página de menu. Padrão: Nenhum

$function A função que exibe o conteúdo da página para a página do menu. Tecnicamente, o parâmetro function é opcional, mas se não for fornecido, o WordPress basicamente assumirá que a inclusão do arquivo PHP irá gerar a tela de administração, sem chamar uma função. A maioria dos autores de plug-ins opta por inserir o código de geração de página em uma função em seu arquivo principal de plug-in :: No caso de o parâmetro function ser especificado, é possível usar qualquer string para o parâmetro file. Isso permite o uso de páginas como? Page = my_super_plugin_page em vez de? Page = my-super-plugin / admin-options.php.

Então, o que posso deduzir disso é que, se você deixar a função vazia, ela tenta incluir um arquivo php com base no que você definiu menu_slug.

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')
                 );
}
Brady
fonte
@ Brad Eu sei disso, e a função "load_view" está funcionando bem e produzindo o conteúdo corretamente ao usar um valor estático. Por exemplo: incl .... / views / my-panel.php ');
Luis
@Luis - Então qual é o problema?
Brady
@Brady array (& $ this, 'load_view') // Onde especifico o valor de $ filename ??. Eu não posso fazer algo como array (& $ this, 'load_view ("my-value")') 'Eu quero encontrar uma maneira de passar parâmetros para a função que estou chamando
Luis
Oh, eu entendi agora. Você deseja passar uma função de classe, mas com um parâmetro Bem, eu olhei e olhei e não consigo encontrar como fazê-lo. Mas como você está passando na aula, não pode fazer o que eu coloquei na EDIT 2?
Brady
@Brady: Sua segunda edição não vai ajudar muito, você apenas substitui a filenamevariável para que sempre seja "somethingelse". Sua primeira edição pode ser o truque aqui: se load_viewnão fizer nada, exceto incluir o arquivo, você realmente não deve passar uma função de retorno de chamada e o WordPress tentará carregar a página que você passou como lesma.
Jan Fabry
0

Resolvi esse problema anexando apenas o ID (ou quaisquer dados necessários) à lesma do menu.

Por exemplo:

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

Isso criará uma URL com 'my-plugin-settings-filename' (como exemplo), e eu posso apenas analisar essa parte da URL (com $ _GET ou filter_input).

Jeff Vdovjak
fonte
Você também pode usar um parâmetro de URL, mas precisa criar um item de menu (e pode ocultá-lo, se quiser).
Jeff Vdovjak
Obrigado por colocar meu código em um bloco de código toscho. Quando faço uma pergunta, há um botão para isso, mas não estou familiarizado com a marcação para fazer isso em uma resposta.
Jeff Vdovjak
0

Com base na resposta do usuário35752 , você pode até usar um método de objeto com parâmetros como retorno de chamada.

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