chaihongjun.me

thinkphp5.0制作可以自动更新的网站地图sitemap.xml

制作一个良好的网站地图sitemap.xml有助于帮助搜索引擎爬虫了解我们的网站,从SEO角度考虑,是一个有好处的事情,既然有好处就去试试。当然,为了更方便,每次发布新文章的时候网站地图sitemap.xml都会自动更新一次,保证全部需要的链接都有。

首先,规划路由设计:

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

当访问"/sitemap.xml"的时候,会访问index模块内的Sitemap控制器其中的index方法。

接着编写这个控制器代码:

<?php

namespace app\index\controller;
use app\common\controller\HomeBase;

use think\Controller;

// 站点地图class Sitemap extends Controller
class Sitemap extends Controller
{
  public function index()
  {
     generate_sitemap(); //地图生成方法
  }
}

这个控制器负责收集全部的链接,然后写入一个xml文件中,考虑到在文章保存的控制器也需要做这些工作,因此把这些工作整合到一个公共方法内,然后再调用即可,这里访问网站地图的URL就调用生成方法,保存文章控制器也会调用。

再继续在公共方法文件common.php内编写generate_sitemap()方法的具体方法体:

// 生成Sitemap
function generate_sitemap()
{
  
  // get_site_urls()获取全站URL
  $urls = get_site_urls();
  // 开始构建XML内容
  $xml = '<?xml version="1.0" encoding="UTF-8"?>';
  $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
  foreach ($urls as $url) {
    $xml .= '<url>';
    $xml .= '<loc>' . htmlspecialchars($url, ENT_XML1, 'UTF-8') . '</loc>';
    $xml .= '</url>';
  }
  $xml .= '</urlset>';
  //设置响应类型并返回XML内容
  responseXML($xml, 'xml');
}

上面代码是将全站的URL拼接成xml格式的字符串,注意htmlspecialchars这个php内嵌的函数的使用,这个函数将特殊字符转换为对应的HTML实体,以确保XML的正确性和可读性。XML字符串再返回浏览器。那么获取链接还单独需要一个方法去完成:

// 获取站点全部URL列表
function get_site_urls()
{
  $urlsArray = [];
  // 首页
  array_push($urlsArray, 'https://chaihongjun.me');
  // 栏目名称
  $cates = Category::all();
  foreach ($cates as $cate) {
    array_push($urlsArray, 'https://chaihongjun.me/' . $cate->name);
  }
  //文章链接
  $articles = Article::where('status', 1)->select();
  foreach ($articles as $article) {
    $article->url = UrlHelper::generateArticleUrl($article['id']);
    array_push($urlsArray, 'https://chaihongjun.me' . $article['url']);
  }
  return $urlsArray;
}

还需要一个自定义相应的函数用于处理输出的响应头:

// 自定义响应方法,设置Content-Type为application/xml
function responseXML($content, $type = 'html')
{
  if ($type === 'xml') {
    header('Content-Type: application/xml; charset=utf-8');
  }
  echo $content;
  exit;
}

这里根据网站的实际情况去编写,generate_sitemap()要完成的3件事情,其中2个分别又由2个函数实现:

  1.  构建xml内容自己完成

  2.  xml中的链接由get_site_urls()负责

  3. 以正确的形式返回响应由responseXML()完成

上面是访问路由地址,完成了sitemap.xml生成,如果需要自动更新,只需要在文件保持控制器中使用generate_sitemap():

  /**
   * 保存文章
   */
  public function save()
  {
    if ($this->request->isPost()) {
      $data = $this->request->param();
      // dump($data['push_baidu']);
      // break;
      $validate_result = $this->validate($data, 'Article');
      if ($validate_result !== true) {
        $this->error($validate_result);
      } else {
        //文章标题重复检测
        if (article_title_duplicate_detection($data['title'])) {
          // 保存数据库成功
          if ($this->article_model->allowField(true)->save($data)) {
            // 获取当前文章ID
            $article = new ArticleModel;
            $currentArticleId = $article->getLastInsID();
            //推送到百度
            if ($data['push_baidu'] == 1 && $data['status'] == 1) {
              $this->success(baidu_regular_push($currentArticleId, 1));
            }
            // 不推送 直接保存
            else {
              $this->success('文章没有推送百度,保存成功!');
            }
               // 更新网站地图
               generate_sitemap();

          } else {
            $this->error('文章没有推送百度,保存失败');
          }
        } else {
          $this->error('文章标题已经存在!');
        }
      }
    }
  }

特别需要注意的一点,如果服务器针对.xml文件后缀做了缓存等特殊配置,需要去掉:

location ~ \.(html|rtf|rtx|svg|svgz|txt|xsd|xsl|xml)$ { #这里的xml要去掉
    expires 2592000s;
    log_not_found off;
    access_log off;
    add_header Pragma "public";
    add_header Cache-Control "max-age=2592000, public, must-revalidate, proxy-revalidate";
    add_header X-Powered-By "chaihongjun.me";

不然依然404,依然又有更新,增加了sitemap.txt格式的地图生成,generate_sitemap这个函数稍作修改:

function generate_sitemap()
{

  $urls = get_site_urls();

  // 开始构建XML内容
  $xml = '<?xml version="1.0" encoding="UTF-8"?>';
  $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    foreach ($urls as $url) {
    $xml .= '<url>';
        $xml .= '<loc>' . htmlspecialchars($url, ENT_XML1, 'UTF-8') . '</loc>';
        $xml .= '</url>';
    }
    $xml .= '</urlset>';

// 开始构建txt内容
// 要创建和写入的文件名
$sitemapTXT = $_SERVER['DOCUMENT_ROOT'] . "/sitemap.txt";
// 尝试打开文件来写入。如果文件不存在,尝试创建它。
$file = fopen($sitemapTXT, "w") or die("Unable to open file!");
// 写入内容到文件
// 写入每个URL到文件中
foreach ($urls as $url) {
fwrite($file, $url . "\n");
}
fclose($file);

 // 为了保证sitemap.txt文件能顺利生成,xml文件的输出需要放在函数最后执行
// 设置响应类型并返回XML内容
responseXML($xml, 'xml');
}


知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:柴宏俊»