Yii2 component for generate sitemap.xml files
Run
composer require "demi/sitemap-generator" "~1.0"
Edit "/console/config/main.php"
return [
'controllerMap' => [
'sitemap' => [
'class' => 'demi\sitemap\SitemapController',
'modelsPath' => '@console/models/sitemap', // Sitemap-data models directory
'modelsNamespace' => 'console\models\sitemap', // Namespace in [[modelsPath]] files
'savePathAlias' => '@frontend/web', // Where would be placed the generated sitemap-files
'sitemapFileName' => 'sitemap.xml', // Name of main sitemap-file in [[savePathAlias]] directory
],
],
];
Because generator working in console, Yii create absolute url should know site base url, so configure it: "./environments/prod/console/config/main-local.php"
'components' => [
// fix console create url
'urlManager' => [
'baseUrl' => 'http://example.com',
],
],
"./environments/dev/console/config/main-local.php"
'components' => [
// fix console create url
'urlManager' => [
'baseUrl' => 'http://example.local',
],
],
The re-init project local config:
php ./init
OR just apply same config to your "/console/config/main-local.php"
Also you can merge urlManager rules from frontend(or common) to console config.
Just change "/console/config/main.php" file:
// get config of urlManager from frontend for correctly create urls in console app
$frontend = require(__DIR__ . '/../../frontend/config/main.php');
return [
'id' => 'app-console',
'components' => [
'urlManager' => $frontend['components']['urlManager'],
],
];
Also useful append .gitignore for ignore all generated sitemaps files:
# sitemaps
/frontend/web/sitemap*.xml
You should create special sitemap-models for each your model, that should be in result sitemap.xml.
So let's create a maximal sitemap model extended from you Post
model and attach interfaces:
/console/models/sitemap/SitemapPost.php
<?php
namespace console\models\sitemap;
use Yii;
use yii\helpers\Url;
use common\models\Post;
use demi\sitemap\interfaces\Basic;
use demi\sitemap\interfaces\GoogleAlternateLang;
use demi\sitemap\interfaces\GoogleImage;
class SitemapPost extends Post implements Basic, GoogleImage, GoogleAlternateLang
{
/**
* Handle materials by selecting batch of elements.
* Increase this value and got more handling speed but more memory usage.
*
* @var int
*/
public $sitemapBatchSize = 10;
/**
* List of available site languages
*
* @var array [langId => langCode]
*/
public $sitemapLanguages = [
'en',
'ru-RU',
];
/**
* If TRUE - Yii::$app->language will be switched for each sitemapLanguages and restored after.
*
* @var bool
*/
public $sitemapSwithLanguages = true;
/* BEGIN OF Basic INTERFACE */
/**
* @inheritdoc
*/
public function getSitemapItems($lang = null)
{
// Add to sitemap.xml links to regular pages
return [
// site/index
[
'loc' => Url::to(['/site/index', 'lang' => $lang]),
'lastmod' => time(),
'changefreq' => static::CHANGEFREQ_DAILY,
'priority' => static::PRIORITY_10,
'alternateLinks' => [
'en' => Url::to(['/site/index', 'lang' => 'en']),
'ru' => Url::to(['/site/index', 'lang' => 'ru']),
],
],
// post/index
[
'loc' => Url::to(['/post/index', 'lang' => $lang]),
'lastmod' => time(),
'changefreq' => static::CHANGEFREQ_DAILY,
'priority' => static::PRIORITY_10,
'alternateLinks' => [
'en' => Url::to(['/post/index', 'lang' => 'en']),
'ru' => Url::to(['/post/index', 'lang' => 'ru']),
],
],
// ... you can add more regular pages if needed, but I recommend
// separate pages related only for current model class
];
}
/**
* @inheritdoc
*/
public function getSitemapItemsQuery($lang = null)
{
// Base select query for current model
return static::find()
->select(['id', 'title', 'date', 'updated_at'])
->where(['status' => Post::STATUS_ACTIVE])
->orderBy(['date' => SORT_DESC]);
}
/**
* @inheritdoc
*/
public function getSitemapLoc($lang = null)
{
// Return absolute url to Post model view page
return Url::to(['/post/view', 'id' => $this->id], true);
}
/**
* @inheritdoc
*/
public function getSitemapLastmod($lang = null)
{
return $this->updated_at;
}
/**
* @inheritdoc
*/
public function getSitemapChangefreq($lang = null)
{
return static::CHANGEFREQ_MONTHLY;
}
/**
* @inheritdoc
*/
public function getSitemapPriority($lang = null)
{
return static::PRIORITY_8;
}
/* END OF Basic INTERFACE */
/* BEGIN OF GoogleImage INTERFACE */
/**
* @inheritdoc
*
* @param self $material
*/
public function getSitemapMaterialImages($material, $lang = null)
{
// List of Post related images without scheme (news logo eg.)
$images = [];
// "/uploads/post/1.jpg"
$images[] = $this->logo;
// You can add more images (if Post have a photo gallery etc.)
// !important! You can return array of any elements(Objects eg. $this->images relation), because its elements
// will be foreached and become as $image argument for $this->getSitemapImageLoc($image)
return $images;
}
/**
* @inheritdoc
*/
public function getSitemapImageLoc($image, $lang = null)
{
// Return absolute url to each Post image
// @see $image argument becomes from $this->getSitemapMaterialImages()
return Yii::$app->urlManager->baseUrl . $image;
}
/**
* @inheritdoc
*/
public function getSitemapImageGeoLocation($image, $lang = null)
{
// Location name string, for example: "Limerick, Ireland"
return null;
}
/**
* @inheritdoc
*/
public function getSitemapImageCaption($image, $lang = null)
{
// Image caption, simply use Post title
return $this->title;
}
/**
* @inheritdoc
*/
public function getSitemapImageTitle($image, $lang = null)
{
// Image title, simply use Post title
return $this->title;
}
/**
* @inheritdoc
*/
public function getSitemapImageLicense($image, $lang = null)
{
return null;
}
/* END OF GoogleImage INTERFACE */
/* BEGIN OF GoogleAlternateLang INTERFACE */
/**
* @inheritdoc
*/
public function getSitemapAlternateLinks()
{
// Generate altername links for all site language versions for this Post
$buffer = [];
foreach ($this->sitemapLanguages as $langCode) {
$buffer[$langCode] = $this->getSitemapLoc($langCode);
// or eg.: $buffer[$langCode] = Url::to(['post/view', 'id' => $this->id, 'lang' => $langCode]);
}
return $buffer;
}
/* END OF GoogleAlternateLang INTERFACE */
}
If you sitemap model doesn't have images or only one site language - just remove interfaces
GoogleImage
and/or GoogleAlternateLang
and it's functions.
Generator automaticly searching all your sitemap models by config path: /console/models/sitemap/*
Run Yii console command in project root:
./yii sitemap
then check "http://site/sitemap.xml" file
Comments