Динамическое имя функции в php
Я хотел бы упростить создание "Пользовательских типов записей" в WordPress, поскольку утомительно проходить один и тот же сценарий и снова и снова менять все экземпляры имен пользовательских типов записей вручную.
Это довольно просто сделать, создав переменную, содержащую имя CPT, и использовать ее везде, где это необходимо. Таким образом, все, что мне нужно сделать, это объявить переменную в начале скрипта, и это должно позаботиться обо всем остальном.
Единственная проблема заключается в том, что для того, чтобы это работало, мне также нужно добавить префикс имени CPT перед каждой функцией в скрипте, и кажется, что использование переменной в имени функции не легко или даже не рекомендуется в PHP.
Так как я мог решить это?
Вот пример ниже, чтобы прояснить это:
$prefix = 'news';
function news_custom_type_init()
{
global $prefix;
register_post_type($prefix, array(
'labels' => array(
'name' => $prefix,
'singular_label' => $prefix,
'add_new' => 'Add',
...
));
register_taxonomy_for_object_type( 'category', $prefix );
}
add_action('init', $prefix.'_custom_type_init');
Это почти нормально и может быть стандартизировано, если только я смогу динамически переименовать функцию, чтобы не писать слово "новости" перед ней, а вместо этого использовать префикс "$".
Это могло бы быть хорошо, но просто не работает:
$prefix = 'news';
$functionName= $prefix."_custom_type_init";
function $functionName()
{
global $prefix;
register_post_type($prefix, array(
'labels' => array(
'name' => $prefix,
'singular_label' => $prefix,
'add_new' => 'Add',
...
));
register_taxonomy_for_object_type( 'category', $prefix );
}
add_action('init', $prefix.'_custom_type_init');
Необходимость именовать функцию как бы побеждает первоначальную цель моей попытки (особенно, когда скрипт включает в себя десятки подобных функций).
Каков был бы лучший способ сделать это?
PS: я много гуглил и "переполнялся стеком" по этому поводу, но не нашел ни одного рабочего решения, которое бы соответствовало моим потребностям и не генерировало сообщение об ошибке WordPress.
Спасибо.
10 ответов
Достаточно просто, вот похожая отрывочная форма проекта:
$function = $prefix . '_custom_type_init';
if(function_exists($function)) {
$function();
}
Это старый поток, но просто используйте анонимные функции:
add_action('init', function() use($args) {
//...
});
Тогда нет необходимости объявлять так много функций.
Редактировать (2017-04): Анонимные функции (должным образом реализованные) - это путь, см. Ответ Дэвида Вильхубера.
Этот ответ не рекомендуется, как и любой подход, который включает в себя код в виде строки, потому что это включает (среди прочего) конкатенацию.
Я не уверен, что это целесообразно использовать, или это вам помогает, но php позволяет создавать "анонимные" функции:
function generateFunction ($prefix) {
$funcname = create_function(
'/* comma separated args here */',
'/* insert code as string here, using $prefix as you please */'
);
return $funcname;
}
$func= generateFunction ("news_custom_type_init");
$func(); // runs generated function
Я предполагаю, что add_action просто вызывает любую функцию, которую вы передали.
http://php.net/manual/en/function.create-function.php
Примечание: create_function не вернет функцию с нужным именем, но содержимое функции будет находиться под вашим контролем, и настоящее имя функции не имеет значения.
Я думаю, что вы могли бы использовать
runkit_function_add
http://php.net/manual/pl/function.runkit-function-add.php
Еще один доступный метод заключается в использовании eval()
Вы можете использовать строку в скобках
("function_name_{$dynamic_var}")()
Этот пост старый, но PHP 7 может решить этот вопрос.
Пытаться:
$prefix = 'news';
$functionName = $prefix . "_custom_type_init";
${$functionName} = function() use ($prefix) {
register_post_type($prefix, array(
'labels' => array(
'name' => $prefix,
'singular_label' => $prefix,
'add_new' => 'Add'
)
);
register_taxonomy_for_object_type( 'category', $prefix );
};
add_action('init', '$' . $functionName);
Я думаю, что это должно работать для WordPress.
Динамическая функция, названная в PHP как
variable functions
https://www.php.net/manual/en/functions.variable-functions.php
как пример
$functionName = function () {
global $prefix;
register_post_type($prefix, array(
'labels' => array(
'name' => $prefix,
'singular_label' => $prefix,
'add_new' => 'Add',
...
));
register_taxonomy_for_object_type( 'category', $prefix );
}
вы можете вызвать это, набрав
$functionName()
eval() — самый простой метод https://www.php.net/manual/en/function.eval.php
$name='new_func';
$var = eval($name."();");
function new_func(){echo "It work";}
Я также искал способ сделать это, так как хотел создать функцию, которая могла бы создавать псевдонимы для функций, прямо как в ruby. например
function an_insanely_long_function_name($a, $b) {
// do something with $a and $b
}
// I'll go insane if I have to type that stupidly long function name every time
// Aliases to the rescue :)
define_alias('shrt_nm', 'an_insanely_long_function_name');
shrt_nm('a', 'b');
Я провел довольно много исследований — около 2 минут :p — и не нашел ничего, что могло бы помочь мне реализовать эту функциональность.
Я уже было собирался сдаться и сделать все вручную, но тут вспомнил старый добрый "eval", мой давний приятель :).
Вот что вам нужно сделать:
function define_alias($alias, $function) {
if (function_exists($alias))
throw new \Exception('A function named ' . $alias . ' already exists!');
// create the function
eval("function $alias(...\$args) { $function(...\$args); }")
}
Я не уверен, что что-то из вышеперечисленного действительно отвечает на вопрос о динамическом создании пользовательских типов сообщений. Хотя это работает для меня:
$languages = ("English", "Spanish", "French");
foreach($languages as $language):
$example = function () use ($language) {
$labels = array(
'name' => __( $language . ' Posts' ),
'singular_name' => __( $language . ' Post' )
);
$args = array(
'labels' => $labels,
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'menu_position' => 5,
"rewrite" => array( "slug" => $language . "_posts", "with_front" => true ),
'capability_type' => 'page',
);
register_post_type( $language . "_posts", $args );
};
add_action( 'init', $example, 0 );
endforeach;