制作一个良好的网站地图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个函数实现:
构建xml内容自己完成
xml中的链接由get_site_urls()负责
以正确的形式返回响应由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'); }