Динамическое имя функции в 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;
Другие вопросы по тегам