用 Laravel 简单制作 Sitemap

几年前,搜索引擎就已经鼓励人们提交的 Sitemap 来帮助搜索引擎索引你的网站。直到现在,研究如何提交 Sitemap 这件事情依旧很值得学习。

为了翻译好原文,我花了一点时间研究了 Sitemap,并把我知道的整理出来。

什么是 Sitemap

Google 为其作了定义:

Sitemap 是一个文件,在其中列出网站的网页,告诉 Google 和其他搜索引擎你的网站内容的组织情况。 当 Googlebot 等搜索引擎网络抓取工具读取到这个文件,就会更智能地抓取你的网站。

他们还概述了一些为什么你要提交这个文件的原因:

  • 如果你的网站很大,Google 网页抓取工具可能会忽略一些新的或最近更新的网页。
  • 你的网站有大量的内容页存档,这些内容页彼此隔离或完全没有相互关联。如果你的网站网页不会自然地相互引用,则可以在 Sitemap 中列出这些网页,以确保 Google 不会忽略某些网页。
  • 如果你的网站是新的,而且指向网站的链接不多。Googlebot 和其他网络抓取工具会随着链接从一个网页到另一个网页来抓取网络。因此,如果没有其他网站链接到你的网页,Google 可能很难发现你的网页。
  • 如果你的网站使用大量富 AJAX 或 Flash 内容的页面,则不容易被 Googlebot 发现。但如果是显示在 Google 新闻中,或使用其他与 Sitemap 兼容的注释。Google 就可以根据需要将 Sitemap 中的其他信息纳入搜索范围。

你的网站可能不符合上述难以抓取的原因,但我觉得,就算只是出于网站安全的考虑,提交一个 Sitemap 也是值得的。

Sitemap 协议

在官方 Sitemaps 网站上,它列出了构建 Sitemap 所需的所有信息。下面是 XML 格式的基本示例:

<?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> 

如你所见,Sitemap 只是一个 XML 文件,而且每个网站页面都有一个 <url>

单个 XML 文件大约可以容纳 50,000 条记录,但是你也可以将它们分成多个文件,并利用索引文件指向其他文件。当然官网也有简单的示例介绍:

<?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>

在每个 <loc> 内,它指向包含 <url> 项目的 XML 文件,如第一个示例中所示。

本教程使用了索引样式,用来自不同表的记录,自定义每个 URL 列表,从而无需进行额外的处理。

构建 Sitemap 控制器

我的 Sitemap 会有两个主要部分,分别是博客文章、博客类别和播客列表。 每个部分都会在属于自己的文件中,并且有索引将指向它们。

首先,用下面的指令创建 Sitemap 的控制器:

php artisan make:controller SitemapController

现在打开这个文件,我们创建一个 Sitemap 索引。

创建 Sitemap 索引

下面是创建一个新的索引方法,这个方法会生成所需的 XML:

public function index()
{
  $post = Post::active()->orderBy('updated_at', 'desc')->first();
  $podcast = Podcast::active()->orderBy('updated_at', 'desc')->first();

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

发布和播客查询需要在索引视图中生成最后修改的时间戳,这样才能让抓取工具知道是否添加了新的内容。

另外,header() 这个返回样式可能甚少用到,我在这里解释下:它返回一个响应对象,分配视图的同时把 header 设置为 text/xml 。 如果你只返回一个 view() ,就无法访问到 XML 文件。

接下来,我们的 sitemap.index 视图文件将如下所示:

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <sitemap>
        <loc>https://laravel-news.com/sitemap/posts</loc>
        <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>https://laravel-news.com/sitemap/categories</loc>
        <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap>
    <sitemap>
        <loc>https://laravel-news.com/sitemap/podcasts</loc>
        <lastmod>{{ $podcast->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
    </sitemap
</sitemapindex>

在这个视图里,我只是采取我自定义的 publishes_at 时间戳,使用 Carbon  设置时区为 UTC,最后使用 Carbon Atom 字符串将格式正确化。

创建 Sitemap URL 文件

下一步是创建每个 URL 的文件。 在 SitemapController 控制器里写三个相似的新方法。 如下:

public function posts()
{
    $posts = Post::active()->where('category_id', '!=', 21)->get();
    return response()->view('sitemap.posts', [
        'posts' => $posts,
    ])->header('Content-Type', 'text/xml');
}

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

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

接着创建一个视图文件 sitemap.posts :

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    [@foreach](https://learnku.com/users/5651) ($posts as $post)
        <url>
            <loc>https://laravel-news.com/{{ $post->uri }}</loc>
            <lastmod>{{ $post->publishes_at->tz('UTC')->toAtomString() }}</lastmod>
            <changefreq>weekly</changefreq>
            <priority>0.6</priority>
        </url>
    @endforeach
</urlset>

同样地复制好其他视图之后就写路由:

Route::get('/sitemap', 'SitemapController@index');
Route::get('/sitemap/posts', 'SitemapController@posts');
Route::get('/sitemap/categories', 'SitemapController@categories');
Route::get('/sitemap/podcasts', 'SitemapController@podcasts');

你可能注意到我选择不使用 XML 文件扩展名,这不是必须的。不过如果你喜欢,可以添加扩展名到路由:

Route::get('/sitemap.xml', 'SitemapController@index');

最后只需调整视图以指向正确的位置。

小结

用 Laravel 写 Sitemap 并不是很难,特别是当你的网站结构像我的一样简单。 如果你想自动化整个进程,用这个包 也是比较方便的。

当然还可以建立有 图像视频 的 Sitemap,甚至你还可以创建自己的 XSL 样式表

以上内容翻译改编自 Eric L. Barnes 的 Building a Search Engine Friendly Sitemap XML with Laravel

本作品采用《CC 协议》,转载必须注明作者和本文链接
Stay Hungry, Stay Foolish.
本帖由系统于 6年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1
月光

Get it !

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!