各位观众,晚上好!我是今天的主讲人,咱们今晚来唠唠 WordPress 里一个相当重要的小家伙——add_shortcode()
函数。别看它名字挺短,作用可不小,它可是短代码(Shortcode)的灵魂人物,负责把你的自定义标签和 PHP 函数联系起来,让你的 WordPress 内容更加灵活。
今天咱们不光要讲怎么用 add_shortcode()
,还要深入它的源码,看看它到底是怎么把这些短代码和处理函数“撮合”到一起的,以及背后藏着哪些精巧的设计。准备好了吗?咱们这就开始!
一、什么是短代码 (Shortcode)?
先给不熟悉短代码的观众老爷们简单科普一下。短代码,顾名思义,就是一段简短的代码,通常用方括号包裹,比如 [my_shortcode]
。它允许你在 WordPress 的文章、页面或者小工具里嵌入复杂的功能,而无需编写大量的 HTML 或者 PHP 代码。
想象一下,你想要在每篇文章的末尾插入一个自定义的作者信息框,包含作者的头像、姓名和简介。如果没有短代码,你可能需要在每个文章的模板里手动添加这段代码,或者使用插件。但有了短代码,你只需要定义一个 [author_info]
短代码,并在文章中插入它,WordPress 就会自动调用相应的 PHP 函数来生成作者信息框。是不是方便多了?
二、add_shortcode()
的基本用法
add_shortcode()
函数的语法很简单:
add_shortcode( string $tag, callable $callback )
$tag
: 短代码的名称,也就是方括号里的内容,比如"my_shortcode"
。$callback
: 一个 PHP 函数或者方法,当 WordPress 遇到这个短代码时,就会调用这个函数来处理它。这个函数必须返回一个字符串,这个字符串将被替换到短代码的位置。
举个栗子:
<?php
/**
* 这是一个处理 [greeting] 短代码的函数
*/
function greeting_shortcode_handler( $atts, $content = null ) {
// $atts 是一个关联数组,包含短代码的属性
// $content 是短代码的内容,如果短代码是封闭的,比如 [greeting]Hello[/greeting],那么 $content 就是 "Hello"
$name = isset( $atts['name'] ) ? esc_attr( $atts['name'] ) : 'World'; // 如果有 name 属性,就用它,否则用 "World"
return '<p>Hello, ' . $name . '!</p>';
}
add_shortcode( 'greeting', 'greeting_shortcode_handler' );
?>
这段代码定义了一个名为 greeting
的短代码,当你在文章中使用 [greeting name="Alice"]
时,WordPress 会调用 greeting_shortcode_handler
函数,并将 name="Alice"
作为 $atts
参数传递给它。函数返回 <p>Hello, Alice!</p>
,这个字符串会替换掉 [greeting name="Alice"]
。
三、add_shortcode()
源码剖析
现在,咱们深入 add_shortcode()
的源码,看看它到底是怎么工作的。add_shortcode()
函数位于 wp-includes/shortcodes.php
文件中。
function add_shortcode( $tag, $callback ) {
global $shortcode_tags;
if ( is_callable( $callback ) ) {
$shortcode_tags[ $tag ] = $callback;
}
}
这段代码的核心就两行:
global $shortcode_tags;
:声明$shortcode_tags
是一个全局变量。$shortcode_tags[ $tag ] = $callback;
:如果$callback
是一个可调用的函数(或者方法),就把它存储到$shortcode_tags
数组里,以$tag
作为键。
关键数据结构:$shortcode_tags
$shortcode_tags
是一个全局数组,它存储了所有已注册的短代码和它们对应的处理函数。它的结构大概是这样的:
$shortcode_tags = array(
'greeting' => 'greeting_shortcode_handler',
'another_shortcode' => 'another_handler',
// ... 更多短代码
);
也就是说,$shortcode_tags
是一个关联数组,键是短代码的名称(比如 "greeting"
),值是对应的处理函数(比如 "greeting_shortcode_handler"
)。
四、短代码的处理流程
当 WordPress 渲染文章内容时,它会调用 do_shortcode()
函数来处理短代码。do_shortcode()
函数会遍历文章内容,查找所有可能的短代码标签,然后根据 $shortcode_tags
数组,找到对应的处理函数,并执行它。
do_shortcode()
函数的源码比较复杂,咱们这里只提取关键部分,进行简化说明:
function do_shortcode( $content ) {
global $shortcode_tags;
if ( false === strpos( $content, '[' ) ) {
return $content; // 如果内容中没有方括号,说明没有短代码,直接返回
}
// 1. 构建短代码的正则表达式
$pattern = get_shortcode_regex();
// 2. 使用正则表达式匹配短代码
preg_match_all( '/' . $pattern . '/s', $content, $matches );
// 3. 遍历所有匹配到的短代码
if ( ! empty( $matches[0] ) ) {
for ( $i = 0; $i < count( $matches[0] ); $i++ ) {
$shortcode = $matches[0][$i]; // 完整的短代码字符串,比如 [greeting name="Alice"]
$tag = $matches[2][$i]; // 短代码的名称,比如 "greeting"
$atts_string = $matches[3][$i]; // 短代码的属性字符串,比如 ' name="Alice"'
$content_inside = $matches[5][$i]; // 封闭短代码的内容,比如 "Hello" (对于 [greeting]Hello[/greeting])
// 4. 查找对应的处理函数
if ( isset( $shortcode_tags[ $tag ] ) && is_callable( $shortcode_tags[ $tag ] ) ) {
$callback = $shortcode_tags[ $tag ];
// 5. 解析属性字符串为关联数组
$atts = shortcode_parse_atts( $atts_string );
// 6. 调用处理函数,并替换短代码
$replace_with = call_user_func( $callback, $atts, $content_inside, $tag );
$content = str_replace( $shortcode, $replace_with, $content );
}
}
}
return $content;
}
简单概括一下 do_shortcode()
的流程:
- 检查是否存在短代码: 如果文章内容中没有
[
符号,就直接返回,避免不必要的处理。 - 构建正则表达式: 使用
get_shortcode_regex()
函数生成一个用于匹配短代码的正则表达式。这个正则表达式可以匹配各种形式的短代码,包括自闭合的和封闭的。 - 匹配短代码: 使用
preg_match_all()
函数,根据正则表达式,在文章内容中查找所有匹配的短代码。 - 遍历匹配结果: 遍历所有匹配到的短代码,提取短代码的名称、属性和内容。
- 查找处理函数: 在
$shortcode_tags
数组中查找与短代码名称对应的处理函数。 - 解析属性: 使用
shortcode_parse_atts()
函数将属性字符串解析为关联数组。 - 调用处理函数: 使用
call_user_func()
函数调用处理函数,并将属性数组和内容作为参数传递给它。 - 替换短代码: 将文章内容中的短代码替换为处理函数返回的字符串。
五、短代码属性的处理:shortcode_parse_atts()
shortcode_parse_atts()
函数负责将短代码的属性字符串解析为关联数组。例如,对于 [greeting name="Alice" age=30]
,它会返回:
array(
'name' => 'Alice',
'age' => '30'
)
shortcode_parse_atts()
函数的源码也比较复杂,这里只给出简化的说明:
function shortcode_parse_atts( $text ) {
$atts = array();
$pattern = '/(w+)s*=s*"([^"]*)"(?:s|$)|(w+)s*=s*'([^']*)'(?:s|$)|(w+)s*=s*([^s'"]+)(?:s|$)|"([^"]*)"(?:s|$)|(S+)(?:s|$)/';
$text = preg_replace( "/[x00-x20x7f-xff]+/", ' ', $text );
$text = trim( $text );
if ( empty( $text ) ) {
return $atts;
}
preg_match_all( $pattern, $text, $match, PREG_SET_ORDER );
foreach ( $match as $m ) {
if ( ! empty( $m[1] ) ) {
$atts[ strtolower( $m[1] ) ] = stripcslashes( $m[2] );
} elseif ( ! empty( $m[3] ) ) {
$atts[ strtolower( $m[3] ) ] = stripcslashes( $m[4] );
} elseif ( ! empty( $m[5] ) ) {
$atts[ strtolower( $m[5] ) ] = stripcslashes( $m[6] );
} elseif ( ! empty( $m[7] ) ) {
$atts[] = stripcslashes( $m[7] );
} elseif ( isset( $m[8] ) ) {
$atts[] = stripcslashes( $m[8] );
}
}
return $atts;
}
这个函数使用正则表达式来匹配属性,并处理各种引号和转义情况,最终返回一个关联数组,方便短代码的处理函数使用。
六、短代码的进阶用法
除了基本用法,短代码还有一些更高级的用法,比如:
-
嵌套短代码: 允许在一个短代码中使用另一个短代码。例如:
[outer_shortcode] [inner_shortcode] Content [/inner_shortcode] [/outer_shortcode]
要处理嵌套短代码,需要在处理函数中递归调用
do_shortcode()
函数。 -
自闭合短代码: 像 HTML 标签一样,短代码也可以是自闭合的,比如
[my_shortcode /]
。 -
短代码属性的默认值: 可以在处理函数中为属性设置默认值,如果短代码中没有指定该属性,就使用默认值。
-
移除短代码: 可以使用
remove_shortcode()
函数移除已注册的短代码。
七、使用场景案例分析
为了更好地理解短代码的用法,我们来看几个实际的使用场景:
场景 | 短代码名称 | 处理函数 | 描述 |
---|---|---|---|
显示当前年份 | current_year |
current_year_shortcode_handler |
在文章中插入当前年份。 |
显示友情链接 | friend_links |
friend_links_shortcode_handler |
显示一组友情链接,可以指定链接的数量和排序方式。 |
显示自定义的广告位 | ad_space |
ad_space_shortcode_handler |
根据指定的广告位 ID,显示对应的广告。 |
创建可折叠的内容区域(手风琴) | accordion 和 item |
accordion_shortcode_handler 和 item_shortcode_handler |
使用嵌套的短代码,创建一个可折叠的内容区域,每个 item 代表一个折叠项。 |
显示特定分类的文章列表 | category_posts |
category_posts_shortcode_handler |
显示指定分类的文章列表,可以指定文章的数量、排序方式和显示格式。 |
八、总结与建议
add_shortcode()
函数是 WordPress 中一个非常重要的函数,它允许开发者自定义标签,并在文章、页面或者小工具中嵌入复杂的功能。通过深入理解 add_shortcode()
的源码和短代码的处理流程,我们可以更好地利用短代码来扩展 WordPress 的功能,提高开发效率。
几点建议:
- 避免滥用短代码: 短代码虽然方便,但是过多的短代码会影响文章的可读性和性能。尽量将常用的功能封装成插件,而不是使用大量的短代码。
- 注意短代码的安全性: 短代码的处理函数应该进行输入验证和过滤,防止 XSS 攻击。
- 使用有意义的短代码名称: 短代码的名称应该具有描述性,方便用户理解和使用。
- 为短代码提供详细的文档: 编写清晰的文档,说明短代码的用法和属性,方便用户使用。
今天的讲座就到这里。希望大家通过今天的学习,对 WordPress 的 add_shortcode()
函数有了更深入的了解。感谢大家的观看!如果有什么问题,欢迎在评论区留言,咱们一起探讨。下次再见!