Шорткоды на регулярных выражениях

Часто на сайтах возникает необходимость вставлять в тексты страниц динамичные информационные блоки – баннеры, телефоны и т.д. Как правило, содержание этих блоков часто изменяется что существенно усложняет работу контент менеджера.

Упростить эту задачу помогут шорткоды (shortcode). Смысл их в том что в HTML-коде страницы вместо нужного контента вставляется символьный код, например [[phone]], а при выводе на фронте сайта он заменяется на нужную информацию.

Шорткод в визуальном редакторе

Двойные квадратные скобки используются для того чтобы исключить ложную замену.

Простой пример замены шоркодов на контент:

$text = '
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
	[[phone]]
	<p>Sed porta justo sed nibh elementum condimentum.</p>
	[[address]]
';

$text = str_ireplace('[[phone]]', '+7 (495) 000-00-00', $text);
$text = str_ireplace('[[address]]', 'г.Москва, Тверская д.9', $text);
echo $text;
PHP

Результат:

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
+7 (495) 000-00-00
<p>Sed porta justo sed nibh elementum condimentum.</p>
г.Москва, Тверская д.9

Шорткоды с контентом из массива

Данный функционал можно реализовать на регулярных выражениях, функцией preg_match_all().

$text = '
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
	[[phone]]
	<p>Sed porta justo sed nibh elementum condimentum.</p>
	[[address]]
';

// Массив значений
$info = array(
	'phone'   => '+7 (495) 000-00-00',
	'address' => 'г.Москва, Тверская д.9',
);

// Поиск и замена
preg_match_all("|\[\[(.*)\]\]|U", $text, $matches);
if (!empty($matches[1])) {
	foreach ($matches[1] as $row) {
		$replase = (empty($info[$row])) ? '' : $info[$row];
		$text = str_ireplace('[[' . $row . ']]', $replase, $text);
	}
}

echo $text;
PHP

Результат:

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
+7 (495) 000-00-00
<p>Sed porta justo sed nibh elementum condimentum.</p>
г.Москва, Тверская д.9

В следующим примере используются шорткод вида [[blocks.XX]], где XX указывает ID нужной записи в таблице `blocks`.

$text = '
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
	[[blocks.1]]
	<p>Sed porta justo sed nibh elementum condimentum.</p>
	[[blocks.2]]
';

// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'ЛОГИН', 'ПАРОЛЬ');

// Поиск и замена
preg_match_all("|\[\[blocks\.(.*)\]\]|U", $text, $matches);
if (!empty($matches[1])) {
	foreach ($matches[1] as $row) {
		$sth = $dbh->prepare("SELECT `text` FROM `blocks` WHERE `id` = ?");
		$sth->execute(array($row));
		$item = $sth->fetch(PDO::FETCH_ASSOC);

		$replase = (empty($item['text'])) ? '' : $item['text'];
		$text = str_ireplace('[[blocks.' . $row . ']]', $replase, $text);
	}
}

echo $text;
PHP

Как вариант замену кодов можно производить в callback-функции буферизации вывода ob_start():

<?php
// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'ЛОГИН', 'ПАРОЛЬ');

function callback($buffer)
{
	preg_match_all("|\[\[blocks\.(.*)\]\]|U", $buffer, $matches);
	if (!empty($matches[1])) {
		foreach ($matches[1] as $row) {
			$sth = $dbh->prepare("SELECT `text` FROM `blocks` WHERE `id` = ?");
			$sth->execute(array($row));
			$item = $sth->fetch(PDO::FETCH_ASSOC);

			$replase = (empty($item['text'])) ? '' : $item['text'];
			$buffer = str_ireplace('[[blocks.' . $row . ']]', $replase, $buffer);
		}
	}

	return $buffer;
}

ob_start('callback');

?>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
[[blocks.1]]
<p>Sed porta justo sed nibh elementum condimentum.</p>
[[blocks.2]]
PHP

Второй вариант со скидыванием буфера в переменную с помощью функции ob_get_contents():

<?php
// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'ЛОГИН', 'ПАРОЛЬ');

ob_start();
?>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
[[blocks.1]]
<p>Sed porta justo sed nibh elementum condimentum.</p>
[[blocks.2]]

<?php
$buffer = ob_get_contents();
ob_end_clean();

preg_match_all("|\[\[blocks\.(.*)\]\]|U", $buffer, $matches);
if (!empty($matches[1])) {
	foreach ($matches[1] as $row) {
		$sth = $dbh->prepare("SELECT `text` FROM `blocks` WHERE `id` = ?");
		$sth->execute(array($row));
		$item = $sth->fetch(PDO::FETCH_ASSOC);

		$replase = (empty($item['text'])) ? '' : $item['text'];
		$buffer = str_ireplace('[[blocks.' . $row . ']]', $replase, $buffer);
	}
}

echo $buffer;
PHP
17.03.2018, обновлено 09.06.2021
3423
Предыдущая запись PHP parse_url и её обратная функция
Следующая запись RSS канал на PHP

Комментарии

, чтобы добавить комментарий.

Другие публикации

Регулярные выражения для замены на теги
Замена URL, e-mail и текста на HTML-теги по регулярному выражению PHP.
2289
+1
PHP-класс обертка для PDO
Класс значительно упрощает работу с PDO, сокращает код. Реализован на статических классах и не требует создание экземпляра класса.
15742
+8
Примеры использования PDO MySQL
В статье приведены основные примеры работы с расширением PHP PDO. Такие как подключение к БД, получение, изменение и...
64656
+2
Поиск похожих статей на PHP + MySQL
Один из вариантов поиска похожих статей в базе данных основан на схождении слов в двух текстах.
2872
+2
Счетчик просмотров страниц с графиком
Для примера возьмем статейный сайт, на нём нужно сделать счетчик просмотров статей, с выводом результатов за день,...
9776
+14
Постраничный вывод и базы данных
В SQL запросах, для ограничения количества строк в результате используется инструкция LIMIT, например следующий вернёт...
5385
+2