WordPress函数:add_shortcode 创建短代码功能
编辑文章简介
add_shortcode 函数允许你将一段复杂的 PHP 代码逻辑封装成一个简单的标签(如 [myshortcode]),供文章、页面或小工具中的内容调用。它是 WordPress 为用户提供的一种极其友好的扩展内容展示与功能的方式。
语法
此函数定义于 wp-includes/shortcodes.php。它本质上是向全局的 $shortcode_tags 数组注册一个回调函数。
add_shortcode( string $tag, callable $callback ): void
| 参数 | 类型 | 说明 |
|---|---|---|
$tag |
string |
必填。你希望使用的短代码标签(不带方括号)。应使用小写字母、数字和下划线,避免特殊字符和连字符。 |
$callback |
callable |
必填。当 WordPress 在内容中检测到该短代码标签时,将要执行的回调函数。此函数会接收一组参数并返回用于替换短代码的字符串。 |
返回值:无。
该函数内部会调用 $shortcode_tags[ $tag ] = $callback;,将你的标签和函数注册到全局短代码列表中。
用法
基础用法
最常见的场景是创建一个无需参数、直接返回固定或简单动态内容的短代码。通常,我们会在插件的主文件或主题的 functions.php 中注册短代码。
示例:创建一个显示当前年份的短代码
// 将此代码添加到当前主题的 functions.php 文件或自定义插件文件中
if ( ! function_exists( 'render_current_year_shortcode' ) ) {
/**
* 渲染显示当前年份的短代码
* @return string 当前年份的HTML
*/
function render_current_year_shortcode() {
// 使用 date_i18n 支持本地化,而非简单的 date(‘Y’)
return '<span class="current-year">' . date_i18n( 'Y' ) . '</span>';
}
}
add_shortcode( 'current_year', 'render_current_year_shortcode' );
使用方式:在文章编辑器中,只需输入 [current_year],发布后前端就会显示为 <span class="current-year">2023</span>(年份随当前时间变化)。
进阶用法
短代码可以接受属性($atts)和包裹内容($content),用于创建高度动态和交互式的元素。$atts 是用户传入的关联数组,$content 是短代码开始和结束标签之间的内容(仅对闭合短代码有效)。
示例:创建一个可自定义样式和链接的警告框短代码
这个短代码允许用户通过属性设置类型和标题,并包裹需要警示的正文内容。
// 将此代码添加到当前主题的 functions.php 文件或自定义插件文件中
if ( ! function_exists( 'render_alert_box_shortcode' ) ) {
/**
* 渲染警告框短代码
*
* @param array $atts 用户定义的短代码属性。
* @param string $content 短代码包裹的内容(如果短代码是闭合的)。
* @param string $tag 短代码标签(用于共享回调函数的情况)。
* @return string 警告框的HTML。
*/
function render_alert_box_shortcode( $atts = array(), $content = null, $tag = '' ) {
// 1. 使用 shortcode_atts 合并用户输入与默认值,防止未定义索引错误
// 为什么用 shortcode_atts? 它提供了安全的默认值并过滤了无关属性。
$atts = shortcode_atts(
array(
'type' => 'info', // 默认类型为‘信息’
'heading' => '请注意', // 默认标题
),
$atts,
$tag // 传入标签名,可用于过滤器
);
// 2. 对用户输入的内容进行转义和清理(关键安全步骤)
$allowed_html = array(
'a' => array( 'href' => array(), 'title' => array() ),
'br' => array(),
'em' => array(),
'strong' => array(),
);
// wp_kses 比 esc_html 更灵活,允许安全的HTML标签存在。
$cleaned_content = ( ! is_null( $content ) ) ? wp_kses( $content, $allowed_html ) : '';
// 3. 根据类型决定CSS类名
$type_class = esc_attr( $atts['type'] ); // 对输出到HTML属性中的值进行转义
// 4. 构建并返回完整的HTML
$output = '<div class="alert-box alert-' . $type_class . '">';
$output .= '<h4>' . esc_html( $atts['heading'] ) . '</h4>'; // 对标题进行转义
$output .= '<div class="alert-content">' . $cleaned_content . '</div>';
$output .= '</div>';
return $output;
}
}
add_shortcode( 'alert', 'render_alert_box_shortcode' );
使用方式:
* [alert]默认的信息框[/alert]
* [alert type=”warning” heading=”警告!”]这是一个<strong>重要</strong>的警告信息。[/alert]
易错点
- 在匿名函数或类方法中直接使用
add_shortcode
错误示例:add_shortcode( 'test', function() { return ‘test’; } );
在主题的functions.php中这样做,可能会导致主题切换时短代码失效,因为匿名函数无法被序列化存储。最佳做法是使用命名函数或将类方法通过array( $this, ‘method_name’ )形式传递,并在类初始化时注册。
原因:WordPress 的短代码列表存储在全局变量中,主题切换会重新加载函数,但匿名函数引用会丢失。 -
误以为短代码内可直接执行 PHP 代码
用户可能在编辑器中输入[myshortcode]<?php echo ‘hello’; ?>[/myshortcode],期望执行 PHP。WordPress 短代码机制不会执行包裹内容中的 PHP 代码,这些内容只会被当作普通文本字符串传递给回调函数。这是出于核心安全设计。 -
短代码标签命名冲突
使用过于通用的标签名,如,,可能与核心、其他插件或主题已注册的短代码冲突,导致不可预期的行为。在开发插件或主题时,应使用唯一前缀,如[myplugin_video]。 -
忘记对输出进行转义
在回调函数中,如果直接将用户输入的$atts或$content拼接到 HTML 中返回,会存在跨站脚本(XSS)漏洞。必须使用esc_html(),esc_attr(),wp_kses()等函数对输出进行恰当地转义。
最佳实践
命名约定与组织代码
为短代码回调函数使用清晰、带有前缀的命名(如 render_{功能}_shortcode),避免与全局函数冲突。对于拥有多个短代码的复杂插件,建议将每个短代码的回调函数封装在一个独立的类中,通过类的方法来管理,从而提高代码的内聚性和可维护性。
使用输出缓冲处理复杂逻辑
当短代码的回调函数内包含大量HTML或复杂的逻辑(如循环查询多篇文章)时,直接使用字符串拼接会使代码难以阅读和维护。此时,可以启用PHP输出缓冲(ob_start() 和 ob_get_clean()),将HTML以更直观的方式“写”出来。
function render_complex_shortcode( $atts ) {
ob_start();
// 复杂的查询和逻辑...
?>
<div class="complex-output">
<h2><?php echo esc_html( $some_title ); ?></h2>
<p>这是一个更清晰、易于维护的模板化输出方式。</p>
<?php // 更多的PHP逻辑和HTML混合 ?>
</div>
<?php
return ob_get_clean();
}
按需加载前端资源
如果短代码需要特定的CSS或JavaScript文件(如一个轮播图组件),不应直接在回调函数中输出 <script> 或 <link> 标签,也不应在每个页面都全局加载。正确的做法是使用 wp_enqueue_script() 和 wp_enqueue_style(),并将其挂钩到 wp_enqueue_scripts 动作上。为了更精准,可以在短代码回调函数中设置一个标志,然后在 wp_footer 动作中检查该标志来决定是否加载资源,或直接使用 get_shortcode_regex() 检测文章内容中是否使用了该短代码。