Как найти все картинки в HTML-тексте на PHP и обернуть их в ссылки

Как найти все изображения в HTML-тексте новости или статьи и обернуть каждое ссылкой на полноразмерную картинку для галереи-лайтбокса: на DOMDocument и на регулярных выражениях.

Задача из практики: в новостях на 1С-Битрикс картинки вставлены прямо в текст, а нужно, чтобы по клику они открывались в полном размере в лайтбоксе (например, fancybox). Для этого каждую картинку надо обернуть ссылкой на её же файл.

Надёжный способ: DOMDocument

function wrapImages(string $html, string $class = 'fancybox'): string
{
    if (trim($html) === '') {
        return $html;
    }
    $dom = new DOMDocument();
    libxml_use_internal_errors(true);
    $dom->loadHTML('<?xml encoding="utf-8"?><div>' . $html . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    foreach (iterator_to_array($dom->getElementsByTagName('img')) as $img) {
        if ($img->parentNode->nodeName === 'a') {
            continue;                                    // уже в ссылке
        }
        $link = $dom->createElement('a');
        $link->setAttribute('href', $img->getAttribute('src'));
        $link->setAttribute('class', $class);
        $img->parentNode->replaceChild($link, $img);
        $link->appendChild($img);
    }

    $wrapper = $dom->getElementsByTagName('div')->item(0);
    $out = '';
    foreach ($wrapper->childNodes as $child) {
        $out .= $dom->saveHTML($child);
    }
    return $out;
}

Функция пропускает картинки, которые уже стоят в ссылке, и не ломается на разных порядках атрибутов и кавычках.

Короткий способ: регулярное выражение

$content = preg_replace(
    '~(<img\b[^>]*\bsrc=(["\'])([^"\']+)\2[^>]*>)~i',
    '<a class="fancybox" href="$3">$1</a>',
    $content
);

Подходит для простого и предсказуемого HTML. Если картинки уже бывают обёрнуты ссылками, используйте вариант с DOMDocument.

Где вызывать в Битрикс

В result_modifier.php шаблона компонента новости: $arResult['DETAIL_TEXT'] = wrapImages($arResult['DETAIL_TEXT']);. Результат кешируется вместе с компонентом, и обработка не выполняется на каждом просмотре.

Все статьи

Расскажите о задаче — подберём платформу и оценим работу

Обсудить проект