2014-09-29 2 views
0

Попытка написать функцию, которая заменит # something # и # anything # в любой строке элементами в моем db, которые соответствуют имени «что-то» и «что угодно».Заменить несколько элементов между тегами в строке

Это должно работать независимо от того, сколько разных # some-name # есть в моей строке. Ниже я до сих пор работаю, но только последний (# ничего #) заменяется правильным кодом при загрузке в моем браузере.

Пожалуйста, имейте в виду, что я учусь, поэтому я могу быть совершенно уверен, как это сделать. Если есть лучший способ, я все уши.

HTML (String)

<p>This is "#something#" I wanted to replace with code from my database. Really, I could have "#anything#" between my pound sign tags and it should be replaced with text from my database</p> 

ВЫВОД Я Получение

This is "#something#" I want to replace with code from my database. Really, I could have "Any Name" between my pound sign tags and it should be replaced with text from my database 

ЖЕЛАЕМЫЙ ВЫВОД

This is "The Code" I want to replace with code from my database. Really, I could have "Any Name" between my pound sign tags and it should be replaced with text from my database 

ФУНКЦИЯ в CMS класса A.php

public function get_snippets($string) { 
$regex = "/#(.*?)#/"; 
preg_match_all($regex, $string, $names); 
$names = $names[1]; 
    foreach ($names as $name){ 
    $find_record = Snippet::find_snippet_code($name); 
    $db_name = $find_record->name; 
    if($name == $db_name) { 
    $snippet_name = "/#".$name."#/"; 
    $code = $find_record->code; 
    } 
    } 
echo preg_replace($snippet_name, $code, $string); 
} 

FUNCTION в классе Snippet b.php

public static function find_snippet_code($name) { 
global $database; 
$result_array = static::find_by_sql("SELECT * from ".static::$table_name." WHERE name = '{$name}'"); 
return !empty($result_array) ? array_shift($result_array) : false; 
} 

ответ

0

Это потому, что ваш preg_replace происходит вне цикла foreach(), так что это происходит только один раз. Вот рабочий пример, основанный на вашем коде, который возвращает $string.

Обратите внимание, что я также использую PREG_SET_ORDER, который дает мне каждый матч как свой собственный массив:

function get_snippets($string) { 
    $regex = '/#([^#]+)#/'; 
    $num_matches = preg_match_all($regex, $string, $matches, PREG_SET_ORDER); 
    if ($num_matches > 0) { 
     foreach ($matches as $match) { 
      // Each match is an array consisting of the token we matched and the 'name' without the special characters 
      list($token, $name) = $match; 

      // See if there is a matching record for 'name' 
      $find_record = Snippet::find_snippet_code($name); 

      // This step might be redundant, but compare name with the record name 
      if ($find_record->name == $name) { 
       // Replace all instances of #token# with the code from the matched record 
       $string = preg_replace('/'.$token.'/', $find_record->code, $string); 
      } 

     } 
    } 

    return $string; 
} 
+0

Fantastic! Теперь мне просто нужно это понять. Вопрос: вы сказали, что это потому, что мой preg_replace был вне моего цикла foreach(). Когда я тестировал его в цикле foreach(), это делало еще более сумасшедшие вещи. Было ли это единственно неправильно, должно быть что-то еще, нет? – user2998254

+0

В вашей версии вы использовали 'echo()' каждый раз, когда вы делали замену. В версии, которую я предоставил, мы работаем непосредственно над '$ string', которая является копией того, что было передано функции. Такова разница, которая вызвала бы странный выход в цикле. – itsmejodie

0

Что вы ищете является preg_replace_callback():

public function get_snippets($string) 
{ 
    $regex = "/#(.*?)#/"; 
    return preg_replace_callback($regex, function($match) { 
     $find_record = Snippet::find_snippet_code($match[1]); 
     return $find_record === false ? '' : $find_record->code; 
    }, $string); 
} 
+0

Спасибо за ваш отзыв, этот код мне не помог. – user2998254

Смежные вопросы