Создание карты сайта для пользовательской модели
Я разработал специальный модуль, в котором перечислены несколько человек на сайте. У каждого человека есть свой собственный URL-адрес (индивидуальный контроллер Magento, который выполняет базовую работу с моделями людей), и мне нужно ввести эти общедоступные URL-адреса в XML-файл Google Sitemap.
Я хочу использовать собственное создание карты сайта Magento и cron, если смогу.
Mage_Sitemap_Model_Observer
уже извлекает все записи Sitemap из таблицы sitemaps
и один за другим вызывает их generateXml()
методы.
$collection = Mage::getModel('sitemap/sitemap')->getCollection();
/* @var $collection Mage_Sitemap_Model_Mysql4_Sitemap_Collection */
foreach ($collection as $sitemap) {
/* @var $sitemap Mage_Sitemap_Model_Sitemap */
try {
$sitemap->generateXml();
}
catch (Exception $e) {
$errors[] = $e->getMessage();
}
}
Я думаю, что мне нужно добавить мою новую карту сайта в таблицу sitemaps
, которая затем будет вызвана для создания моего (отдельного) XML-файла для записей моей пользовательской модели. Однако я не знаю, как сказать Magento использовать мой расширенный My_Module_Model_Sitemap
вместо просто Mage_Sitemap_Model_Sitemap
, последний из которых просто предоставит мне XML-файл со списком всех тех же категорий, продуктов и страниц CMS, что и основные карты сайта.
В таблице sitemaps
есть столбец sitemap_type
, но на него никогда не ссылаются в кодовой базе Magento как насколько я могу судить.
Как я могу использовать встроенный механизм карты сайта Magento при перезаписи Mage_Sitemap_Model_Sitemap
, чтобы иметь свой собственный метод generateXml()
? Или я должен создать альтернативную систему sitemap только для своих собственных целей здесь?
3 answers
Шаги, которые я в итоге использовал, были следующими, и комментарии и ответы до сих пор помогали мне двигаться в правильном направлении.
Сначала я добавил строку в таблицу "карта сайта". Поскольку у нас настроено несколько магазинов, и поскольку я хочу сохранить свой магазин модулей независимым, я не стал жестко кодировать эту вставку в миграцию MySQL, а просто запустил ее в магазине вручную:
INSERT INTO sitemap (sitemap_type, sitemap_filename, sitemap_path, store_id)
VALUES ('people', 'people.xml', '/sitemap/', 2);
Затем я переписал модель Mage_Sitemap_Model_Sitemap
внутри раздела global/models в моем собственном модуле config.xml файл:
<global>
<models>
<sitemap>
<rewrite>
<sitemap>Mymod_People_Model_Sitemap</sitemap>
</rewrite>
</sitemap>
</models>
</global>
Это перезаписывает любые вызовы Mage_Sitemap_Model_Sitemap
по всему сайту с помощью моей пользовательской модели, но я не хотел копировать и вставлять туда слишком много кода. Используя предложение Петара Джамбазова, я использовал условное условие для переноса на родительский класс, если только sitemap_type
не является "людьми".
class Mymod_People_Model_Sitemap extends Mage_Sitemap_Model_Sitemap
{
const PAGE_REFRESH_FREQUENCY = 'weekly';
const PAGE_PRIORITY = '1.0';
public function generateXml()
{
if ($this->getSitemapType() != 'people') {
return parent::generateXml();
}
$io = new Varien_Io_File();
$io->setAllowCreateFolders(true);
$io->open(array('path' => $this->getPath()));
if ($io->fileExists($this->getSitemapFilename()) && !$io->isWriteable($this->getSitemapFilename())) {
Mage::throwException(Mage::helper('sitemap')->__('File "%s" cannot be saved. Please, make sure the directory "%s" is writeable by web server.', $this->getSitemapFilename(), $this->getPath()));
}
$io->streamOpen($this->getSitemapFilename());
$io->streamWrite('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
$io->streamWrite('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">');
$storeId = $this->getStoreId();
$date = Mage::getSingleton('core/date')->gmtDate('Y-m-d');
$baseUrl = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
/**
* Generate people sitemap
*/
$changefreq = Mymod_People_Model_Sitemap::PAGE_REFRESH_FREQUENCY;
$priority = Mymod_People_Model_Sitemap::PAGE_PRIORITY;
$collection = Mage::getModel('people/person')->getCollection();
foreach ($collection as $item) {
$xml = sprintf('<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($item->getUrl()),
$date,
$changefreq,
$priority
);
$io->streamWrite($xml);
}
unset($collection);
$io->streamWrite('</urlset>');
$io->streamClose();
$this->setSitemapTime(Mage::getSingleton('core/date')->gmtDate('Y-m-d H:i:s'));
$this->save();
return $this;
}
}
Есть ли лучший способ избежать копирования и вставки так много из родительского класса?
Вы можете либо расширить Mage_Sitemap_Model_Sitemap
и в нем проверить sitemap_type
, если это ваш тип, сгенерируйте свой xml, иначе сгенерируйте родительский xml. Или вы можете добавить наблюдателя для события коллекции load_after
и добавить свою модель карты сайта в коллекцию.
Есть ли лучший способ избежать копирования и вставки так много из родительского класса?
Если у вас есть Magento>=1.9.0.0 и вас не волнует использование продуктов или настройка приоритета/частоты изменения каталога, вы можете использовать наблюдателя на sitemap_products_generating_before
public function addPagesToSitemap(Varien_Event_Observer $observer)
{
$collection = $observer->getCollection();
$myPages = # your data: array('url_1', 'url_2')
foreach ($myPages as $url) {
$item = new Varien_Data_Object;
$item->setUrl($url);
$collection->addItem($item);
}
}
Если вы хотите завершить различное поведение для страниц карты сайта, возможно, прочитайте Sitemap.xml измените home и/или отправьте более общее событие.