当您在简码中包含简码时,将do_shortcode()替换为直接函数

时间:2019-02-16 19:23:04

标签: php wordpress shortcode

我试图避免使用do_shortcode(),而是想用函数本身代替它。我遇到的问题是封闭的shortcode标记。使用该功能如何实现?

重写:

echo do_shortcode( "
[membership level='12,41']
[get_biddata type='pending' sport='MLB Baseball']
[/membership]
    " );

与此:

echo pmpro_shortcode_membership( array( 'level' => '12,41', 'levels' => NULL, 'delay' => NULL ), $atts);
echo ajax_member_support( array( 'sport' => 'MLB Baseball', 'type' => 'pending' ), $atts );

此函数中包含什么参数:

echo pmpro_shortcode_membership();  替换为:[/membership]结尾的简码标记?

有3个插件:

1)付费会员-短代码标签= [membership] [/membership]

简码回调函数名称:pmpro_shortcode_membership()

2)bidsys-短代码标签= [get_biddata]

简码回调函数名称:ajax_member_support()

3)我自己的自定义插件可以为在文件中使用do_shortcode的网站创建简码。

我难以对调用进行硬编码以摆脱do_shortcode()的问题。仅当包裹在[membership] [/membership]标记中时,它才能正常工作。

适合我的特殊情况的

来自ArtisticPhoenix的答案/代码:

echo pmpro_shortcode_membership(
   array( 'level' => '12,41', 'levels' => NULL, 'delay' => NULL ),
   ajax_member_support( array( 'sport' => 'MLB Baseball', 'type' => 'pending' ))
);

1 个答案:

答案 0 :(得分:0)

请勿重写do_shortcode

这就是答案……简而言之。

在这里,我假设您的帖子是这样的

 [myshortcode]
     [membership level='12,41']
         [get_biddata type='pending' sport='MLB Baseball']
     [/membership]
 [/myshortcod]

对我来说,这是唯一有意义的事情。因为如果您有

[membership level='12,41']
    [get_biddata type='pending' sport='MLB Baseball']
[/membership]

您的短代码为membership,那么如果您在上面调用do_shortcode,则将获得无限递归(或者至少会运行2x成员身份)。我很确定wordpress会删除当前的shortcodes标签,并用该shortcodes函数的返回值替换它们……否则这将是一个主要问题。但是目前尚不清楚您使用的是什么短代码,以及您尝试在短代码中包括哪些短代码。

此外,如果您在WP文档中查找随附的简短代码HERE

没有提及删除当前简码的结束标记。如您所说,让我感到困惑:

  

[这里是会员短代码的功能:

哪个使人相信[membership]会调用该函数,然后您尝试对同一简码do_shortcode执行[membership ...]。这对我来说真的不明智。

先发

(通常)这样编写短代码:

 function foo($atts, $content)  // array, string

不是

 function foo($myarray, $atts) //array, array

因此,当您致电:

 echo pmpro_shortcode_membership(
           array( 'level' => '12,41', 'levels' => NULL, 'delay' => NULL ),
            $atts
 );

我以为这是短代码的开头,参数是错误的...

现在,让我解释一下(上面的答案,不要重做do_shortcode)。

如果您对此进行硬编码而不是:

[membership level='12,41']
   [get_biddata type='pending' sport='MLB Baseball']
[/membership]

您获得(作为$ contents)

[membership level='13,41']  //note the 13,14 not 12,14
   [get_biddata type='pending' sport='MLB Baseball']
[/membership]

由于您无法在代码中准予这种情况,因此必须对此进行说明。为此,您必须自己解析简码(以获取level属性),do_shortcode就是这样做的。

另外,我们假设此短代码membership添加了一些

之类的HTML。
  <div>
        [get_biddata type='pending' sport='MLB Baseball']
  </div>

另一个get_biddata的作用类似于

   <a href="example.com" >Click</a>

因为第二个(上面的)嵌套在另一个获得的简码中

  <div>
        <a href="example.com" >Click</a>
  </div>

如果您一个接一个地运行它们(如您尝试的那样)

   <div>

   </div>
   <a href="example.com" >Click</a>

此HTML可能比简单的<div>复杂得多。因此,结尾的简码确实是最少的问题。

也许这不是您的情况,但不值得重新发明do_shortcode来节省几微秒的时间(充其量,也许您自己解析后还会更糟)。

更不用说这是一个试图解析的雷区,因为需要递归等。

最后

如果您只想在所有对短代码的调用中都包含此功能,则可以对这些方法的调用进行硬编码(并将它们完全排除在后)

如果您应该执行其他操作,则可以打开将哪些属性传递给您的短代码,但这取决于您。

//do your code like this (in the post):
//    [myshortcode sport='foo' level='12,41']
//instead of like this
//   [myshortcode][membership level='12,41'] ... [/myshortcode]

echo pmpro_shortcode_membership(
     array( 'level' => '12,41', 'levels' => NULL, 'delay' => NULL ),
     "[get_biddata type='pending' sport='MLB Baseball']"
);

如上所示,您仍然可以将内部简码作为简码传递给第一个方法/函数。以便将其放置在任何HTML中的正确位置。这确实允许您在构造该短代码时使用自己的属性。

例如:

//$atts['sport'] could come from your shortcode Attributes (as shown above).
echo pmpro_shortcode_membership(
     array( 'level' => $attr['level'], 'levels' => NULL, 'delay' => NULL ),
     "[get_biddata type='pending' sport='{$atts['sport']}']"
);

您也可以这样操作(通过将内层的结果作为内容传递到外层的结果),并避免使用do_shortcode

echo pmpro_shortcode_membership(
   array( 'level' => $attr['level'], 'levels' => NULL, 'delay' => NULL ),
   ajax_member_support( array( 'sport' => 'MLB Baseball', 'type' => 'pending' ))
);

基本上先执行ajax_member_support,然后将其内容放入外部简码的$contents中。在此示例中,此方法有效,但是如果嵌套更深,您将遇到一些问题...

但是,如果您执行上述操作(在本“部分”中),则您不应允许其他短代码嵌套在您的短代码中。相反,您应该将它们的参数作为自己的短代码的一部分传递。如果您将这些属性作为短码的一部分(无论是哪种话)piggy带,这将使生活更加轻松,并避免了很多问题。

希望如此。

最后一件事(那有点困扰我)

这段代码:

  if(!empty($level) || $level === "0" || $level === 0)
  //if level is not empty, or it is string '0' or just 0

可以简化,因为我们知道从shortcode属性只能传递字符串。因此,代替这些东西:

  if(strlen($level))
     //empty (such as null) is 0, but string '0' and 0 are strlen 1.

为了说明这一点,我们不能以这样的短代码传递数组

[membership level="[3,4]"]

因为它只是一个字符串[3,4]。您知道的(因为您必须从字符串中解析级别),但是可能没有意识到。因此,现在我们同意只能通过短代码传递字符串,我们可以对此进行测试:

echo strlen(0)."\n";
echo strlen('0')."\n";
echo strlen(false)."\n";
echo strlen(null)."\n";

输出

1 //strlen(0)
1 //strlen('0')
0 //strlen(false)
0 //strlen(null)

Sandbox

显而易见,strlen('')也是0。而且,如果未设置级别,则由于您“正确”使用了shortcode_atts,因此它将默认为NULL(因此,我们不必担心未定义/未设置)。因此,这两段代码大致相同,只是其中一段较短。

这似乎有点“怪异”,但是如果我们知道我们只需要处理基元(非数组,非对象)并且可以保证将其设置(这里就是这种情况)。比strlen应该还好。

干杯!

更新

对于2个以上的简码,您将继续将函数嵌套到父代的内容中:

echo pmpro_shortcode_membership(
   array( 'level' => $attr['level'], 'levels' => NULL, 'delay' => NULL ),
   ajax_member_support(
          array( 'sport' => 'MLB Baseball', 'type' => 'pending' ),
          some_other_shortcode(
              ['foo'=>'bar'],
              some_other_shortcode_1(
                   ['biz'=>'baa'],
                    ......
               )
          )
   )
);

依次类推,最里面的函数首先执行,并且可能返回某种字符串,然后将该字符串传递给父函数。因为父函数正在使用此内容通过$content = do_shortcode($content)查找其他短代码。当在父函数中调用该函数时,原本应该是已执行的简码的内容在调用它之前就已经完成了。但是do_shortcode将返回文本,即使那里没有简码(因为它已经完成了)。因此,如果没有事先完成,它应该在应该去的地方。

基本上,您只是在向它提供从do_shortcode获得的内容,因此一切正常(在大多数情况下)。