Yii如何实现Sitemap的自动生成XML文件的2种方法

jerry Yii 2015年08月18日 收藏

第一种方法:

<?php
class Sitemap extends CController{
    protected $webSiteTitle = '';
    protected $changefreq = '';
    protected $content = '';
    protected $priority = '';
    protected $blogItems = array();
    protected $tagItems = array();
    protected $categoryItems = array();
    protected $items = array();
    /**
     * 添加基本信息
     * @param string $title
     * @param string $link
     * @param string $description
     */
    public function __construct() {
           $this->webSiteTitle = 'http://'.$_SERVER['SERVER_NAME'];
           $this->changefreq = 'daily';//always hourly daily weekly monthly yearly never
           $this->priority = 0.5;
       }
    /**
     * 分类
     */
    private function categorySitemap(){
        $criteria = new CDbCriteria();
        $criteria->condition = 'category=:category';
        $criteria->params = array(':category'=>'blog');
        $criteria->order = 'create_date DESC';
        $result = Type::model()->findAll($criteria);
        foreach($result as $k=>$v){
            $this->categoryItems[] = array(
                'url'=>$this->webSiteTitle.'/category/'.urlencode($v->name),
                'date'=>date(DATE_W3C, strtotime($v->update_date))
            );
        }
    }
    /**
     * 文章
     */
    private function blogSitemap(){
        $criteria = new CDbCriteria();
        $criteria->condition = 'is_lock=0 and is_delete=0';
        $criteria->select = 'id, tag, update_date';
        $criteria->order = 'create_date DESC';
        $model = Blog::model()->findAll($criteria);
        foreach($model as $k=>$v){
            $this->blogItems[] = array(
                'url'=>$this->webSiteTitle.'/blog/'.$v->id,
                'date'=>date(DATE_W3C, strtotime($v->update_date))
            );
            $tagArr = preg_split('#,|,#i', $v->tag);
            if(!empty($tagArr)){
                foreach($tagArr as $k=>$v){
                    if(!in_array($v,$this->tagItems)){
                        $this->tagItems[] = $v;
                    }
                }
            }
        }
        //创建临时函数数组
        $tmp = array();
        $tmp = $this->tagItems;
        $this->tagItems = array();
        foreach($tmp as $k=>$v){
            $this->tagItems[] = array(
                'url'=>$this->webSiteTitle.'/tag/'.urlencode($v),
                'date'=>date(DATE_W3C, time())
            );
        }
        unset($tmp);
    }
    /**
     * 构建xml元素
     */
     public function buildSitemap() {
        $blogitem = '';
        foreach($this->blogItems as $k=>$v){
            $blogitem .= <<<BLOG
            <url>\r\n
                <loc>{$v['url']}</loc>\r\n
                <lastmod>{$v['date']}</lastmod>\r\n
                <changefreq>{$this->changefreq}</changefreq>\r\n
                <priority>{$this->priority}</priority>\r\n
            </url>\r\n
BLOG;
        }
        $categoryitem = '';
        foreach($this->categoryItems as $k=>$v){
            $categoryitem .= <<<BLOG
            <url>\r\n
                <loc>{$v['url']}</loc>\r\n
                <lastmod>{$v['date']}</lastmod>\r\n
                <changefreq>{$this->changefreq}</changefreq>\r\n
                <priority>{$this->priority}</priority>\r\n
            </url>\r\n
BLOG;
        }
        $tagitem = '';
        foreach($this->tagItems as $k=>$v){
            $tagitem .= <<<BLOG
            <url>\r\n
                <loc>{$v['url']}</loc>\r\n
                <lastmod>{$v['date']}</lastmod>\r\n
                <changefreq>{$this->changefreq}</changefreq>\r\n
                <priority>{$this->priority}</priority>\r\n
            </url>\r\n
BLOG;
        }
        $this->content = <<<SITEMAP
<?xml version='1.0' encoding='UTF-8'?>\r\n
<?xml-stylesheet type="text/xsl" href="{$this->webSiteTitle}/sitemap.xsl"?>
<!-- generator="GoWhich/1.0" -->
<!-- sitemap-generator-url="{$this->webSiteTitle}" sitemap-generator-version="1.0.0" -->
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r\n
        xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"\r\n
        xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\r\n
            {$blogitem}
            {$categoryitem}
            {$tagitem}
</urlset>\r\n
SITEMAP;
       }
  /**
   * 输出sitemap内容
   */
  function show() {
        $this->blogSitemap();
        $this->categorySitemap();
        if (empty($this->content)) {
            $this->buildSitemap();
        }
           return $this->content;
  }
  /**
   * 将rss保存为文件
   * @param String $fname
   * @return boolean
   */
       function saveToFile($fname) {
           $handle = fopen($fname, 'wb');
           if ($handle === false){
               return false;
           }
           fwrite($handle, $this->content);
           fclose($handle);
       }
       /**
        * 获取文件的内容
        * @param String $fname
        * @return boolean
        */
       function getFile($fname) {
           $handle = fopen($fname, 'r');
           if ($handle === false){
               return false;
           }
        while(!feof($handle)){
            echo fgets($handle);
        }
           fclose($handle);
       }
}
?>
Controller中我建立了两个action 
/**
 * sitemap列表
 */
public function actionSitemap(){
    //rss创建
    $obj = new Sitemap();
    $this->render('sitemap',array('rss'=>$obj->show()));
}
public function actionSitemapXsl(){
    $this->render('sitemapxsl');
}
View的两个文件的代码如下
sitemap.php 
<?php
/* @var $this FeedController */
header("Content-Type: text/xml; charset=utf-8");
echo $rss;
exit;
?>
sitemapxsl.php 
<?php
header("Content-Type: text/xml; charset=utf-8");
?>
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:html="http://www.w3.org/TR/REC-html40"
                xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>XML Sitemap</title>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <style type="text/css">
                body {
                    font-family:"Lucida Grande","Lucida Sans Unicode",Tahoma,Verdana;
                    font-size:13px;
                }
                #intro {
                    background-color:#CFEBF7;
                    border:1px #2580B2 solid;
                    padding:5px 13px 5px 13px;
                    margin:10px;
                }
                #intro p {
                    line-height:    16.8667px;
                }
                td {
                    font-size:11px;
                }
                th {
                    text-align:left;
                    padding-right:30px;
                    font-size:11px;
                }
                tr.high {
                    background-color:whitesmoke;
                }
                #footer {
                    padding:2px;
                    margin:10px;
                    font-size:8pt;
                    color:gray;
                }
                #footer a {
                    color:gray;
                }
                a {
                    color:black;
                }
            </style>
        </head>
        <body>
        <h1>XML Sitemap</h1>
        <div id="intro">
            <p>
                This is a XML Sitemap which is supposed to be processed by search engines like <a href="http://shouce.ren">Google</a>, <a href="http://search.msn.com">MSN Search</a> and <a href="http://www.yahoo.com">YAHOO</a>.<br />
                It was generated using the Blogging-Software <a href="http://gowhich.com/">GoWhich</a> and the <a href="http://www.gowhich.com/sitemap.xml" title="Google Sitemap Generator Plugin for GoWhich">Google Sitemap Generator Plugin</a> by <a href="http://www.gowhich.com/">GoWhich</a>.<br />
                You can find more information about XML sitemaps on <a href="http://sitemaps.org">sitemaps.org</a> and Google's <a href="http://code.google.com/sm_thirdparty.html">list of sitemap programs</a>.
            </p>
        </div>
        <div id="content">
            <table cellpadding="5">
                <tr style="border-bottom:1px black solid;">
                    <th>URL</th>
                    <th>Priority</th>
                    <th>Change Frequency</th>
                    <th>LastChange (GMT)</th>
                </tr>
                <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
                <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
                <xsl:for-each select="sitemap:urlset/sitemap:url">
                    <tr>
                        <xsl:if test="position() mod 2 != 1">
                            <xsl:attribute  name="class">high</xsl:attribute>
                        </xsl:if>
                        <td>
                            <xsl:variable name="itemURL">
                                <xsl:value-of select="sitemap:loc"/>
                            </xsl:variable>
                            <a href="{\$itemURL}">
                                <xsl:value-of select="sitemap:loc"/>
                            </a>
                        </td>
                        <td>
                            <xsl:value-of select="concat(sitemap:priority*100,'%')"/>
                        </td>
                        <td>
                            <xsl:value-of select="concat(translate(substring(sitemap:changefreq, 1, 1),concat(\$lower, \$upper),concat(\$upper, \$lower)),substring(sitemap:changefreq, 2))"/>
                        </td>
                        <td>
                            <xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(' ', substring(sitemap:lastmod,12,5)))"/>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </div>
        <div id="footer">
            Generated with <a href="http://www.gowhich.com/sitemap.xml" title="Google Sitemap Generator Plugin for GoWhich">Google Sitemap Generator Plugin for GoWhich</a> by <a href="http://www.gowhich.com/">GoWhich</a>. This XSLT template is released under GPL.
        </div>
        </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
XML;
echo $xml;
exit;
?>

为了使得url看起来好看一点。
我做了一下路由设置

'sitemap.xsl'=>'site/sitemapxsl',
'sitemap.xml'=>'site/sitemap',

第二种方法:

yii-sitemap-generator 是一个生成网站 sitemap 的 Yii 框架 扩展
如何使用
1. 下载文件解压到 /protected/extensions 文件夹下
2. 修改配置文件 /protected/config/main.php, 如下

'components'=>array(
    ...
    'sitemap'=>array(
        'class'=>'ext.yii-sitemap-generator.Sitemap',
        'basePath'=>dirname(__DIR__).'/www',
        'urls'=>array(
            array('site/index','frequency'=>'always','priority'=>'1.0'),
            array('site/page','view'=>'about','frequency'=>'always','priority'=>'1.0'),
            array('site/contact','frequency'=>'weekly','priority'=>'0.2'),
            array('model'=>'Post','url'=>array('post/view','id'=>'id'),'frequency'=>'daily','priority'=>'0.2'),
        )
    ),
    ...
)

其中,urls 的格式分为两种
1). 基于模型的 URL,如上面的
array('model'=>'Post','url'=>array('post/view','id'=>'id'),'frequency'=>'daily','priority'=>'0.2')
model 表示模型的类名; url 构建 URL,数组第一位相当与 yii 的 route,后面的参数使用 K=>V 值对,K表示参数名,V表示模型中的 V 属性值,如上面的 V id 指的是 Post 模型实例化对象的 id 属性值;frequency 表示更新频次,与sitemap语法中的changefreq 相同;priority 表示权重,与 sitemap 中的 priority 相同。2). 基本 URL 如上面的
array('site/page','view'=>'about','frequency'=>'always','priority'=>'1.0')
frequency 和 priority 与上面相同,注意的是,数组第一项必须为 yii 的 route
3. 在 consloe 中生成
创建 protected/commands/SitemapCommand.php

<?php
class SitemapCommand extends CConsoleCommand {
    public function actionIndex() {
        $sitemap = Yii::app()->sitemap;
        $sitemap->generate();
    }
}

运行命令 yiic sitemap 就可以生成站点 Sitemap 了,你可以创建一个cron job 定时执行这个命令,达到定时更新 sitemap 的目的
在 Controller 中生成的使用方法也是一样,直接使用 Yii::app()->sitemap 就可以返回 Sitemap 类了。
yii-sitemap-generator 下载

下载地址