Передача аргументов в callback-функцию страницы меню админки WordPress
Ситуация: Я работаю над плагином и разрабатываю его как класс, всё работало хорошо, пока я не столкнулся с этой ситуацией. Я хотел сделать код чище и попробовал это...
class MyPlugin {
function __construct() {
add_action('admin_menu', array(&$this, 'myplugin_create_menus');
}
// Не хочу писать отдельную функцию для каждой страницы настроек
// предпочитаю загружать содержимое из внешнего файла.
function load_view($filename) {
$view = require(dirname(__FILE__).'/views/'.$filename.'.php');
return $view;
}
// Здесь возникает проблема
function myplugin_create_menus() {
add_menu_page( 'Название плагина',
'Название плагина',
'manage_options',
'my-plugin-settings',
array(&$this, 'load_view') // Где указать значение $filename??
);
}
}#конец класса
Я пробовал разные варианты, но ничего не работает, может я смотрю прямо на решение, но не вижу его.
Конечно, это упрощённый пример, все мои функции имеют префиксы и выглядят не совсем так, как здесь, но надеюсь, вы поняли суть моего вопроса.
Заранее спасибо.
P.S.: Если хотите увидеть оригинальный исходный код, я с радостью вставлю его и дам ссылку.

Вы не можете передать аргумент в callback-функцию. add_menu_page()
добавляет её как обработчик действия, а admin.php
запускает действие, без каких-либо аргументов.
Я вижу два простых решения этой проблемы. Первое — хранить все имена файлов в массиве внутри вашего класса, индексируя их по имени хука. Затем вы можете использовать это для поиска нужного файла для загрузки (вы также можете хранить дополнительные данные в этом массиве).
class WPSE16415_Plugin
{
protected $views = array();
function load_view() {
// current_filter() также возвращает текущее действие
$current_views = $this->views[current_filter()];
include(dirname(__FILE__).'/views/'.$current_views.'.php');
}
function myplugin_create_menus() {
$view_hook_name = add_menu_page( 'Название плагина',
'Название плагина',
'manage_options',
'my-plugin-settings',
array(&$this, 'load_view'),
);
$this->views[$view_hook_name] = 'options';
}
}
Второй вариант — пропустить аргумент callback, чтобы WordPress сам включал файл, указанный в имени слага, как предлагает Брэди в своём ответе.

У меня это не работает. Я использую WordPress 4.1 (и на сегодняшний день 4.1.1)

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

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

Я решил эту проблему, просто добавляя ID (или любые другие нужные данные) к слагу меню.
Например:
add_menu_page( 'Название плагина',
'Название плагина',
'manage_options',
'my-plugin-settings-' . $identifier,
'setting-function-callback'
);
Это создаст URL вида 'my-plugin-settings-filename' (например), и я могу просто разобрать эту часть URL (с помощью $_GET или filter_input).

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

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

Функция load_view должна выглядеть так?:
function load_view($filename) {
include(dirname(__FILE__).'/views/'.$filename.'.php');
}
И в вашем включаемом файле она должна выводить контент для отображаемой страницы.
РЕДАКТИРОВАНО:
Вот что говорит кодекс по этому поводу:
$menu_slug
(string) (обязательный)
Уникальный идентификатор для этого меню (должен быть уникальным для данного меню). До версии 3.0 этот параметр назывался file (или handle). Если параметр функции опущен, menu_slug должен быть PHP-файлом, который обрабатывает отображение содержимого страницы меню.
По умолчанию: Нет
$function
Функция, которая отображает содержимое страницы для пункта меню. Технически, параметр функции не является обязательным, но если он не указан, WordPress будет считать, что включаемый PHP-файл генерирует административный экран без вызова функции. Большинство авторов плагинов предпочитают размещать код генерации страницы в функции внутри основного файла плагина.:В случае, если параметр функции указан, можно использовать любую строку для параметра file. Это позволяет использовать страницы вида ?page=my_super_plugin_page вместо ?page=my-super-plugin/admin-options.php.
Из этого я могу сделать вывод, что если оставить функцию пустой, WordPress попытается включить PHP-файл на основе того, что вы установили в menu_slug
.
РЕДАКТИРОВАНО 2
function load_view() {
include(dirname(__FILE__).'/views/'.$this->filename.'.php');
}
function myplugin_create_menus() {
$this->filename = "something";
add_menu_page( 'Название плагина',
'Название плагина',
'manage_options',
'my-plugin-settings',
array(&$this, 'load_view')
);
$this->filename = "somethingelse";
add_menu_page( 'Название плагина',
'Название плагина',
'manage_options',
'my-plugin-settings',
array(&$this, 'load_view')
);
}

@Brady Я знаю это, и функция "load_view" работает корректно и выводит содержимое правильно при использовании статического значения. Например: incl..../views/my-panel.php');

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

А, теперь я понял. Вы хотите передать метод класса, но с параметром. Я искал и искал, но не могу найти, как это сделать. Но раз вы передаете класс, то разве нельзя сделать так, как я указал в EDIT 2?

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

На основе ответа user35752, вы даже можете использовать метод объекта с параметрами в качестве 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)
