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() 检测文章内容中是否使用了该短代码。