sitemap 文件填充示例代码
最近制作网站的 sitemap ,要求每个 txt 文件包含不超过 5w 条 url 。包括 www 站 与 m 站,http 与 https ,即要同时制作四份 sitemap ,并每日自动更新。
CREATE TABLE `z_sitemaps` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`txt_area` enum('m','www') NOT NULL DEFAULT 'www',
`txt_order` int(10) unsigned NOT NULL COMMENT '文件名称 1.txt 2.txt ..',
`url_sum` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '包含的url数量',
`complete` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否填充完毕',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
<?php
namespace App\Library\Other;
use DB;
/**
* 整理 sitemap 文件
* 制作 sitemap xml 地图
*/
class Sitemap {
private $max_num; // 单个sitemap最大url个数
private $area; // www | m
private $https_dir; // 存放路径
private $sync_xml_dir; // sitemap xml地图
// 规范:所有dir路径必须以/结尾
public function __construct(string $area){
$this->max_num = 49900;
$this->area = in_array($area, ['www','m']) ? $area : 'www';
$this->https_dir = public_path().'/sitemaps/'.$area.'/https/';
$this->sync_xml_dir = public_path().'/sitemaps/';
}
/*
* @param $urls url数组
* @return 所放入的文件路径,多个文件以;分隔
*/
public function createSitemap(array $urls){
$count = count($urls);
if($count > $this->max_num){return false;}
$sitemap = $this->searchSitemap();
$expect_num = 49900 - $sitemap->url_sum;
$put_files = [];
// 文件数量小于期望值直接填充
if($count <= $expect_num){
$file_name = $this->fillSitemap($sitemap, $urls);
$put_files[] = $file_name;
}else{
// 先将未填满的sitemap文件填满
$slice_arr = array_slice($urls, 0, $expect_num);
$file_name = $this->fillSitemap($sitemap, $slice_arr);
$put_files[] = $file_name;
// 再将剩余的添加到新文件
$remain = array_slice($urls,$expect_num);
$sitemap = $this->newSitemap();
$file_name = $this->fillSitemap($sitemap, $remain);
$put_files[] = $file_name;
}
return implode(';', $put_files);
}
/*
* 查找尚未填充完毕的sitemap文件
* @return 一条表记录
*/
public function searchSitemap(){
$sitemap = DB::table('z_sitemaps')->where('txt_area',$this->area)->where('complete',0)->where('url_sum','<',$this->max_num)->orderBy('id','desc')->first();
return $sitemap ? $sitemap : $this->newSitemap();
}
/*
* 建立空sitemap文件
* @return 一条数据记录
*/
public function newSitemap(){
// 最大文件名
$max_order = DB::table('z_sitemaps')->where('txt_area',$this->area)->max('txt_order');
// 最大文件名+1 则是下一个文件名
if(!$max_order){ $max_order = 1;} else { $max_order = $max_order + 1;}
// public/sitemaps/{www|m}/https/1.txt
$file_name = $this->getSitemapFilename($max_order);
// 建立空文件
file_put_contents($file_name, '');
// 同时添加表记录对应文件名
$sitemap_id = DB::table('z_sitemaps')->insertGetId([
'txt_area' => $this->area,
'txt_order' => $max_order,
'created_at' => date('Y-m-d H:i:s', time()),
]);
return DB::table('z_sitemaps')->where('id',$sitemap_id)->first();
}
/*
* @param $sitemap 一条表记录
* @param $urls url数组
* @return 已保存的sitemap文件地址
*/
public function fillSitemap($sitemap, array $urls){
$count = count($urls);
$url_list = implode("\n", $urls)."\n";
$file_name = $this->getSitemapFilename($sitemap->txt_order);
$rs = file_put_contents($file_name, $url_list, FILE_APPEND);
$current = $sitemap->url_sum + $count;
$is_complete = $current >= $this->max_num ? 1 : 0;
DB::table('z_sitemaps')->where('id',$sitemap->id)->update([
'url_sum' => $current,
'updated_at' => date('Y-m-d H:i:s', time()),
'complete' => $is_complete,
]);
// 同时生成 http 格式
$this->syncHttpsToHttp($file_name);
return $file_name;
}
// 文件真实路径
public function getSitemapFilename($txt_order){
return $this->https_dir.$txt_order.'.txt';
}
// 同步https目录中的sitemap文件到http目录
// 注意:https目录与http目录必须是同级目录
public function syncHttpsToHttp($file_name)
{
$str = file_get_contents($file_name);
if($str){
$http_str = str_replace('https','http',$str);
$http_dir_path = str_replace('https', 'http', $file_name);
file_put_contents($http_dir_path, $http_str);
}
}
//生成sitemap地图 XML格式
public function sitemapXml($is_http=0)
{
$area = $this->area;
$http = $is_http ? 'http' : 'https';
$strxml = '<sitemapindex></sitemapindex>';
$xmlobj = new \SimpleXMLElement($strxml);
$sitemaps = DB::table('z_sitemaps')->where('txt_area',$area)->orderBy('id','desc')->get();
foreach ($sitemaps as $v) {
$loc = 'https://xxxx.com/sitemaps/'.$http.'/'.$v->txt_order.'.txt';
$lastmod = $v->updated_at;
$sitemap = $xmlobj->addChild('sitemap');
$sitemap->addChild('loc',$loc);
$sitemap->addChild('lastmod',$lastmod);
}
$file_path = '...';
$xmlobj->asXML($file_path);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接