Пользователь может ввести текст и использовать некоторые определенные заполнители, которые заменяются автоматически. Может случиться так, что для заполнителя нет соответствующего значения, так что заполнитель будет заменен пустой строкой или нулем или чем-то в этом роде. Это может привести к бесполезному / грамматически некорректному тексту.
Допустим, система предоставляет заполнители [Price_Difference] и [Price].
Пользователь вводит текст как «Яблоко стоит [Цена] USD. Теперь оно [Price_Difference] USD дешевле. Купи 7 и получи 100 бесплатно». Теперь у нас есть объект в БД, который содержит цену и (возможно) старую цену. Если определена старая цена, мы можем рассчитать разницу в цене, заменить заполнители, и все будут довольны. Но если не определена старая цена, предложение не будет иметь особого смысла.
$user_text = "An apple costs [Price] USD. It's now [Price_Difference] USD cheaper. Buy 7 and get 100 free.";
$usable_data = ['price' => 50, 'price_difference' => 200];
Теперь я мог бы использовать что-то вроде
$final_text = str_ireplace(
['[Price]', '[Price_Difference]'],
[$usable_data['price'], $usable_data['price_difference']],
$user_text
];
Чтобы получить результат, как «Яблоко стоит 50 долларов. Теперь оно дешевле на 200 долларов. Купи 7 и получи 100 бесплатно».
Но давайте предположим, что есть объект, который не имеет старой цены для расчета разницы в ценах. Результат будет что-то вроде «Яблоко стоит 50 долларов. Теперь оно дешевле доллара. Купи 7 и получи 100 бесплатно».
Моя первоначальная идея — сделать части текста необязательными. Тогда я мог бы заменить все заполнители, но только если существует соответствующее значение. На втором шаге я заменил бы все заполнители, которые все еще содержат заполнители, и удалил последние заполнители-маркеры на последнем этапе.
В качестве простого примера это может быть что-то вроде:
$user_text = "An apple costs [Price] USD. [[It's now [Price_Difference] USD cheaper.]] Buy 7 and get 100 free.";
if ($usable_data['price'] > 0) {
$final_text = str_ireplace('[Price]', $usable_data['price'], $user_text);
}
if ($usable_data['price_difference'] > 0) {
$final_text = str_ireplace('[Price_Difference]', $usable_data['price_difference'], $user_text);
}
Это приведет к
«Яблоко стоит 50 долларов США. [[Теперь это [Price_Difference] USD дешевле».] Купи 7 и получи 100 бесплатно ».
Теперь мне нужно что-то (может быть, регулярное выражение), чтобы найти / удалить все части текста, который содержит [(. *)] Внутри [[и]], поэтому конечный результат будет «Яблоко стоит 50 долларов. Купи 7 и получи 100 бесплатно».
Поскольку у меня возникли проблемы при использовании [и] как для фактического заполнителя, так и для «необязательных» частей текстового блока, я начал использовать двойные [[и]] для необязательных частей. Мой в основном работает регулярное выражение
$res = preg_replace("@\[\[(.*)\]\]@siU", '', $text);
Который действительно удаляет все между [[и]]. Это не может быть жадным, так как текст может содержать несколько заполнителей и необязательных текстовых частей. Но мне нужно что-то, что удаляет эту часть, только если между ними есть [и a]. Так было бы что-то вроде
$res = preg_replace("@\[\[(.* andmusthave[and] )\]\]@siU", '', $text);
Но я на самом деле сомневаюсь, что это лучший подход вообще. Может быть, есть что-то более универсальное, чтобы использовать «дополнительные» части в системе заполнителей?
РЕДАКТИРОВАТЬ
После публикации этого вопроса у меня появилась идея, которая, кажется, работает:
$pr = preg_replace("@\[\[(.*)\[(.*)\](.*)\]\]@siU", '', $var);
Но я все еще не совсем уверен, является ли это лучшим решением для первоначальной проблемы.
Задача ещё не решена.
Других решений пока нет …