Делаем карту сайта sitemap.xml в yii2
  • 2177

Делаем карту сайта sitemap.xml в yii2

Автор: admin | 21 мая (Пн.) 2018г. в 22ч.56м.

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

Есть не мало модулей и виджетов на github для генерации карты сайта, но я предпочитаю
сделать эту работу самостоятельно, тем более что все довольно просто. Итак, приступим.

Для начала определимся, что нам нужно, то есть какую информацию будет содержать карта сайта.
Для просмотра стандартных тегов для карты сайта обратимся к сайту https://www.sitemaps.org/ru/protocol.html

Вот такие теги я взял на вооружение для своей карты сайта:
<url>
    <loc>
    https://coderius.biz.ua/blog/article/apache-redirekt-s-www-na-bez-www-c-https
    </loc>
    <lastmod>2018-05-21T06:43:36+03:00</lastmod>
    <changefreq>daily</changefreq>
    <priority>1</priority>
</url>​

Мы выберем базовую "комплектацию" и в итоге карта сайта будет такой:

Карта сайта в yii2

Создание контроллера

Создаем контроллер в папке controllers и назовем его SitemapController. Выкладываю
сразу весь код контроллера. Он вполне понятел. Единственное, что Вам нужно работать с
своими моделями из которых и будем "добываться" данные для карты сайта. Тут, в примере
я создаю sitemap для блога и сюда будут включены посты блога, категории и теги. Ну и
конечно главная страница. Судя по пространству имен можно заметить, что в примере
используется advensed шаблон, но для base шаблона в коде менять ни чего не надо, кроме
пространства имен.
<?php

/**
 * Sitemap
 */
namespace frontend\controllers;


//Здесь обозначаем модели и базовые классы, которые будем использовать в коде.
use frontend\models\blog\articles\BlogArticles;
use frontend\models\blog\categories\BlogCategories;
use frontend\models\blog\tags\BlogTags;
use yii\web\Controller;
use yii\db\Query;
use Yii;

class SitemapController extends Controller
{
 
    public function actionIndex()
    {
        //Если нужно сбросить кэш, то расскоментируем и перезагрузим страницу
//        Yii::$app->cache->delete('sitemap');
        
        if (!$xml_sitemap = Yii::$app->cache->get('sitemap')) {  // проверяем есть ли закэшированная версия sitemap
        
            $urls = array();
 
            // Выбираем категории сайта
            $articles = BlogArticles::find()->active()->orderCreatedAt()->all();
            foreach ($articles as $article) {
                $urls[] = array(
                    'loc' => $article->url,
                    'lastmod' => date( DATE_W3C, strtotime($article->lastMod) ),
                    'changefreq' => 'daily',
                    'priority' => 1.0
                );
            }
 
            
            $categories = BlogCategories::find()->orderId()->all();
            foreach ($categories as $category) {
                $urls[] = array(
                    'loc' => $category->url,
                    'changefreq' => 'weekly',
                    'priority' => 0.8
                );
            }
            
            $series = BlogSeries::find()->orderId()->all();
            foreach ($series as $sery) {
                $urls[] = array(
                    'loc' => $sery->url,
                    'changefreq' => 'weekly',
                    'priority' => 0.5
                );
            }
            
            $tags = BlogTags::find()->orderId()->all();
            foreach ($tags as $tag) {
                $urls[] = array(
                    'loc' => $tag->url,
                    'changefreq' => 'weekly',
                    'priority' => 0.4
                );
            }
            
//            var_dump($urls);die;
            
            $xml_sitemap = $this->renderPartial('index', array( // записываем view на переменную для последующего кэширования
                'host' => Yii::$app->request->hostInfo,         // текущий домен сайта
                'urls' => $urls,                                // с генерированные ссылки для sitemap
            ));
        
            Yii::$app->cache->set('sitemap', $xml_sitemap, 60*60*12); // кэшируем результат на 12 ч
    }
    
        Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
        $headers = Yii::$app->response->headers;
        $headers->add('Content-Type', 'text/xml');
    
        return $xml_sitemap;
    }
    
}​

Когда я делаю выборку, то я использую методы запросов из ActiveQuery, такие как
 ->active() или ->orderCreatedAt()

Вот так они реализованы в модели:
class BlogArticlesQuery extends \yii\db\ActiveQuery
{
    
    public function active()
    {
        return $this->andWhere([BlogArticles::tableName().'.flagActive' => EnumBlog::ARTICLE_STATUS_ACTIVE]);
    }​

То есть это некое сокращение кода. Подробнее про создание вспомогательных методов в
ActiveQuery можете почитать тут.

Передаем собранные данные в вид и сохраняем все в переменной:
$xml_sitemap = $this->renderPartial('index', array(
    'host' => Yii::$app->request->hostInfo,
    'urls' => $urls,
));  ​

Не забываем, что нужно использовать именно $this->renderPartial
 'index' - файл видов, который будет создан далее.

Результат генирации кешируем на 12 ч. вот так:
Yii::$app->cache->set('sitemap', $xml_sitemap, 60*60*12); ​

Обратите внимание, что результат нужно возвращать так return $xml_sitemap; не через
echo, иначе может вылететь ошибка, связанная с отправкой заголовков.

Создание view

Создаем дирректорию sitemap в папке views согласно правилам фреймворка.
Внутри папки создаем файл index.php в который передаются данные из контроллера.
<?php

/* @var $urls */
/* @var $host */
 
echo '<?xml version="1.0" encoding="UTF-8"?>';
?>
 
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <?php foreach($urls as $url): ?>
        <url>
            <loc><?= $host . $url['loc']; ?></loc>
            <?php if(isset($url['lastmod'])): ?>
            <lastmod><?= $url['lastmod']; ?></lastmod>
            <?php endif; ?>
            <changefreq><?= $url['changefreq']; ?></changefreq>
            <priority><?= $url['priority']; ?></priority>
        </url>
    <?php endforeach; ?>
</urlset>​

Тут в цикле формируется карта сайта.

Создание правила роутинга url

Ну и чтобы карта сайта выводиласть по адресу http//:site.com/sitemap.xml нужно
добавить правила в роутинг:
<?php
return [
            'class' => 'yii\web\UrlManager',
            'baseUrl' => $baseUrl,//это базовый url определенный где-то в коде
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => true,
            'rules' => [
                'sitemap.xml' => 'sitemap/index',//правило для карты сайта
                
                '/' => 'site/index',​

Финал.

Когда все готово, вы можете проверить карту сайта на валидность в каком-нибудь
сервисе для проверки карт. Я пользуюсь Search Console от goole в панели веб мастера,
что очень удобно.

Читайте также из этой серии:

Приветствую!

Меня зовут Сергей. Я - автор этого блога.

Если Вам был полезен материал на моем сайте, поддержите пожалуйста мой проект, чтобы о нем узнали другие люди - кликните plizz :) на иконку в соц. сети, чтобы поделиться материалом с другими.