大家好!欢迎来到今天的WordPress源码深度解析讲座,我是你们的老朋友(虽然可能是第一次见),今天要聊聊WordPress里一个非常实用、但有时候又让人有点摸不着头脑的家伙:shortcode
。
别怕,shortcode其实就是WordPress提供的一个小工具,让你能在文章、页面甚至小工具里嵌入一些动态内容,而不用写一堆复杂的PHP代码。 今天我们就来扒一扒它的皮,重点解析add_shortcode()
和do_shortcode()
这两个核心函数的工作原理。
Shortcode:让你的文章不再单调
想象一下,你想在文章里插入一个幻灯片,或者一个订阅表单。如果没有shortcode,你可能需要修改主题文件,或者使用复杂的插件。但是有了shortcode,你只需要在文章里写一个像[myslideshow]
这样的标签,WordPress就会自动把它替换成幻灯片的HTML代码。是不是很方便?
add_shortcode()
:注册你的专属标签
首先,我们来看看add_shortcode()
函数。它的作用就像给WordPress注册一个新的短代码标签。语法很简单:
add_shortcode( string $tag, callable $callback )
$tag
: 这是你想要使用的短代码标签的名字,比如'myslideshow'
,'subscribeform'
等等。$callback
: 这是一个回调函数,当WordPress遇到你的短代码标签时,它会调用这个函数来生成最终的HTML代码。
举个例子,假设我们要创建一个简单的短代码,用来显示当前年份:
function my_current_year_shortcode() {
return date('Y');
}
add_shortcode('currentyear', 'my_current_year_shortcode');
这段代码的意思是:
- 我们定义了一个名为
my_current_year_shortcode()
的函数,它返回当前的年份。 - 我们使用
add_shortcode()
函数将'currentyear'
这个标签与my_current_year_shortcode()
函数关联起来。
现在,你就可以在文章里写[currentyear]
,WordPress会自动把它替换成当前的年份。
深入add_shortcode()
源码
add_shortcode()
函数本身的代码并不复杂,它主要做的事情就是把标签和回调函数存储到一个全局变量里。我们来看一下它的简化版:
global $shortcode_tags;
if ( ! isset( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
$shortcode_tags = array();
}
$shortcode_tags[ $tag ] = $callback;
这段代码做了以下几件事:
- 声明全局变量
$shortcode_tags
。$shortcode_tags
是一个数组,用来存储所有注册的短代码标签和对应的回调函数。 - 检查
$shortcode_tags
是否已经存在,如果不存在,就初始化一个空数组。 - 将
$tag
和$callback
存储到$shortcode_tags
数组中。
简单来说,add_shortcode()
就是一个注册表,把你的短代码标签和处理它的函数登记在案。
do_shortcode()
:找到标签,执行回调
接下来,我们来看看do_shortcode()
函数。它的作用是扫描一段文本,找到所有的短代码标签,然后调用相应的回调函数来替换它们。
do_shortcode( string $content ) : string
$content
: 这是你要扫描的文本,通常是文章的内容。- 返回值: 替换了所有短代码标签后的文本。
举个例子,假设你的文章内容是:"今天天气真好![currentyear]年真是个好年份!"
,那么调用do_shortcode()
后,它会变成"今天天气真好!2023年真是个好年份!"
(假设现在是2023年)。
深入do_shortcode()
源码
do_shortcode()
函数的源码比较复杂,因为它需要处理各种情况,例如嵌套的短代码、带有属性的短代码等等。我们来看一下它的简化版,重点关注它是如何找到标签并执行回调的:
global $shortcode_tags;
if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
return $content; // 没有注册任何短代码,直接返回
}
$pattern = get_shortcode_regex(); // 获取用于匹配短代码的正则表达式
return preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
这段代码做了以下几件事:
- 检查全局变量
$shortcode_tags
是否为空,如果为空,说明没有注册任何短代码,直接返回原始文本。 - 调用
get_shortcode_regex()
函数获取用于匹配短代码的正则表达式。 - 使用
preg_replace_callback()
函数,根据正则表达式查找文本中的短代码标签,并调用do_shortcode_tag()
函数来处理每一个匹配到的短代码标签。
get_shortcode_regex()
:正则表达式的艺术
get_shortcode_regex()
函数的作用是生成一个用于匹配短代码的正则表达式。这个正则表达式需要能够匹配各种形式的短代码,例如:
[currentyear]
[myslideshow id="123"]
[subscribeform title="订阅"]内容[/subscribeform]
这个函数的代码比较复杂,我们就不在这里展开了。但是你需要知道的是,它生成了一个强大的正则表达式,可以处理各种复杂的短代码形式。
do_shortcode_tag()
:真正干活的函数
do_shortcode_tag()
函数是真正干活的函数。它接收 preg_replace_callback()
函数传递过来的匹配结果,然后根据标签名找到对应的回调函数,并执行它。我们来看一下它的简化版:
global $shortcode_tags;
$tag = $matches[2]; // 获取标签名
$atts = shortcode_parse_atts( $matches[3] ); // 解析属性
$content = $matches[5]; // 获取短代码的内容(如果有)
if ( isset( $shortcode_tags[ $tag ] ) ) {
$callback = $shortcode_tags[ $tag ]; // 获取回调函数
if ( is_callable( $callback ) ) {
return call_user_func( $callback, $atts, $content, $tag ); // 执行回调函数
}
}
return $matches[0]; // 如果没有找到对应的回调函数,则返回原始的短代码标签
这段代码做了以下几件事:
- 从
$matches
数组中获取标签名、属性和内容。$matches
数组是preg_replace_callback()
函数传递过来的匹配结果。 - 使用
shortcode_parse_atts()
函数解析属性。 - 从
$shortcode_tags
数组中查找与标签名对应的回调函数。 - 如果找到了回调函数,并且它是一个可调用的函数,则使用
call_user_func()
函数执行它,并将属性、内容和标签名作为参数传递给它。 - 如果找不到对应的回调函数,则返回原始的短代码标签。
Shortcode的属性(Attributes)
Shortcode可以带属性,就像HTML标签一样。例如:[myslideshow id="123" width="600"]
。在你的回调函数中,你可以通过 $atts
参数来访问这些属性。
function my_slideshow_shortcode( $atts ) {
$atts = shortcode_atts(
array(
'id' => '1',
'width' => '400',
),
$atts,
'myslideshow'
);
$id = intval( $atts['id'] );
$width = intval( $atts['width'] );
// 根据 $id 和 $width 生成幻灯片的 HTML 代码
$html = '<div class="slideshow" style="width: ' . $width . 'px;">';
$html .= '幻灯片ID:' . $id;
$html .= '</div>';
return $html;
}
add_shortcode('myslideshow', 'my_slideshow_shortcode');
在这个例子中,我们使用了 shortcode_atts()
函数来定义默认的属性值,并且将用户传入的属性值合并到默认值中。shortcode_atts()
函数可以确保你的代码在没有指定属性值时也能正常工作。
嵌套的Shortcode
Shortcode可以嵌套,就像HTML标签一样。例如:
[outer]
[inner]Inner Content[/inner]
[/outer]
要处理嵌套的shortcode,你需要在你的回调函数中递归调用do_shortcode()
函数。
function outer_shortcode( $atts, $content = null ) {
$content = do_shortcode($content); // 处理嵌套的 shortcode
return '<div class="outer">' . $content . '</div>';
}
add_shortcode('outer', 'outer_shortcode');
function inner_shortcode( $atts, $content = null ) {
return '<div class="inner">' . $content . '</div>';
}
add_shortcode('inner', 'inner_shortcode');
在这个例子中,outer_shortcode()
函数调用了 do_shortcode()
函数来处理 $content
变量中的嵌套的 shortcode。
Shortcode的优先级
如果你注册了多个 shortcode,它们可能会发生冲突。WordPress 允许你通过调整 shortcode 的优先级来解决冲突。但是默认情况下,所有 shortcode 的优先级都是 10。你可以使用 remove_shortcode()
函数来移除一个 shortcode,然后再使用 add_shortcode()
函数来重新注册它,并指定一个新的优先级。
Shortcode的安全问题
Shortcode 可能会带来安全问题,因为它们允许用户在文章中执行代码。为了避免安全问题,你应该始终对用户输入进行验证和过滤,并且避免在 shortcode 中执行敏感操作。
总结
add_shortcode()
和 do_shortcode()
是 WordPress 短代码功能的核心。add_shortcode()
函数用于注册短代码标签和对应的回调函数,而 do_shortcode()
函数用于扫描文本,找到短代码标签,并调用相应的回调函数来替换它们。了解这两个函数的工作原理,可以帮助你更好地使用 WordPress 的短代码功能,并且避免一些常见的错误。
一个表格总结 add_shortcode() 和 do_shortcode()
函数名 | 作用 | 参数 | 返回值 |
---|---|---|---|
add_shortcode() |
注册一个短代码标签和对应的回调函数 | $tag (string): 短代码标签名,例如 ‘currentyear’。$callback (callable): 处理短代码的回调函数。这个函数接收三个参数:$atts (array): 短代码的属性,如果没有属性,则为空数组。$content (string): 短代码的内容,如果有的话。如果没有内容,则为 null。$tag (string): 短代码的标签名。 |
无 |
do_shortcode() |
扫描文本,找到短代码标签,并调用相应的回调函数来替换它们 | $content (string): 要扫描的文本。 |
$content (string): 替换了所有短代码标签后的文本。如果没有找到任何短代码标签,则返回原始的文本。 |
一些使用建议
- 命名规范: 给你的短代码标签起一个有意义的名字,避免和其他插件或主题的短代码冲突。
- 属性默认值: 使用
shortcode_atts()
函数来定义属性的默认值,确保你的代码在没有指定属性值时也能正常工作。 - 安全第一: 对用户输入进行验证和过滤,避免安全问题。
- 性能优化: 避免在短代码中执行耗时的操作,例如数据库查询。
好了,今天的讲座就到这里。希望通过今天的讲解,大家对 WordPress 的 shortcode 有了更深入的了解。记住,shortcode 是一个强大的工具,但是也要谨慎使用。 下次有机会再和大家分享其他的WordPress源码知识! 祝大家编程愉快!