Карта сайта Yii2 для поисковых систем.

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

Способы создание такой карты сайта есть разные. Популярностью пользуются онлайн генераторы. Но такие сервисы генерируют карту на определенный момент и если вы добавите новые страницы ее придется переделывать.

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

Чтобы карта открывалась по ссылке http://site.com/sitemap.xml нужно добавить правило для urlManager в frontend\config\main.php:

'sitemap.xml' => 'site/sitemap', //карта сайта

Это делается для того, чтобы не приходилось указывать название контроллера (site) и добавился нужный префикс (.xml)

Как можно заметить по этой строке, генерировать карту будет SiteController в действии actionSitemap():

use frontend\models\Sitemap;
...
//Карта сайта. Выводит в виде XML файла.
public function actionSitemap(){
    $sitemap = new Sitemap();
    //Если в кэше нет карты сайта        
    if (!$xml_sitemap = Yii::$app->cache->get('sitemap')) {
        //Получаем мыссив всех ссылок
        $urls = $sitemap->getUrl();
        //Формируем XML файл
        $xml_sitemap = $sitemap->getXml($urls);
        // кэшируем результат
        Yii::$app->cache->set('sitemap', $xml_sitemap, 3600*12); 
    } 
    //Выводим карту сайта
    $sitemap->showXml($xml_sitemap);
}


Основной элемент карты сайта это ссылки на его страницы. Способы получения этих самых ссылок есть разные. Здесь рассмотрим 2 варианта, при которых URL на сайте организованы с учетом ЧПУ и названия страниц прописаны словами, а не http://site.com/post/1 и тд.
 

  1. Используется свой класс маршрутизации urlManager с использованием отдельной таблицы в базе денных, которая хранит алиасы для URL страниц (постов, меток, рубрик). Подробнее о создании такого класса читайте тут.
  2. Ссылки (URL) хранятся в поле "url" соответствующих таблиц (постов, рубрик, меток). Данный метод организации URL описан тут.


 

Вариант 1.

Особенностью данного подхода есть то, что эти ссылки мы будем брать из одной таблицы базы данных, которая используется при создании своего правила маршрутизации urlManager. Данная таблица содержит 2 графы, в одной из которых ссылка в формате yii2, а в другой алиас, который выводится в виде ссылки. Например обычная ссылка без ЧПУ на данную страницу может быть такой:
post/view?id=11

в адресной строке же будет:
sitemap_yii2.html

Что намного понятнее для человека и SEO оптимизировано.
Основной функционал находится в модели frontend\models\Sitemap.php:
 

<?php
namespace frontend\models;
use Yii;
use yii\base\Model;
use common\models\Sef;
class Sitemap extends Model{
    public function getUrl(){
            $urls = array();    
            //Получаем массив URL из таблицы Sef
            $url_rules = Sef::find()
                    ->select('link')
                    ->all();
            //Формируем двумерный массив. createUrl преобразует ссылки в правильный вид. 
            //Добавляем элемент массива 'daily' для указания периода обновления контента 
            foreach ($url_rules as $url_rule){
                $urls[] = array(Yii::$app->urlManager->createUrl([$url_rule->link]),'daily');
            }
            return $urls;
    }
    public function getXml($urls){
        $host = Yii::$app->request->hostInfo; // домен сайта    
        ob_start();  
        echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
        <url>
        <loc><?= $host ?></loc>
        <changefreq>daily</changefreq>
        <priority>1</priority>
        </url>
        <?php foreach($urls as $url): ?>
        <url>
        <loc><?= $host.$url[0] ?></loc>
        <changefreq><?= $url[1] ?></changefreq>
        </url>
        <?php endforeach; ?>
        </urlset>
        <?php return ob_get_clean();
    }
    public function showXml($xml_sitemap){
        // устанавливаем формат отдачи контента        
        Yii::$app->response->format = \yii\web\Response::FORMAT_XML;  
        //повторно т.к. может не сработать
        header("Content-type: text/xml");
        echo $xml_sitemap;
        Yii::$app->end(); 
    }    
}

Код, как обычно, хорошо прокомментирован, будут вопросы - спрашивайте.
Метод createUrl() на основе ссылок таблицы вида post/view?id=11, составит правильные ссылки с учетом моего правила маршрутизации.

То есть карта сайта генерируется из всех ссылок, которые есть в таблице sef. У меня там записи, рубрики, метки, в принципе все что надо, кроме главной страницы, поэтому для нее указываем теги перед началом цикла.

 

Вариант 2.

Данный вариант используется когда ссылки, а вернее названия страниц которые выводятся в URL, хранятся в базе данных в полях (например "url") соответствующих таблиц (посты, рубрика, метки). И затем с помощью настройки массива правил urlManager формируются нужные/полные URL. Т.к. данные находятся в разных таблицах - собираем их. Так же добавляем ссылки на главную и несколько статичных страниц, которых нет в БД. Меняем метод getUrl() в нашем классе:
 

<?php
namespace frontend\models;
 
use Yii;
use yii\base\Model;
use common\models\Post;
use common\models\Category;
use common\models\Tags;
 
class Sitemap extends Model{
 
    public function getUrl(){
 
            $urls = array();
 
            //Посты
            $url_posts = Post::find()
                    ->select('url')
                    ->all();
            //Формируем двумерный массив. createUrl преобразует ссылки в правильный вид. 
            //Добавляем элемент массива 'daily' для указания периода обновления контента 
            foreach ($url_posts as $url_post){
                $urls[] = array(Yii::$app->urlManager->createUrl([$url_post->url]) . '.html','daily');
            }
 
            //Рубрики
            $url_cats = Category::find()
                    ->select('url')
                    ->all();
            foreach ($url_cats as $url_cat){
                $urls[] = array('/category' . Yii::$app->urlManager->createUrl([$url_cat->url]),'daily');
            }
 
            //Метки
            $url_tags = Tags::find()
                    ->select('url')
                    ->all();
            foreach ($url_tags as $url_tag){
                $urls[] = array('/tag' . Yii::$app->urlManager->createUrl([$url_tag->url]),'daily');
            }
 
            //Статичные страницы (у каждой свое действие контроллера)
            $arr_stat_page = [
                'about.html', 'service.html', 'contact.html',
            ];
            foreach ($arr_stat_page as $url_stat){
                $urls[] = array(Yii::$app->urlManager->createUrl($url_stat),'daily');
            }
 
            return $urls;
    }
 
    //Формирует XML файл, возвращает в виде переменной
    public function getXml($urls){
        $host = Yii::$app->request->hostInfo; // домен сайта    
        ob_start();  
 
        echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
 
        <url>
        <loc><?= $host ?></loc>
        <changefreq>daily</changefreq>
        <priority>1</priority>
        </url>
 
        <?php foreach($urls as $url): ?>
        <url>
        <loc><?= $host.$url[0] ?></loc>
        <changefreq><?= $url[1] ?></changefreq>
        </url>
        <?php endforeach; ?>
        </urlset>
 
        <?php return ob_get_clean();
    }
 
    //Возвращает XML файл
    public function showXml($xml_sitemap){
        // устанавливаем формат отдачи контента        
        Yii::$app->response->format = \yii\web\Response::FORMAT_XML;  
        //повторно т.к. может не сработать
        header("Content-type: text/xml");
        echo $xml_sitemap;
        Yii::$app->end(); 
    }    
}


В массиве $urls будут данные такого формата:
 

Array
(
    [0] => Array
        (
            [0] => /about.html
            [1] => daily
        )
    [1] => Array
        (
            [0] => /service.html
            [1] => daily
        )
    [2] => Array
        (
            [0] => /contact.html
            [1] => daily
        )
...

Для выдачи контента в XML формате я использую стандартную функцию php header(), т.к. способ указания с помощью Yii2
Yii::$app->response->format = \yii\web\Response::FORMAT_XML;
у меня лично не работает.

Ваша карта должна открываться по ссылке http://ваш_сайт.com/sitemap.xml
Если вы не используете данные подходы формирования URL, то можете составить свой массив ссылок который будет использоваться при генерации данной карты сайта.


Проверка карты сайта: https://www.xml-sitemaps.com/validate-xml-sitemap.html

Источник: Перейти
Комментарии (0):
Чтобы оставить свой комментарий, необходимо пройти аутентификацию