如何将preg_replace匹配变量$2传入getYoutubeVideoID函数
问题解决:PHP中preg_replace捕获组无法传入自定义函数的问题
问题场景
现有两个PHP函数:bbc2html用于将BBCode转换为HTML,getYoutubeVideoID用于从YouTube链接中提取视频ID。在处理[youtube]标签时,尝试将preg_replace匹配到的链接(捕获组$2)传入getYoutubeVideoID,但实际传入的是字符串'$2',无法得到正确的视频ID。
原函数代码:
function bbc2html($content) { $search = array ( '/(\[b\])(.*?)(\[\/b\])/', '/(\[u\])(.*?)(\[\/u\])/', '/(\[i\])(.*?)(\[\/i\])/', '/(\[youtube\])(.*?)(\[\/youtube\])/' ); $replace = array ( '<b>$2</b>', '<u>$2</u>', '<i>$2</i>', '<div class="video_wrapper card border-0 shadow text-center m-2" style="width: 25rem;"> <div class="video_trigger card-body" data-source="'.getYoutubeVideoID('$2').'" data-type="youtube"> <p class="text-center">As soon as you click on the button you accept that cookies from YouTube to be loaded</p> <input type="button" class="btn btn-success" value="OK"> <a href="$2" type="button" target="_blank" class="btn btn-danger"><i class="fa-brands fa-youtube pe-1"></i>direct link</a> </div> <div class="video_layer" style="display: none;"> <iframe src="" border="0" data-scaling="true" data-format="16:9" style="height: 0px;"></iframe> </div> </div>' ); return preg_replace($search, $replace , $content); }
function getYoutubeVideoID($link):string{ $baseUrl = parse_url($link, PHP_URL_HOST); if($baseUrl == "youtu.be"){ $urlParts = explode('/',$link); $id = end($urlParts); } elseif (preg_match('/(youtube.com)/i',$baseUrl)) { if(preg_match('/(youtube.com\/watch\?v=)/i',$link)){ $urlParts = explode('?v=',$link); $id = end($urlParts); } elseif(preg_match('/(youtube.com\/)/i',$link)) { $urlParts = explode('/',$link); $id = end($urlParts); } else { return ""; } } else { return ""; } return $id; }
解决方法
preg_replace的替换字符串无法直接执行函数处理捕获组内容,需要改用preg_replace_callback,通过回调函数处理每个匹配结果,再调用getYoutubeVideoID获取真实视频ID。
修改后的bbc2html函数:
function bbc2html($content) { // 先处理粗体、下划线、斜体这些简单替换 $content = preg_replace('/\[b\](.*?)\[\/b\]/', '<b>$1</b>', $content); $content = preg_replace('/\[u\](.*?)\[\/u\]/', '<u>$1</u>', $content); $content = preg_replace('/\[i\](.*?)\[\/i\]/', '<i>$1</i>', $content); // 处理youtube标签,用回调函数处理捕获组 $content = preg_replace_callback('/\[youtube\](.*?)\[\/youtube\]/', function($matches) { // $matches[1]是匹配到的YouTube链接 $videoId = getYoutubeVideoID($matches[1]); // 返回拼接好的HTML结构 return '<div class="video_wrapper card border-0 shadow text-center m-2" style="width: 25rem;"> <div class="video_trigger card-body" data-source="' . $videoId . '" data-type="youtube"> <p class="text-center">点击按钮即表示您同意加载YouTube的Cookie</p> <input type="button" class="btn btn-success" value="确定"> <a href="' . $matches[1] . '" type="button" target="_blank" class="btn btn-danger"><i class="fa-brands fa-youtube pe-1"></i>直接链接</a> </div> <div class="video_layer" style="display: none;"> <iframe src="" border="0" data-scaling="true" data-format="16:9" style="height: 0px;"></iframe> </div> </div>'; }, $content); return $content; }
说明
- 简单的BBCode(粗体、下划线、斜体)仍用
preg_replace处理,保持简洁。 - YouTube标签改用
preg_replace_callback,回调函数的$matches参数包含所有捕获组内容,$matches[1]就是匹配到的视频链接,直接传入getYoutubeVideoID即可得到正确的视频ID。 - 同时将提示文本翻译成了中文,符合国内使用场景。
内容的提问来源于stack exchange,提问作者Heisenberg
相关产品推荐
相关产品推荐

