Кастомная генерация файла sitemap.xml
Готовый код можно скачать в моем репозитории на GitFlic.
В стандартных возможностях Битрикс, карта сайта создаётся вручную через через модуль в админке. Под ручным созданием понимается не написание файла с нуля, а создание карты через нажатие кнопки. Если на сайте поменялись данные, возможно запустить автогенерацию. Минус стандартного решения, нет возможности дополнить sitemap.xml дополнительными полями.
Такие извращения не могут устраивать SEO специалистов, поэтому нам нужна своя кастомная карта сайта, которую легко настроить без лишних действий. Для этого в папке php_interface
сайта создаём файл hmarketingSitemap.php
и помещаем в него код:
php_interface/hmarketingSitemap.php<?php
/**
* @author Эйч Маркетинг <info@hmarketing.ru>
* @copyright 2014-2024 The hmarketing.ru
*/
// пространство имен модуля
namespace Hmarketing\Sitemap;
// пространство имен для автозагрузки модулей
use \Bitrix\Main\Loader;
// пространство имен для работы с файловой системой
use Bitrix\Main\IO;
// пространство имен с абстрактным классом для любых приложений, любой конкретный класс приложения является наследником этого абстрактного класса
use Bitrix\Main\Application;
// пространство имен для работы с датой
use Bitrix\Main\Type\DateTime;
// пространство имен для работы с запросами
use \Bitrix\Main\Entity\Query;
// подключаем модуль «Информационные блоки»
Loader::includeModule('iblock');
/**
* основной класс модуля
*
*/
class hmarketingSitemap
{
/**
* статические и динамические страницы в массиве после обработки
*
* @var array
*/
public $array_pages = array();
/**
* страницы из админки
*
* @var array
*/
public $urlPatch;
/**
* инфоблоки из админки
*
* @var array
*/
public $blockId;
/**
* исключаемые URL из фдминки
*
* @var array
*/
public $exceptionsPatch;
/**
* базовый URL сайта из админки
*
* @var string
*/
public $site_url;
/**
* базовое название файла из фдминки
*
* @var string
*/
public $fileName = FALSE;
//*******************************************//
// Получение данных модуля из базы //
//*******************************************//
/**
* получаем данные с настройками модуля из базы
*
* основной метод который подключает вспомогательные методы
*
* @param string $urlPatch страницы
* @param string $blockId ID инфоблоков
* @param string $exceptionsPatch исключения
* @param string $site_url базовый URL сайта
* @param string $fileName название файла
* @return int метод data() в случае успешной записи в файл возвращает число
*/
public function data($urlPatch, $blockId, $exceptionsPatch, $site_url, $fileName)
{
$this->urlPatch = $urlPatch;
$this->blockId = $blockId;
$this->exceptionsPatch = $exceptionsPatch;
$this->site_url = $site_url;
$this->fileName = $fileName;
if ((!empty($this->site_url) && !empty($this->fileName)) && (!empty($this->urlPatch) || !empty($this->blockId))) {
$this->statikPages($this->urlPatch);
$this->blockPages($this->blockId);
$this->exceptionsUrl($this->exceptionsPatch);
return $this->createXml();
}
}
//*******************************************//
// Метод для обработки страниц //
//*******************************************//
/**
* преобразование статических страниц в массив
*
* обработанные данные записываются в свойство array_pages
*
* @param string $str
* @return void
*/
public function statikPages($str)
{
// разделяем строку по переносу строк
$arrStr = preg_split("/\r\n|\n|\r/", $str);
// перебираем результат
foreach ($arrStr as $key => $value) {
// статичные страницы
$file = new IO\File(Application::getDocumentRoot() . trim($value) . 'index.php');
// если файл сушествует
if ($file->isExists()) {
$data = DateTime::createFromTimestamp($file->getModificationTime());
$data = $data->toString(new \Bitrix\Main\Context\Culture(array("FORMAT_DATETIME" => 'Y-m-d HH:i:s')));
$this->array_pages[] = array(
'URL' => trim($value),
'DATA' => $data,
'CHANGEFREQ' => 'daily',
'PRIORITY' => '0.9',
);
}
}
}
//*******************************************//
// Метод для обработки инфоблоков //
//*******************************************//
/**
* преобразование инфоблоков в массив
*
* обработанные данные записываются в свойство array_pages
*
* @param string $str
* @return void
*/
public function blockPages($str)
{
// разделяем строку по переносу строк
$arrStr = preg_split("/\r\n|\n|\r/", $str);
foreach ($arrStr as $key => $value) {
$iblockId = explode(':', $value);
// корневой элемент
$indexsQuery = new Query(
\Bitrix\Iblock\IblockTable::getEntity()
);
$indexsQuery->setSelect(array('*'))
->setFilter(array('=ID' => $iblockId[0], '=ACTIVE' => "Y"));
$indexs = $indexsQuery->exec();
foreach ($indexs as $index) {
$this->array_pages[] = [
'URL' => \CIBlock::ReplaceDetailUrl($index['LIST_PAGE_URL'], $index, true),
'DATA' => $index['TIMESTAMP_X']->format('Y-m-d H:i:s'),
'CHANGEFREQ' => 'monthly',
'PRIORITY' => '0.9',
];
}
// список разделов
$sectionsQuery = new Query(
\Bitrix\Iblock\SectionTable::getEntity()
);
$sectionsQuery->setSelect(array('*', 'SECTION_PAGE_URL' => 'IBLOCK.SECTION_PAGE_URL'))
->setFilter(array('=IBLOCK_ID' => $iblockId[0], '=ACTIVE' => "Y"));
$sections = $sectionsQuery->exec();
foreach ($sections as $section) {
$this->array_pages[] = [
'URL' => \CIBlock::ReplaceDetailUrl($section['SECTION_PAGE_URL'], $section, true, 'S'),
'DATA' => $section['TIMESTAMP_X']->format('Y-m-d H:i:s'),
'CHANGEFREQ' => 'daily',
'PRIORITY' => '0.8',
];
}
// cписок элементов
if ($iblockId[1] === 'Y') {
$elementQuery = new Query(
\Bitrix\Iblock\ElementTable::getEntity()
);
$elementQuery->setSelect(array('*', 'DETAIL_PAGE_URL' => 'IBLOCK.DETAIL_PAGE_URL'))
->setFilter(array('=IBLOCK_ID' => $iblockId[0], '=ACTIVE' => "Y"));
$elements = $elementQuery->exec();
foreach ($elements as $element) {
$this->array_pages[] = [
'URL' => \CIBlock::ReplaceDetailUrl($element['DETAIL_PAGE_URL'], $element, true, 'E'),
'DATA' => $element['TIMESTAMP_X']->format('Y-m-d H:i:s'),
'CHANGEFREQ' => 'monthly',
'PRIORITY' => '0.7',
];
}
}
}
}
//*******************************************//
// Метод для обработки исключений //
//*******************************************//
/**
* преобразование исключаемых страниц в массив
*
* исключаем из массива array_pages URL если они добавлены в исключение
*
* @param string $str
* @return void
*/
public function exceptionsUrl($str)
{
// разделяем строку по переносу строк
$arrStr = preg_split("/\r\n|\n|\r/", $str);
// перебираем основной массив $this->array_pages, пытаемся найти значение в $arrStr, если находим удаляем по ключу из основного массива $this->array_pages элемент массива
foreach ($this->array_pages as $key => $value) {
if (in_array($value['URL'], $arrStr)) {
unset($this->array_pages[$key]);
}
}
}
//*******************************************//
// Метод для генерации карты сайта //
//*******************************************//
/**
* создание карты сайта и запись в файл
*
* @return int если запись в файл прошла успешно, возвращается число
*/
public function createXml()
{
// cоздаём XML документ
$xml_content = '';
foreach ($this->array_pages as $key => $value) {
$xml_content .= PHP_EOL . '<url>' . PHP_EOL . '<loc>' . $this->site_url . $value['URL'] . '</loc>' . PHP_EOL . '<changefreq>' . $value['CHANGEFREQ'] . '</changefreq>' . PHP_EOL . '<priority>' . $value['PRIORITY'] . '</priority>' . PHP_EOL . '</url>';
}
// формируем шапку и вставляем тело документа
$xml_file = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . $xml_content . PHP_EOL . '</urlset>';
// находим/создаем файл для записи
$file = new IO\File(Application::getDocumentRoot() . '/' . $this->fileName . '.xml');
// запись содержимого в файл с заменой
return $file->putContents($xml_file);
}
}
Добавляем функцию в файл init.php
для возможности вызова скрипта из Агента:
php_interface/init.php<?php
// автозагрузка класса
CModule::AddAutoloadClasses(
'', // не указываем имя модуля
array(
// ключ - имя класса с простанством имен, значение - путь относительно корня сайта к файлу
'Hmarketing\Sitemap\hmarketingSitemap' => '/local/php_interface/hmarketingSitemap.php',
)
);
/**
* функция для запуска генерации карты сайта с агента
*
* @return string для агента функция должна вернуть сама себя
*/
function hmarketingSitemap()
{
// страницы
$urlPatch = '/test/';
// инфоблоки
$blockId = '1:Y';
// исключения
$exceptionsPatch = '';
// базовый URL сайта
$site_url = 'http://www.site1.loc';
// название файла
$fileName = 'sitemap';
$hmarketingSitemap = new Hmarketing\Sitemap\hmarketingSitemap();
if ($hmarketingSitemap->data($urlPatch, $blockId, $exceptionsPatch, $site_url, $fileName)) {
return "hmarketingSitemap();";
}
}
Вешаем функцию на агента: