【问题标题】:Dynamic function name in phpphp中的动态函数名
【发布时间】:2013-02-06 22:22:27
【问题描述】:

我想简化在 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');

这几乎没问题并且可以标准化,只要我可以动态重命名函数,以便不必在它前面写单词“news”而是使用“$prefix”代替。

这本来可以很好,但不起作用:

$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:我在谷歌上搜索并“stackoverflow”了很多关于此的信息,但没有找到任何适合我需要的有效解决方案并且不会生成 WordPress 错误消息。

谢谢。

【问题讨论】:

    标签: php function dynamic wordpress


    【解决方案1】:

    在 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()来调用它

    【讨论】:

      【解决方案2】:

      我不确定上述任何内容是否真正回答了有关动态创建自定义帖子类型的问题。不过这对我有用:

      $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;
      

      【讨论】:

        【解决方案3】:

        这篇文章很旧,但 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。

        【讨论】:

          【解决方案4】:

          我认为你可以使用

          runkit_function_add

          http://php.net/manual/pl/function.runkit-function-add.php

          另一种可用的方法是使用eval()

          【讨论】:

            【解决方案5】:

            编辑(2017-04):匿名函数(正确实现)是要走的路,请参阅 David Vielhuber 的回答。

            这个答案是不明智的,就像任何涉及将代码作为字符串的方法一样,因为这会邀请(除其他外)连接。


            我不确定它是否值得使用,或者它是否对你有帮助,但是 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 不会返回一个你想要的名字的函数,但是函数的内容会在你的控制之下,函数的真实名字并不重要。

            【讨论】:

            • 谢谢 cernunnos,我要试试这个。我不仅受到这里语言的限制,还受到 WordPress 机制的限制。希望它会工作。我会回复你的。
            • 它不起作用。至少在 WordPress 中没有。它在另一个核心页面上生成错误(致命错误:在 /home/www/xxx/web/admin/wp-includes/rewrite.php 中的非对象上调用成员函数 add_rewrite_tag())。此外,我不相信这是要走的路,因为触发函数的“add_action”需要一个字符串。
            • 就是这样,genetareFunction 返回一个字符串,它不会具有您期望的名称:而不是 $prefix."_customblabla" 它将类似于“lamda_5”,但该名称将保存到变量作为字符串,可以传递给 add_action (它是一个有效的回调,wordpress add_action api 说它接受一个有效的回调)。尝试在代码字符串中添加 die("i dead here") 以查看 wordpress 是否真的到达那里(或 error_log("bla"))
            • @cernunnos 投票反对,因为不再推荐。自 PHP 7.2 起,create_function 将被弃用。请改用匿名函数。唯一的缺点是一旦与匿名函数挂钩,您就无法删除该操作。来自 PHP 文档,“强烈建议不要依赖此函数。”
            • @sampoh 更新了答案,你投反对票是绝对正确的
            【解决方案6】:

            这是一个旧线程,但只是使用匿名函数:

            add_action('init', function() use($args) {
                //...
            });
            

            那么就不用声明这么多函数了。

            【讨论】:

            • 在循环中使用地图创建多个帖子类型时的强大技术。如果帖子类型共享某些功能但与数据层次结构不同并且不应该作为父级等相互耦合,这通常是一个好主意。
            • 如果人们一直在直接调用其他模块的函数,就会出现问题。不是说你应该这样做,但它可能会发生。
            【解决方案7】:

            很简单,这是一个类似的项目截图:

            $function = $prefix . '_custom_type_init';
            if(function_exists($function)) {
              $function();
            }
            

            【讨论】:

            • 我不确定我是否说清楚了(或者我不明白你的意思)。您的脚本检查该函数是否已经存在,为此,该函数应该首先手动创建,对吗?我并不是要动态地“调用”现有函数,我要做的正是动态地“创建”该函数。为了简单起见,在我上面的脚本中,我只想从第一条指令之外的任何地方删除“新闻”一词,并让脚本正常工作。如果我没有得到你,我很抱歉。
            • 如果我理解正确的话,你想要有一些函数,比如“news_something”和“blog_something”等。然后动态调用需要的一个。我提供的代码应该在 init() 中调用并选择要调用的函数。如果您想要从多个位置调用相同的函数,我相信您需要创建函数并让它们调用相同的函数,因为它们需要在 PHP 中注册。
            • 感谢您对 hexbot 的帮助。我编辑了上面的消息,以便通过一个无效的示例更好地理解我的目的。
            猜你喜欢
            • 1970-01-01
            • 2013-07-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多