Простая система баннеров для Cotonti
Популярные запросы: тема Omnis, плагин Pagelist, Cotonti 0.9.24.2, ЧПУ, Font Face
- 528 просмотров
- 25 июня, 2024
- Обновлено: 2 августа, 2024
- admin
- Время чтения: 6 минут
- 2 (Подробно)
![](pics/thumbs/148/img-148-966x644-crop.jpg)
Недавно для одного из проектов возникла идея реализации баннерной системы. Требования оказались довольно простыми – хотя бы потому, что системы ротации баннеров в классическом понимании достаточно давно устарели. Мне же понадобилось реализовать следующие возможности:
Вывод баннера в конкретной локации
Поскольку размер рекламного баннера прямо зависит от того, где он размещается, необходимо дифференцировать их по локациям. Например,
- баннеры в 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)} === true --> {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
29.06.2024 | Все элементы 3 уровня теперь являются массивами, функция sedby_banner() принимает 4 параметра: $tpl, $area, $id и $elems |
26.06.2024 | Вместо одного теперь используются два текстовых элемента |
Необходимо использовать $_SESSION для фиксирования уже показанных баннеров.
Интересный плагин. И движок тоже хорошо что развивается. Мой вопрос такой: а можно сделать так, чтобы посетителю выводился не случайный баннер, который может повториться, а все по очереди из указанной группы?
Новый комментарий