Передача аргументов в обратный вызов страницы меню администратора?


14

Ситуация: я работаю над плагином и разрабатываю его как класс, все работало нормально, пока я не столкнулся с этой ситуацией. Я хотел сделать вещи немного чище и попробовал это ..

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

Я пробовал кучу разных вариантов, но ничего не работает, может быть, я перед этим, но я не вижу его.

Конечно, это воссоздание, я поставил перед всеми своими функциями префиксы, и они не совсем такие, как я написал здесь, но я надеюсь, что вы поняли, о чем я прошу.

Заранее спасибо.

PD: Если вы хотите увидеть оригинальный исходный код, я буду рад вставить его и дать ссылку.

Ответы:


8

Вы не можете передать аргумент в функцию обратного вызова. add_menu_page()добавляет его как обработчик действия и admin.phpзапускает действие без каких-либо аргументов.

Я вижу два простых решения этой проблемы. Одним из них является сохранение всех имен файлов в массиве вашего класса, проиндексированного по имени хука. Затем вы можете использовать это для поиска файла, который вам нужно загрузить (вы также можете сохранить дополнительные данные в этом массиве).

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

Другой способ - пропустить аргумент обратного вызова, поэтому WordPress будет включать файл, указанный самим именем слага, как предполагает Брейди в своем ответе.


ах-ха, почему я не подумал сделать это таким образом :(
Брэди,

ДА!! Вы спасли десятки котят сегодня ... никогда не слышали об этой функции, хотя 'current_filter'. Очень умное решение. Большое спасибо за вашу помощь @Brady @Jan Fabry
Луис

4

Вы всегда можете просто использовать анонимную функцию (или замыкание). Что-то на аффект:

add_menu_page( $page, $menu, $capability, $slug, function() { print_my_admin_page($with_args); }, $icon, $position);

1
Это не работает для меня. Я использую WordPress 4.1 (и на сегодняшний день 4.1.1)
Джефф Вдовьяк

Умная! И это работает. Вот более полный пример: hastebin.com/segibugice, который будет генерировать URL-адрес, например example.com/wp-admin/admin.php?page=my-slug
Quinn Comendant

Я должен был упомянуть при передаче переменных в область действия анонимной функции, вы должны использовать ключевое слово «use». function() use ($my_var) { // now you can use $my_var }
user35752

0

функция load_view должна быть такой?

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

и в вашем включаемом файле он должен отображать любой контент для отображаемой страницы.

РЕДАКТИРОВАТЬ:

Вот что говорит Кодекс по этому вопросу:

$menu_slug (string) (required)Имя пули для ссылки на это меню (должно быть уникальным для этого меню). До версии 3.0 это называлось параметром файла (или дескриптора). Если параметр функции пропущен, menu_slug должен быть PHP-файлом, который обрабатывает отображение содержимого страницы меню. По умолчанию: нет

$function Функция, которая отображает содержимое страницы для страницы меню. Технически, параметр функции является необязательным, но если он не предоставлен, WordPress в основном будет предполагать, что включение файла PHP создаст экран администрирования без вызова функции. Большинство авторов плагинов предпочитают помещать генерирующий страницу код в функцию в свой основной файл плагина. В случае, если указан параметр функции, можно использовать любую строку для параметра файла. Это позволяет использовать такие страницы, как? Page = my_super_plugin_page вместо? Page = my-super-plugin / admin-options.php.

Итак, из этого я могу сделать вывод, что если вы оставите функцию пустой, она попытается включить php-файл, основываясь на том, что вы установили menu_slugдля.

РЕДАКТИРОВАТЬ 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 Я знаю это, и функция «load_view» работает хорошо и правильно выводит контент при использовании статического значения. Например: incl .... / views / my-panel.php ');
Луис

@Luis - Тогда в чем проблема?
Брейди,

@Brady array (& $ this, 'load_view') // Где мне указать значение $ filename ??. Я не могу сделать что-то вроде массива (& $ this, 'load_view ("my-value") ") Я хочу найти способ передачи параметров в функцию, которую я вызываю
Луис

О, я понял это сейчас. Вы хотите передать функцию класса, но с параметром. Хорошо я выглядел и смотрел и не могу найти, как ты это делаешь. Но так как вы проходите класс, то не можете ли вы сделать то, что я положил в EDIT 2?
Брейди,

@Brady: Ваше второе редактирование мало поможет, вы просто переопределите filenameпеременную, чтобы она всегда была "somethingelse". Ваше первое редактирование может быть уловкой: если load_viewничего не делает, кроме включения файла, вы действительно не должны передавать функцию обратного вызова, и WordPress попытается загрузить страницу, которую вы передали в качестве слаг.
Ян Фабри

0

Я решил эту проблему, просто добавив идентификатор (или любые другие данные, которые вам нужны) в слаг меню.

Например:

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

Затем будет создан URL-адрес с именем «my-plugin-settings-filename» (в качестве примера), и я могу просто проанализировать эту часть URL-адреса (с помощью $ _GET или filter_input).


Вы также можете использовать параметр URL, но вы должны создать пункт меню (и затем вы можете скрыть его, если хотите).
Джефф Вдовяк

Спасибо за то, что поместили мой код в блок кода. Когда я задаю вопрос, есть кнопка для него, но я не знаком с разметкой, чтобы сделать это в ответе.
Джефф Вдовяк

0

На основе ответе пользователя 35752 , вы даже можете использовать объектный метод с параметрами в качестве обратного вызова.

$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)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.