@MrSusua

Как реализовать обработку результатов foreach в PHP?

Добрый день и с Новым Годом всех вас!

У меня есть переменная с данными:

<?php
$content = '

<code>
	<?php echo '<p>Привет, мир!</p>'; ?>
</code>

<p></p>

<code>
	<?php echo '<p>Добрый день, мир!</p>'; ?>
</code>

<div></div>

<code>
	<?php echo '<p>Добрый вечер, мир!</p>'; ?>
</code>

<p>И т. д.</p>

';


Необходимо найти СОДЕРЖИМОЕ (содержимое - это то что внутри) всех тегов code ,обработать его функцией htmlspecialchars и вернуть обратно в контент (внутрь тегов code) уже обработанные результаты. Должно получиться так:

$content = '

<code>
	&lt;?php echo '&lt;p&gt;Привет, мир!&lt;/p&gt;'; ?&gt;
</code>

<p></p>

<code>
	&lt;?php echo '&lt;p&gt;Добрый день, мир!&lt;/p&gt;'; ?&gt;
</code>

<div></div>

<code>
	&lt;?php echo '&lt;p&gt;Добрый вечер, мир!&lt;/p&gt;'; ?&gt;
</code>

<p>И т. д.</p>

';


Я пробую так, но, что-то не работает:

preg_match_all( "/(?<=<code>).*?(?=<\/code>)/uis", $content, $matches );
	foreach($matches[0] as $one) {
		$obr = htmlspecialchars( $one[0], ENT_QUOTES, 'UTF-8' );
		$content = str_replace( $one[0], $obr, $content);
	}

Где я ошибаюсь?
  • Вопрос задан
  • 192 просмотра
Решения вопроса 1
Lobotomist
@Lobotomist
Software Developer
Вам стоило бы посмотреть, чему у вас равны переменные на каждом этапе обработки. И тогда вы бы заметили, что $matches[0] хранит в себе строки, а не массивы. И вместо $one[0] вам нужно обращаться к $one.

preg_match_all( "/(?<=<code>).*?(?=<\/code>)/uis", $content, $matches );
foreach($matches[0] as $one) {
	$obr = htmlspecialchars( $one, ENT_QUOTES, 'UTF-8' );
	$content = str_replace( $one, $obr, $content);
}
//</code>


Еще можно использовать preg_replace_callback. Мне кажется это более логичным.

$replaceFunc = function($matches) {
	return htmlspecialchars($matches[0], ENT_QUOTES, 'UTF-8');
};
$content = preg_replace_callback("/(?<=<code>).*?(?=<\/code>)/uis", $replaceFunc, $content);
//</code>


В конце блоков кода присутствует "< /code>" - похоже, это глюк парсера тостера. Видимо, в связи с < code> внутри регэкспа.

UPD:
Ну вот, я только что заметил, что веду себя как некрофил =(
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Melkij
@Melkij
PostgreSQL DBA
Используйте preg_replace_callback, проще будет.
Ответ написан
Комментировать
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Ваша проблема легко решается при помощи var_dump. $matches - двумерный массив, а вы, когда делаете $one[0], пытаетесь залезть на третий уровень.
ideone.com/o6dahA

Ну а вообще, Владлен Ultra совершенно верно говорит - не нужно парсить html регулярными выражениями.
Ответ написан
Комментировать
@MrSusua Автор вопроса
К сожалению, ковыряться в WordPress с DOMDocument у меня (да и у других, думаю, тоже), нет никакого желания. PHP стерпит всё. Обработать любое регулярное выражение займёт микросекунды.

К сожалению, var_dump. $matches мне не подходит, так как в WordPress, мне нужно вернуть именно обработанный $content.

Как допилить вот это решение?

preg_match_all( "/(?<=<code>).*?(?=<\/code>)/uis", $content, $matches );
  foreach($matches[0] as $one) {
    $obr = htmlspecialchars( $one[0], ENT_QUOTES, 'UTF-8' );
    $content = str_replace( $one[0], $obr, $content);
  }
</code>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы