PHP中将类WordPress短代码的字符串解析为数组的问题
问题
我正在使用Laravel开发一款页面构建器,尝试实现类WordPress风格的短代码功能。现有如下HTML字符串:
$string = '<div class="temp"> [title type="text" tag="h2" value="This is my cool title" disabled some-attribute] [text type="text" tag="p" value="Lorem ipsum dolor sit amet"] </div>';
目标是提取所有方括号内的短代码,转换为如下格式的数组:
[ [ "id" => "title", "type" => "text", "tag" => "h2", "value" => "This is my cool title", "disabled" => true, "some-attribute" => true ], [ "id" => "text", "type" => "text", "tag" => "p", "value" => "Lorem ipsum dolor sit amet" ] ]
但现有代码通过explode(' ', $match)按空格拆分短代码时,会把引号内的空格也当作分隔符,导致结果混乱:
// Extract all brackets from the string preg_match_all('/(?<=\[)[^\][]*(?=])/', $string, $matches); $itemsArray = array(); // Explode each shortcode by spaces foreach ($matches[0] as $match) { $shortcode = explode( ' ', $match ); $itemArray = array(); // split shortcode in attributes foreach ($shortcode as $key => $attr) { $temp = explode('=', $attr); // First attribute is the id if ($key === 0) { $itemArray['id'] = $temp[0]; } else { if ( count($temp) > 1 ) { $itemArray[ $temp[0] ] = trim($temp[1],'"'); } else { $itemArray[ $temp[0] ] = true; } } } $itemsArray[] = $itemArray; }
错误输出结果:
[ [ "id" => "title" "type" => "text" "tag" => "h2" "value" => "This" "is" => true "my" => true "cool" => true "title"" => true "disabled" => true "some-attribute" => true ], [ "id" => "text" "type" => "text" "tag" => "p" "value" => "Lorem" "ipsum" => true "dolor" => true "sit" => true "amet"" => true ] ]
需要解决:如何拆分短代码时忽略引号内的空格?
解决方案
核心思路是放弃用explode按空格拆分,改用正则表达式精准匹配每个属性项,包括带空格的引号内值。修正后的代码如下:
// 提取所有方括号内的短代码内容 preg_match_all('/(?<=\[)[^\][]*(?=])/', $string, $matches); $itemsArray = []; foreach ($matches[0] as $match) { $itemArray = []; // 提取短代码ID(开头的标识) preg_match('/^\w+/', $match, $idMatch); $itemArray['id'] = $idMatch[0]; // 匹配所有属性:支持 key="value(含空格)" 和 standalone-attr 两种格式 preg_match_all('/(\w+-?\w+)(?:="([^"]*)")?/', $match, $attrMatches, PREG_SET_ORDER); foreach ($attrMatches as $attr) { // 跳过已经提取的ID项 if ($attr[1] === $itemArray['id']) { continue; } // 有值则赋值,无值则设为true if (isset($attr[2])) { $itemArray[$attr[1]] = $attr[2]; } else { $itemArray[$attr[1]] = true; } } $itemsArray[] = $itemArray; } // 输出验证结果 print_r($itemsArray);
关键逻辑说明
- 提取短代码ID:用
/^\w+/匹配短代码开头的标识(比如title、text)。 - 匹配属性的正则:
/(\w+-?\w+)(?:="([^"]*)")?/(\w+-?\w+):匹配属性名,支持带连字符的格式(如some-attribute)。(?:="([^"]*)")?:可选的属性值部分,[^"]*会匹配双引号内的所有内容(包括空格),不会被空格打断。
- 处理属性:遍历匹配到的属性,跳过ID项,有值则直接赋值,无值的独立属性设为
true。
运行这段代码后,就能得到符合预期的数组结构,正确保留引号内的空格内容。
内容的提问来源于stack exchange,提问作者AlexThunder
相关产品推荐
相关产品推荐

