不要重写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 会删除当前的短代码标签并将它们替换为该短代码函数的返回值......否则这将是一个主要问题。但目前尚不清楚您的简码是什么,以及您试图在简码中包含哪些简码。
另外,如果您在 WP 文档中查看随附的短代码 HERE
没有提到删除当前短代码的结束标记。正如你所说,我很困惑:
[这里是]会员简码的功能:
这导致人们相信[membership] 调用了该函数,然后您尝试在同一短代码[membership ...] 上执行do_shortcode。这对我来说不是很明智。
首发
短代码(通常)是这样编写的:
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中。这在本示例中有效,但如果嵌套更深,您将遇到一些问题...
但是,如果您执行上述操作(在此“部分”中),则不应允许将其他短代码嵌套在您的短代码中。相反,您应该将他们的参数作为您自己的简码的一部分传递。如果您将这些属性作为简码的一部分(无论是什么),它将使生活变得更轻松并防止很多问题......
希望这是有道理的。
最后一件事(这有点困扰我)
这段代码:
if(!empty($level) || $level === "0" || $level === 0)
//if level is not empty, or it is string '0' or just 0
可以简化,因为我们知道只能从短代码属性传递字符串。所以代替那些东西:
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 获得的内容,因此一切正常(在大多数情况下)。