首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 正則替換回調內容標籤實作 (WordPress Shortcode 風格)

     編輯:PHP 綜合知識

應用場景

內容管理系統中常需支援類似 WordPress Shortcode 的標籤語法:[gallery ids="1,2,3"]、[contact-form id="5"]。核心需求:正則匹配標籤 → 提取屬性 → 呼叫對應處理函式 → 替換回內容。

核心實作

<?php
function my_wp_plugin_tag_action($content, $tag, $function, $args = false) {
    // 1. 正則匹配所有目標標籤
    // $tag 範例:'/\[gallery\s+([^\]]*)\]/' 捕獲屬性部分
    preg_match_all($tag, $content, $matches);
    
    if (count($matches) > 0) {
        // 2. 去重 (避免同一標籤重複處理)
        $matches = array_unique($matches[0]); // 取完整匹配 (index 0)
        
        $tag_results = array();
        $found_tags = array();
        
        // 3. 逐個處理
        foreach ($matches as $idx => $full_tag) {
            // 解析屬性字串為陣列 (簡易版,實際建議用 shortcode_parse_atts)
            $attrs = shortcode_parse_atts($full_tag); // 需自行實作或引入 WP 核心函式
            
            // 呼叫處理函式
            $result = call_user_func($function, $attrs, $full_tag);
            
            $tag_results[] = $result;
            $found_tags[] = $full_tag;
        }
        
        // 4. 批次替換
        $content = str_replace($found_tags, $tag_results, $content);
    }
    
    return $content;
}

// 屬性解析輔助函式 (簡化版)
function shortcode_parse_atts($tag) {
    $pattern = '/(\w+)\s*=\s*"([^"]*)"/';
    preg_match_all($pattern, $tag, $m);
    return array_combine($m[1], $m[2]);
}

使用範例

// 1. 定義處理函式
function handle_gallery($attrs, $full_tag) {
    $ids = explode(',', $attrs['ids'] ?? '');
    $html = '<div class="gallery">';
    foreach ($ids as $id) {
        $html .= '<img src="/wp-content/uploads/' . trim($id) . '.jpg" />';
    }
    $html .= '</div>';
    return $html;
}

function handle_contact_form($attrs, $full_tag) {
    return '<form action="/contact" method="post">...</form>';
}

// 2. 內容處理流程
$content = '
歡迎來到相簿:
[gallery ids="101,102,103"]

聯繫我們:
[contact-form id="5"]
';

// 3. 依序處理各標籤類型
$content = my_wp_plugin_tag_action($content, '/\[gallery\s+([^\]]*)\]/', 'handle_gallery');
$content = my_wp_plugin_tag_action($content, '/\[contact-form\s+([^\]]*)\]/', 'handle_contact_form');

echo $content;

進階增強:統一標籤註冊機制

class ShortcodeProcessor {
    private $tags = array();
    
    public function register($tagName, $callback) {
        // 自動建立正則:[tagName attrs...]
        $this->tags[$tagName] = '/\[' . $tagName . '\s+([^\]]*)\]/';
        $this->callbacks[$tagName] = $callback;
    }
    
    public function process($content) {
        foreach ($this->tags as $name => $regex) {
            $content = $this->replaceTags($content, $regex, $this->callbacks[$name]);
        }
        return $content;
    }
    
    private function replaceTags($content, $regex, $callback) {
        preg_match_all($regex, $content, $matches);
        if (empty($matches[0])) return $content;
        
        $replacements = array();
        foreach ($matches[0] as $fullTag) {
            $attrs = $this->parseAtts($fullTag);
            $replacements[$fullTag] = call_user_func($callback, $attrs, $fullTag);
        }
        return strtr($content, $replacements); // strtr 比 str_replace 更安全
    }
    
    private function parseAtts($tag) {
        // 完整支援:單引號、雙引號、無引號、布林屬性
        $pattern = '/(\w+)\s*=\s*(?:"([^"]*)"|\'([^\']*)\'|(\S+))/';
        preg_match_all($pattern, $tag, $m, PREG_SET_ORDER);
        $attrs = array();
        foreach ($m as $match) {
            $attrs[$match[1]] = $match[2] ?? $match[3] ?? $match[4] ?? true;
        }
        return $attrs;
    }
}

// 使用
$processor = new ShortcodeProcessor();
$processor->register('gallery', 'handle_gallery');
$processor->register('contact-form', 'handle_contact_form');
$processor->register('video', function($attrs) {
    return '<video src="' . ($attrs['src'] ?? '') . '" controls></video>';
});

$output = $processor->process($content);

關鍵設計決策

決策點選擇理由
正則邊界 \[tag\s+([^\]]*)\] 不支援巢狀標籤,簡化解析邏輯
屬性解析 支援雙引號/單引號/無引號 相容多種寫作習慣
替換策略 收集後批次 strtr 避免替換結果被二次匹配、保持順序
錯誤處理 回調拋出異常時保留原標籤 不讓單一標籤錯誤破壞整頁內容

效能建議

  • 大量內容時,考慮編譯正則快取 (static $compiled = [])
  • 標籤處理函式應為純函式,避免副作用
  • 支援巢狀標籤需改用遞迴下降解析器,正則無法正確處理

此模式廣泛應用於 CMS、部落格系統、郵件模板引擎,掌握其核心機制可靈活擴展各類動態內容標籤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved