Простой sitemap для сайта на yii2

20.10.2015

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

Рассмотрим простой пример реализации sitemap для yii2:

Добавим в urlManager rules правило 'sitemap.xml' => 'sitemap/index' файла frontend\config\main.php:

return [
    'id' => 'test-Frontend',
    'name' => 'test',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'frontend\controllers',
    'components' => [
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => true,
        ],
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules'=> [
                 ...
                'sitemap.xml' => 'sitemap/index',
                 ...
             ]
        ]
] 

В результате обращения по адресу https://ваш.сайт/sitemap.xml будут переданы в контроллер SitemapController. К слову создаем его frontend\controllers\SitemapController.php:

<?php

namespace frontend\controllers;

use frontend\models\Blog\Categories;
use yii\web\Controller;
use yii\db\Query;
use Yii;

class SitemapController extends Controller
{

    public function actionIndex()
    {

        if (!$xml_sitemap = Yii::$app->cache->get('sitemap')) {  // проверяем есть ли закэшированная версия sitemap
            $urls = array();

            // Выбираем категории сайта
            $categories = Categories::find()->all();
            foreach ($categories as $category) {
                $urls[] = array(
                    Yii::$app->urlManager->createUrl(['/blog/' . $category->alias]) // создаем ссылки на выбранные категории
                , 'daily'                                                           // вероятная частота изменения категории
                );
            }

            // Записи Блога
            $posts = (new Query())
                ->select('b.alias, c.alias as c_alias')
                ->from('blog as b')
                ->leftJoin('blog_categories as c', 'b.catid = c.id')
                ->where('b.publish = 1 AND b.created <= NOW()')->all();

            foreach ($posts as $post) {
                $urls[] = array(
                    Yii::$app->urlManager->createUrl(['/blog/' . $post['c_alias'] . '/' . $post['alias']]) // строим ссылки на записи блога
                , 'weekly'
                );
            }

            $xml_sitemap = $this->renderPartial('index', array( // записываем view на переменную для последующего кэширования
                'host' => Yii::$app->request->hostInfo,         // текущий домен сайта
                'urls' => $urls,                                // с генерированные ссылки для sitemap
            ));

            Yii::$app->cache->set('sitemap', $xml_sitemap, 3600*12); // кэшируем результат, чтобы не нагружать сервер и не выполнять код при каждом запросе карты сайта.
        }

        Yii::$app->response->format = \yii\web\Response::FORMAT_XML; // устанавливаем формат отдачи контента

        echo $xml_sitemap;
    }
}

И так, после запроса карты сайта мы попадаем в метод index нашего контроллера. Затем смотрим, создавалась ли карта сайта раньше (есть ли она в кэше), если есть то отдаем кэш, если нет тогда формируем ее. Процесс формирования у каждого может быть свой. Главное здесь принцип: у Вас есть ссылки, их нужно собрать в массив, как Вы это сделаете решать Вам. Ссылки собираем не только статей, новостей, материалов и т.д. но и их категорий (и/или подкатегорий).

Каждый раз в массив добавляются ссылки вида (вложенность может быть любая):

/blog/  Категория

/blog/item/ Статья

/category/  Категория

/category/news/ Подкатегория

/category/news/item/ Статья

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

Время кэширования регулируется здесь:

Yii::$app->cache->set('sitemap', $xml_sitemap, 3600*12); // где 12 (часы) изменяем на любое время.

Изменяем формат вывода контента на xml:

Yii::$app->response->format = \yii\web\Response::FORMAT_XML;

Данная конструкция может вести себя по разному, поэтому если не увидите xml документ на выходе, можно попробовать вместо этой строчки написать так же:

header('Content-Type: application/xml'); // тоже самое, формат отдачи контента

(можно и совместно использовать, но лучше так не делать:) )

 

Вообщем собрали мы все ссылки в $urls:

$urls[] = array(
     Yii::$app->urlManager->createUrl(['/blog/' . $category->alias]) // создаем ссылки на выбранные категории
     , 'daily'                                                       // вероятная частота изменения категории
);

Вместо daily, можно использовать другие параметры. Например в зависимости от предполагаемой частоты изменения страницы выбираем один из параметров здесь: https://www.sitemaps.org/ru/protocol.html#changefreqdef

 

Все что осталось, это создать view. Создаем файл frontend\views\sitemap\index.php с содержимым:

<?php
/* @var $urls */
/* @var $host */

echo '<?xml version="1.0" encoding="UTF-8"?>';
?>

<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
    <? foreach($urls as $url): ?>
        <url>
            <loc><?= $host . $url[0] ?></loc>
            <changefreq><?= $url[1] ?></changefreq>
            <priority>0.5</priority>
        </url>
    <? endforeach; ?>
</urlset>

И тестируем свежеиспеченную карту сайта. https://ваш.сайт/sitemap.xml

В результате должно получить примерно следующую картину:

Пример sitemap для yii2

Вот самый простой пример создания sitemap.xml для своего сайта на yii2.

comments powered by HyperComments