Yii 1.1: esitemap

Generate a sitemap based on configurable Active Records
23 followers

(This information is also found in the included README document)

This extension was inspired by and based on the code originally posted by Jacmoe here: http://www.yiiframework.com/forum/index.php?/topic/670-yiic-sitemap-generation/

Requirements

Built on Yii 1.1.6

Usage

Copy the /sitemap folder into the protected/extensions/ folder.

Move the files from the sitemap/views/ folder (sitemap.php and sitemapxml.php) into the views/site/ folder, or to whichever controller's view folder that you are going to attach the actions to.

Update your controller's actions to include the ESitemapAction and/or ESitemapXMLAction files, as follows:

public function actions()
    {
        return array(
            'sitemap'=>array(
                'class'=>'ext.sitemap.ESitemapAction',
                'importListMethod'=>'getBaseSitePageList',
                'classConfig'=>array(
                    array('baseModel'=>'Task',
                          'route'=>'/task/view',
                          'params'=>array('id'=>'taskId')),         
                ),              
            ),
            'sitemapxml'=>array(
                'class'=>'ext.sitemap.ESitemapXMLAction',
                'classConfig'=>array(
                    array('baseModel'=>'Task',
                          'route'=>'/task/view',
                          'params'=>array('id'=>'taskId')),         
                ),
                //'bypassLogs'=>true, // if using yii debug toolbar enable this line
                'importListMethod'=>'getBaseSitePageList',
            ),          
        );
    };

And, update your URL rules to include a redirect for sitemap.xml:

'urlManager'=>array(
    ...
    'rules'=>array(
        ...
        'sitemap.xml'=>'site/sitemapxml'
    ),
),

The importListMethod allows you to use a custom method on your controller to import a list of non-dynamic page arrays which you wish to include in the sitemap, like so:

class SiteController extends Controller
{
    ....
 
    /**
     * Provide the static site pages which are not database generated
     *
     * Each array element represents a page and should be an array of
     * 'loc', 'frequency' and 'priority' keys
     * 
     * @return array[]
     */
    public function getBaseSitePageList(){
 
        $list = array(
                    array(
                        'loc'=>Yii::app()->createAbsoluteUrl('/'),
                        'frequency'=>'weekly',
                        'priority'=>'1',
                        ),
                    array(
                        'loc'=>Yii::app()->createAbsoluteUrl('/site/contact'),
                        'frequency'=>'yearly',
                        'priority'=>'0.8',
                        ),
                    array(
                        'loc'=>Yii::app()->createAbsoluteUrl('/site/page', array('view'=>'about')),
                        'frequency'=>'monthly',
                        'priority'=>'0.8',
                        ),
                    array(
                        'loc'=>Yii::app()->createAbsoluteUrl('/site/page', array('view'=>'privacy')),
                        'frequency'=>'yearly',
                        'priority'=>'0.3',
                        ),
                );
        return $list;
    }
    ...
}

And finally, the heart of the matter, to include a list of model based links, provide a configuration array to the classConfig property of the action, like so:

'classConfig'=>array(
    array(
        'baseModel'=>'ModelNameOne',
        'route'=>'/route/to/controller',
        'params'=>array('property_key'=>'attribute_name')
        ),
    array(
        'baseModel'=>'Post',
        'route'=>'/post/view',
        'params'=>array('id'=>'postId')
        'scopeName'=>'sitemap'
    ),
)

To utilize the ActiveRecord, you need to have a scope named 'sitemap' which will select the proper criteria, or specify an alternate scopeName like so:

'classConfig'=>array(
    array(
        'baseModel'=>'Post',
        'route'=>'/post/view',
        'params'=>array('id'=>'postId')
        'scopeName'=>'approvedPosts'
    ),
)

Additional Class Configuration options: priority, changefreq (see ESitemapModel)

Sample scope:

public function scopes()
{
    return array(
        'sitemap'=>array('select'=>'id', 'condition'=>'startDate <= NOW()', 'order'=>'dateAdded ASC'),
    );
}

As of Version 1.1: To import models from a module, add an import array to the main configuration for the CAction.

'import'=>array('moduleName.models.*'),

Future Enhancements

  • Cached output: I'd like to add a param to the configuration that will specify how frequently the sitemap will be rebuilt, and create a flat XML output file which will be checked for expiration and if fresh, served, else rebuilt. That's a project for another day though ;)
  • Make the scopeName optional and/or validate that the scopeName exists on the model.

All feedback is welcome! I tried to simplify the syntax as much as possible, but it was hard to get my head around all the possible options that might be desired and still create something that would meet a wide range of needs in a single extension.

Resources

Forum Discussion on ESitemap

ESitemap on GitHub

Releases

Version 1.0 - Initial Release Version 1.01 - Php 5.3.0 Strict Compliance Version 1.1 - Module specific model import functionality

Total 9 comments

#15116 report it
Andres Felipe Diaz at 2013/10/08 02:27pm
Thank you very much!

Hello Dana,

This worked like a breeze. The documentation was very straighforward for us. The only thing we had to do was make sure our access filters which by default deny all requests on action would allow sitemap and sitemapxml actions.

You saved us a lot of time!

Best,

Andrés themidgame.com

#8481 report it
julianm at 2012/06/06 05:33pm
Sitemap with slug

Hi, ok sorry for the buzz but I finally got it. I was missing the slug in the select. It was supposed to use this:

'sitemap'=>array('select'=>'id, slug',...

in the scopes() function. Now it is working fine and I was able to use the permalink in the sitemap. Awesome. You can see a real working version here: SlideOnline.com

#8480 report it
julianm at 2012/06/06 04:59pm
Worked straightforward

Thanks. Great extension.

I was wondering something. Would be possible to use an alternative URL with permalink instead of the route URL?

Do you have any hint about how this can be implemented?

For example, in my case I have this URL that is formed by an ID and a slug value that is also in the model.

/presentation/76-slug/

But I ended with this url in the sitemap instead:

/presentation/76/

I also tried to pass slug as a parameter 'params'=>array('id'=>'id', 'slug'=>'slug'), but was no good. :(

#3495 report it
bigbasher at 2011/04/15 09:44am
Thanks!

I get it - wasnt obvious at first read. Thanks!

#3493 report it
Dana at 2011/04/15 07:16am
Re: bigbasher

You want to place that array as part of the SiteController actions method array, like so:

SiteController {
...
   public function actions()
   {
        return array(
            'sitemap'=>array(
                'class'=>'ext.sitemap.ESitemapAction',
                'importListMethod'=>'getBaseSitePageList',
                /* REPLACE THIS classConfig ARRAY WITH WHAT YOU NEED */
                'classConfig'=>array(
                    array('baseModel'=>'Task',
                          'route'=>'/task/view',
                          'params'=>array('id'=>'taskId')),         
                ),             
            ),
            'sitemapxml'=>array(
                'class'=>'ext.sitemap.ESitemapXMLAction',
                /* PUT THE SAME ARRAY HERE FOR THE XML VERSION */
                'classConfig'=>array(
                    array('baseModel'=>'Task',
                          'route'=>'/task/view',
                          'params'=>array('id'=>'taskId')),         
                ),
                //'bypassLogs'=>true, // if using yii debug toolbar enable this line
                'importListMethod'=>'getBaseSitePageList',
            ),          
        );
    }

Does that clarify at all?

#3492 report it
bigbasher at 2011/04/15 06:12am
The heart of the matter code

'classConfig'=>array( array( 'baseModel'=>'ModelNameOne', 'route'=>'/route/to/controller', 'params'=>array('property_key'=>'attribute_name') ), array( 'baseModel'=>'Post', 'route'=>'/post/view', 'params'=>array('id'=>'postId') 'scopeName'=>'sitemap' ), )

#3491 report it
bigbasher at 2011/04/15 06:11am
And finally, the heart of the matter, ...

Sorry to be thick but its not clear to me where this code should be placed.

#3370 report it
logity at 2011/04/06 05:07pm
Pagination

Good idea, also I would suggest to add smth like ESitemapPaginator and to extend

array(
        'baseModel'=>'Post',
        'scopeName'=>'approvedPosts',
        'view' => array(
            'route'=>'/post/view',
            'params'=>array('id'=>'postId')
        ),
        'list' => array(
            'route' => '/post/list'
            'pageSize' => 20 
             // etc
         ),
    ),
#3044 report it
Dana at 2011/03/09 06:27pm
Added a little more documentation

Sorry I rushed through putting the documentation in and missed a few things. It should all be up to date now!

Leave a comment

Please to leave your comment.

Create extension