Добро пожаловать на сайт SEDBY

Простая система баннеров для Cotonti

  • 497 просмотров
  • 25 июня, 2024
  • Обновлено: 15 июля, 2024
  • admin
  • Время чтения: 6 минут
  • 2 (Подробно)

Недавно для одного из проектов возникла идея реализации баннерной системы. Требования оказались довольно простыми – хотя бы потому, что системы ротации баннеров в классическом понимании достаточно давно устарели. Мне же понадобилось реализовать следующие возможности:

Вывод баннера в конкретной локации

Поскольку размер рекламного баннера прямо зависит от того, где он размещается, необходимо дифференцировать их по локациям. Например,

  • баннеры в header или “шапке” (глобальные),
  • баннеры на главной странице,
  • баннеры в сайдбаре внутренней страницы (шаблоны страниц или разделов).

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

Отсюда полагаем, что основным атрибутом баннера (или их группы) должна стать локация.

Дополнительные атрибуты баннера

Каждый баннер должен иметь следующие компоненты:

  • URL перехода,
  • имя файла с картинкой,
  • текстовое значение для HTML-атрибутов title и alt.

В качестве глобальных параметров мы будем использовать:

  • местоположение папки с картинками,
  • значение атрибута rel.

Нет смысла хранить единый путь в поле с именем файла. Мы будем использовать единый путь для всех картинок и добавим его в настройки плагина.

Кроме этого, не стоит забывать о правильном оформлении баннерных ссылок с помощью атрибута rel. Более подробно об этом мы рассказывали раньше. В нашей реализации мы не будем указывать значение для каждого баннера, и вместо этого используем общий глобальный параметр. Как и местоположение папки с картинками, его мы внесем в настройки будущего плагина.

Удобный формат хранения массива данных

Как понятно из названия, я не стал использовать отдельную таблицу базы данных для хранения наших баннеров. Возможно, это более правильный подход, но для него необходимо создать инструментальную часть, с помощью которой можно будет управлять списком (добавлять и удалять баннеры).

Более простым мне показалось использование ассоциативного массива для хранения записей. Его структура оформилась таким образом:

$sbs_banners = [
	'page' => [
    '1' => [
  		'image' => [
				'astronaut.jpg',
				'pilot.jpg',
			],
  		'link' => [
				'https://sed.by/blog',
				'https://sed.by/archive',
			],
  		'text_1' => [
				'Астронавт',
				'Космонавт',
			],
  		'text_2' => [
				'Изображение астронавта',
				'Картинка космонавта',
			],
  	],
  	'2' => [
  		'image' => [
				'desktop.jpg',
			],
  		'link' => [
				'https://sed.by/cot',
			],
      'text_1' => [
				'Десктоп',
			],
      'text_2' => [
				'Изображение десктопа',
			],
  	],
  ],
];

Кстати, если закомментировать какой-либо элемент массива, можно легко поставить баннер "на паузу". Ну а для того, чтобы все это работало быстрее, можно использовать возможности кэширования. В готовом виде получим следующий код:

<?php
/**
 * SBS Plugin Settings
 *
 * @package sbs
 * @version 1.00
 * @author SED.BY
 * @copyright (c) sed.by 2024
 */

defined('COT_CODE') or die('Wrong URL');

define('SBS_REALM', '[SEDBY] SBS Simple Banner System');

if ($cache && $cache->db->exists('banners', SBS_REALM)) {
	$sbs_banners = $cache->db->get('banners', SBS_REALM);
} else {

	$sbs_banners = [
		'page' => [
	    '1' => [
	  		'image' => [
					'astronaut.jpg',
					'pilot.jpg',
				],
	  		'link' => [
					'https://sed.by/blog',
					'https://sed.by/archive',
				],
	  		'text_1' => [
					'Астронавт',
					'Космонавт',
				],
	  		'text_2' => [
					'Изображение астронавта',
					'Картинка космонавта',
				],
	  	],
	  	'2' => [
	  		'image' => [
					'desktop.jpg',
				],
	  		'link' => [
					'https://sed.by/cot',
				],
	      'text_1' => [
					'Десктоп',
				],
	      'text_2' => [
					'Изображение десктопа',
				],
	  	],
	  ],
	];

	$cache && $cache->db->store('banners', $sbs_banners, SBS_REALM, Cot::$cfg['plugin']['sbs']['cache']);
}

Соответственно, у нас добавился еще один параметр – срок жизни кэша. Его мы добавим в настройки нашего плагина.

Как видно из примера, в качестве ключей массива я использовал значение поля page_id в таблице cot_pages. Это удобно для того, чтобы привязывать баннер к конкретной странице.

Условие и формат вывода баннера

В отдельных случаях нам необходимо проверять наличие в массиве баннера, привязанного к конкретной локации и id ее элемента. Например, если мы выводим баннер для конкретной страницы. Отсюда необходимость в функции проверки. Назовем ее sedby_banner_exists(). Параметров – исходя из структуры массива – будет два: локация и id. Сама же функция будет выглядеть так:

...
require_once cot_incfile('sbs', 'plug', 'settings');

function sedby_banner_exists($area, $id) {
	global $sbs_banners;
	return array_key_exists($id, $sbs_banners[$area]);
}
...

Таким образом, в шаблоне page.tpl мы можем указать:

<!-- IF {PHP.id|sedby_banner_exists('page', $this)} -->
{PHP.id|sedby_banner('sbs', 'page', $this)}
<!-- ENDIF -->

Если sedby_banner_exists() вернет true, будет сгенерен и выведен соответствующий баннер.

Второй момент – это формирование баннера. Здесь, как говорится, могут быть варианты, поэтому надо использовать подгружаемый TPL-шаблон. Функция sedby_banner() получит четыре параметра: имя шаблона, локацию, id элемента и режим вывода (первый элемент или случайный). В моей реализации она выглядит так:

function sedby_banner($tpl = 'sbs', $area = 'global', $id = 'random', $elems = 'first') {

	if (Cot::$cfg['plugin']['sbs']['enable']) {
		global $sbs_banners;

		($id == 'random') && $id = array_rand($sbs_banners[$area]);

		if ($elems == 'random') {
			$banner_link = array_rand($sbs_banners[$area][$id]['link']);
			$banner_image = array_rand($sbs_banners[$area][$id]['image']);
			$banner_text_1 = array_rand($sbs_banners[$area][$id]['text_1']);
			$banner_text_2 = array_rand($sbs_banners[$area][$id]['text_2']);
		} else {
			$banner_link = $banner_image = $banner_text_1 = $banner_text_2 = 0;
		}

		(!isset($tpl) || empty($tpl)) && $tpl = 'sbs';
		$t = new XTemplate(cot_tplfile($tpl, 'plug'));
		$t->assign([
			"BANNER_LINK" => $sbs_banners[$area][$id]['link'][$banner_link],
			"BANNER_IMAGE" => Cot::$cfg['mainurl'] . Cot::$cfg['plugin']['sbs']['folder'] . $sbs_banners[$area][$id]['image'][$banner_image],
			"BANNER_TEXT_1" => $sbs_banners[$area][$id]['text_1'][$banner_text_1],
			"BANNER_TEXT_2" => $sbs_banners[$area][$id]['text_2'][$banner_text_2],
			"BANNER_REL" => 'rel="' . Cot::$cfg['plugin']['sbs']['rel'] . '"',
		]);
		$t->parse();
		$output = $t->text();
	} else {
		$output = '';
	}

	return $output;
}

Я немного разнообразил возможности и добавил к ним вывод случайно выбранного баннера из указанной локации. Это будет реализовано при указании значения random для параметра $id. В остальных случаях производится поиск баннера по его id.

Дефолтный шаблон sbs.tpl будет иметь следующий вид:

<!-- BEGIN: MAIN -->
<a href="{BANNER_LINK}" title="{BANNER_TEXT_1}" class="mb-3 d-block" {BANNER_REL}>
  <img src="{BANNER_IMAGE}" alt="{BANNER_TEXT_2}" class="img-fluid">
</a>
<!-- END: MAIN -->

Естественно, в качестве параметра $tpl можно указать и свой собственный шаблон.

Если же вам необходимо выводить случайный баннер, необходимо немного изменить параметры функции:

{PHP|sedby_banner('sbs', 'page', 'random')}
<!-- Можно и так: -->
{PHP|sedby_banner('sbs', 'page')}
<!-- Или так: -->
{PHP|sedby_banner('sbs', 'page', 'random', 'random')}

Проверять что-либо перед вызовом нашей функции с параметром random уже не надо. Необходимо лишь убедиться в том, что в массиве $sbs_banners() существует локация page, и в ней в нужном количестве (не менее одного) присутствуют элементы, из которых будут сформированы наши баннеры.

Хранение изображений

Для наглядности по умолчанию я разместил изображения в папке /plugins/sbs/img/ Если вам хочется иначе, измените этот путь в настройках плагина.

При размещении баннеров, например, в папке /datas/banners/ учтите, что по умолчанию корневая папка /datas/ закрыта от индексирования. Об этом мы также уже упоминали. Соответственно, и изображения ваших баннеров также не будут проиндексированы. Поэтому если вам необходимо обратное, откройте доступ для поисковых ботов соответствующей директивой в файле robots.txt

Allow: /datas/sbs

Или разместите картинки вне папки datas.

Подключение функций

Поскольку мне понадобилось выводить баннеры только на страницах модуля Page, я подключил функции плагина через хук page.tags файлом sbs.page.tags.php

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=page.tags
[END_COT_EXT]
==================== */

defined('COT_CODE') or die('Wrong URL.');

require_once cot_incfile('sbs', 'plug');

Если вам необходимо использование баннеров в разделах, на главной странице, в шапке сайта и проч., создайте дополнительный файл с соответствующим хуком (page.list.tags, index.tags, header.tags). Либо используйте хук global для доступности функций в любой локации сайта.

Заключение

У нас получился простой и нересурсоемкий плагин для вывода баннеров. Данные получаем из массива в файле настроек и кэшируем для ускорения доступа к его элементам. Срок кэширования по умолчанию – 7 дней. Создавать сложную инструментальную часть и размещать данные в таблице базы данных я не стал, поскольку настройка баннеров – это не рутинная и далеко не ежедневная задача.

Выводить с помощью нашего плагина баннеры можно в режиме привязки “баннер – страница сайта” или в режиме “случайный баннер”. Практически никаких проверок я не делал – опять же по причине отсутствия необходимости в оных. Если они все же где-то необходимы, пишите в комментариях. Готовый плагин выкладываю в Github-репозитории.

Ранее мы разбирались с тонкостями верстки блока загрузки файла в шаблоне page.tpl

Лог обновлений плагина SBS:
29.06.2024 Все элементы 3 уровня теперь являются массивами, функция sedby_banner() принимает 4 параметра: $tpl, $area, $id и $elems
26.06.2024 Вместо одного теперь используются два текстовых элемента
Аватар
  • 1. Никита
  • 26.06.2024 19:30

Интересный плагин. И движок тоже хорошо что развивается. Мой вопрос такой: а можно сделать так, чтобы посетителю выводился не случайный баннер, который может повториться, а все по очереди из указанной группы?

Новый комментарий

Имя:
Для редактирования комментария осталось 10 минут
Блок пользователя
Регистрация на нашем сайте позволит вам общаться на форумах и получить доступ к другому полезному функционалу
Вы вошли как Гость