2010-10-05 85 views
0

我想爲YouTube視頻嵌入代碼替換需要用的preg_replace解釋{}變量幫助參數

{youtube}Video_ID_Here{/youtube}

到目前爲止,我有

preg_replace('/{youtube}(.*){\/youtube}/iU',...)

和它工作得很好。

但現在我想能夠解釋像高度,寬度等參數所以我可以有一個正則表達式,無論是否或沒有參數?它應該能夠inperpret所有這些在下面......

{youtube height="200px" width="150px" color1="#eee" color2="rgba(0,0,0,0.5)"}Video_ID_Here{/youtube}

{youtube height="200px"}Video_ID_Here{/youtube}

{youtube}Video_ID_Here{/youtube}

{youtube width="150px" showborder="1"}Video_ID_Here{/youtube}

回答

1

嘗試這種情況:

function createEmbed($videoID, $params) 
{ 
    // $videoID contains the videoID between {youtube}...{/youtube} 
    // $params is an array of key value pairs such as height => 200px 

    return 'HTML...'; // embed code 
} 

if (preg_match_all('/\{youtube(.*?)\}(.+?)\{\/youtube\}/', $string, $matches)) { 
    foreach ($matches[0] as $index => $youtubeTag) { 
     $params = array(); 

     // break out the attributes 
     if (preg_match_all('/\s([a-z0-9]+)="([^\s]+?)"/', $matches[1][$index], $rawParams)) { 
      for ($x = 0; $x < count($rawParams[0]); $x++) { 
       $params[$rawParams[1][$x]] = $rawParams[2][$x]; 
      } 
     } 

     // replace {youtube}...{/youtube} with embed code 
     $string = str_replace($youtubeTag, createEmbed($matches[2][$index], $params), $string); 
    } 
} 

此代碼相匹配的{的YouTube} ... {/ YouTube的}第一標記,然後打出的屬性到一個數組,傳遞兩者(如鍵/值對)和視頻ID到一個功能。只需填寫函數定義以使其驗證您想要支持的參數並構建適當的HTML代碼即可。

1

你可能想使用preg_replace_callback,作爲否則替換會變得相當複雜。

preg_replace_callback('/{youtube(.*)}(.*){\/youtube}/iU',...) 

而在你的回調,檢查$match[1]的東西像/(width|showborder|height|color1)="([^"]+)"/i模式。 preg_replace_callback中的一個簡單的preg_match_all保持所有部分的整齊,清晰易讀。

+0

出現您的解決方案是最重量輕,但我似乎無法得到它工作...你會介意更深入的這個。我非常擅長php,但對preg ..()函數和正則表達式知之甚少。謝謝! – Johnny 2010-10-06 13:53:06

1

我會做這樣的事情:

preg_match_all("/{youtube(.*?)}(.*?){\/youtube}/is", $content, $matches); 

for($i=0;$i<count($matches[0]);$i++) 
{ 
    $params = $matches[1][$i]; 
    $youtubeurl = $matches[2][$i]; 

    $paramsout = array(); 

    if(preg_match("/height\s*=\s*('|\")([0-9]+px)('|\")/i", $params, $match) 
    { 
    $paramsout[] = "height=\"{$match[2]}\""; 
    } 

    //process others 

    //setup new code 
    $tagcode = "<object ..." . implode(" ", $paramsout) ."... >"; //I don't know what the code is to display a youtube video 

    //replace original tag 
    $content = str_replace($matches[0][$i], $tagcode, $content); 
} 

你可以只找PARAMS後「{YouTube的」與之前的「}」,但你打開自己到XSS問題。最好的方法是查找特定數量的參數並驗證它們。不要讓像<和>這樣的東西在你的標籤中傳遞,因爲有人可能會把do_something_nasty();或者其他的東西。

+0

+1不僅僅是正確的答案,而且解釋了preg_match查詢錯誤所涉及的安全威脅=) – stevendesu 2010-10-06 01:56:10

0

我根本不使用正則表達式,因爲它們在解析標記時出了名。

由於您的輸入格式是如此接近HTML/XML擺在首位,我會依賴於

$tests = array(
    '{youtube height="200px" width="150px" color1="#eee" color2="rgba(0,0,0,0.5)"}Video_ID_Here{/youtube}' 
    , '{youtube height="200px"}Video_ID_Here{/youtube}' 
    , '{youtube}Video_ID_Here{/youtube}' 
    , '{youtube width="150px" showborder="1"}Video_ID_Here{/youtube}' 
    , '{YOUTUBE width="150px" showborder="1"}Video_ID_Here{/youtube}' // deliberately invalid 
); 

echo '<pre>'; 
foreach ($tests as $test) 
{ 
    try { 
    $youtube = SimpleXMLYoutubeElement::fromUserInput($test); 

    print_r($youtube); 
    } 
    catch (Exception $e) 
    { 
    echo $e->getMessage() . PHP_EOL; 
    } 
} 
echo '</pre>'; 

class SimpleXMLYoutubeElement extends SimpleXMLElement 
{ 
    public static function fromUserInput($code) 
    { 
    $xml = @simplexml_load_string(
     str_replace(array('{', '}'), array('<', '>'), strip_tags($code)), __CLASS__ 
    ); 
    if (!$xml || 'youtube' != $xml->getName()) 
    { 
     throw new Exception('Invalid youtube element'); 
    } 
    return $xml; 
    } 

    public function toEmbedCode() 
    { 
    // write code to convert this to proper embode code 
    } 
}