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

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);
user35752
источник
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
источник
@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)
Lordgretix
источник