Добавляем автоматически генерируемый sitemap в Laravel

Добавлено: 14/04/2019 08:11 |  Обновлено: 14/04/2019 08:14 |  Добавил: nick |  Просмотры: 11150 Комментарии: 11
Вводная часть
В материале описывается как можно сформировать sitemap для сайта на Laravel. Sitemap сформируем на основе данного сайта (phpnick.ru). В результате sitemap будет условно состоять из 4 файлов: общий (индексный) и 3 отдельных файла для материалов (posts), категорий и тегов. Скрипты из материала подходят для 5-ой версии фреймворка.
Что такое sitemap? В общем случае sitemap – это xml-файл (или несколько связанных xml-файлов). Описание назначения данного файла на сайте sitemaps.org такое:
С помощью файла Sitemap веб-мастеры могут сообщать поисковым системам о веб-страницах, которые доступны для сканирования. Файл Sitemap представляет собой XML-файл, в котором перечислены URL-адреса веб-сайта в сочетании с метаданными, связанными с каждым URL-адресом (дата его последнего изменения; частота изменений; его приоритетность на уровне сайта), чтобы поисковые системы могли более грамотно сканировать этот сайт.

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

Sitemap 0.90, предоставляемый в соответствии с условиями лицензии Attribution-ShareAlike Creative Commons, получил широкое признание. Его поддерживают Google, Yahoo! и Майкрософт. sitemaps.org
Короче говоря, если ваш сайт большой и на нем есть много различных материалов, поисковые роботы могут не найти какие-то страницы/материалы на вашем сайте без файла sitemap. И соответственно эти материалы/страницы не попадут в поисковую выдачу.

Структура sitemap-файла

Структура одиночного sitemap-файла следующая:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <url>
      <loc>http://www.example.com/</loc>
      <lastmod>2005-01-01</lastmod>
      <changefreq>monthly</changefreq>
      <priority>0.8</priority>
   </url>
</urlset>
Но для данного сайта, мы сформируем 4 файла: общий (индексный) и 3 отдельных для материалов (posts), категорий и тегов.

Общий файл (индексный) имеет следующую структуру:
<?xml version="1.0" encoding="UTF-8"?>

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
   <sitemap>
      <loc>http://www.example.com/sitemap1.xml.gz</loc>
      <lastmod>2004-10-01T18:23:17+00:00</lastmod>
   </sitemap>

   <sitemap>
      <loc>http://www.example.com/sitemap2.xml.gz</loc>
      <lastmod>2005-01-01</lastmod>
   </sitemap>

</sitemapindex>
Как можно видеть, данный файл содержит ссылки на 2 отдельных sitemap-файла. Напоминаю, что у нас их будет 3 (для материалов, тегов и категорий).

С назначением и структурой sitemap мы определились, а теперь посмотрим как реализовать его на Laravel-сайте.

По традиции начнем с маршрутов (routes).

Маршруты (routes)

Добавим следующие маршруты в файл web.php:
/* Sitemap */
Route::get('/sitemap', 'SitemapController@index');
Route::get('/sitemap/posts', 'SitemapController@posts');
Route::get('/sitemap/categories', 'SitemapController@categories');
Route::get('/sitemap/tags', 'SitemapController@tags');
Первый маршрут ведет к общему (индексному) файлу, а последующие к 3 отдельным. За все это отвечает общий контроллер SitemapController. Обратите внимание, что мы здесь не указываем расширение .xml. Потому что это не обязательно, но если вы хотите, вы можете добавить это расширение:
Route::get('/sitemap.xml', 'SitemapController@index');
Контроллер SitemapController

Добавим новый контроллер с помощью artisan-команды:
php artisan make:controller SitemapController
Его содержимое будет следующим:
<?php
namespace App\Http\Controllers;

use App\Post;
use App\Category;
use App\Tag;

use Illuminate\Http\Request;

class SitemapController extends Controller
{
    public function index()
	{
	  $post = Post::approved()->orderBy('updated_at', 'desc')->first();
	  $category = Category::approvedPosts()->orderBy('updated_at', 'desc')->first();
	  $tag = Tag::approvedPosts()->orderBy('updated_at', 'desc')->first();

	  return response()->view('sitemap.index', [
	      'post' => $post,
	      'category' => $category,
	      'tag' => $tag,
	  ])->header('Content-Type', 'text/xml');
	}

	public function posts()
	{
	    $posts = Post::approved()->orderBy('updated_at', 'desc')->get();
	    return response()->view('sitemap.posts', [
	        'posts' => $posts,
	    ])->header('Content-Type', 'text/xml');
	}

	public function categories()
	{
	    $categories = Category::approvedPosts()->orderBy('updated_at', 'desc')->get();
	    return response()->view('sitemap.categories', [
	        'categories' => $categories,
	    ])->header('Content-Type', 'text/xml');
	}

	public function tags()
	{
	    $tags = Tag::approvedPosts()->orderBy('updated_at', 'desc')->get();
	    return response()->view('sitemap.tags', [
	        'tags' => $tags,
	    ])->header('Content-Type', 'text/xml');
	}	
}
Здесь у нас 3 метода (index(), posts(), categories(), tags()), отвечающие за формирование 4 sitemap-файлов. В первом методе index() в переменные $post, $category и $tag мы получаем последний материал, категорию и тег, для того чтобы потом в индексном файле заполнить содержимое тега . В данном теге указывается время изменения соответствующего файла Sitemap. Значение тега должно быть представлено в формате W3C Datetime.
Предоставляя отметку времени последнего изменения, Вы позволяете сканерам поисковой системы извлекать только часть файлов Sitemap в индексе, то есть сканер может извлекать только те файлы Sitemap, которые были изменены после определенной даты. Этот механизм частичного извлечения файлов Sitemap позволяет быстро обнаруживать новые URL на сайтах больших размеров. sitemaps.org
Обратите внимание, что во всех 4-х методах контроллера в качестве ответа сервера указывается заголовок:
header('Content-Type', 'text/xml')
Осталось создать файлы видов/представлений (views).

Виды (views)

Я думаю уже понятно, что нам нужно создать 4 вида, 1 для индексного xml-файла и 3 отдельных для материалов (posts), категорий и тегов. Для этого, в первую очередь, в папке views создадим папку sitemap, и уже в нее добавим 4 вида.

Первый вид для индексного xml-файла – index.blade.php:
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>{{ url('sitemap/posts') }}</loc>
        <lastmod>{{ $post->updated_at->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>{{ url('sitemap/categories') }}</loc>
        <lastmod>{{ $category->updated_at->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>{{ url('sitemap/tags') }}</loc>
        <lastmod>{{ $tag->updated_at->toAtomString() }}</lastmod>
    </sitemap>
</sitemapindex>
Вид для xml-файла материалов – posts.blade.php:
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach ($posts as $post)
        <url>
            <loc>{{url("/")}}{{ $post->path() }}</loc>
            <lastmod>{{ $post->updated_at->toAtomString() }}</lastmod>
            <changefreq>monthly</changefreq>
            <priority>1.0</priority>
        </url>
    @endforeach
</urlset>
Вид для xml-файла тегов – tags.blade.php:
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach ($tags as $tag)
        <url>
            <loc>{{ route('tag', $tag->slug) }}</loc>
            <lastmod>{{ $tag->updated_at->toAtomString() }}</lastmod>
            <changefreq>monthly</changefreq>
            <priority>0.8</priority>
        </url>
    @endforeach
</urlset>
Вид для xml-файла категорий – categories.blade.php:
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    @foreach ($categories as $category)
        <url>
            <loc>{{ route('category', $category->slug) }}</loc>
            <lastmod>{{ $category->updated_at->toAtomString() }}</lastmod>
            <changefreq>monthly</changefreq>
            <priority>0.8</priority>
        </url>
    @endforeach
</urlset>
На этом с программированием мы закончили, осталось добавить строчку в файл robots.txt:
Sitemap: https://phpnick.ru/sitemap
Если кто не знает, то файл robots.txt для сайта на Laravel должен находиться в папке public.

Оставьте свой комментарий

Комментарии