OpenCart sitemap с кешированием

Так уж повелось, что в OpenCart есть стандартный модуль для создания XML файла в формате sitemap для использование в основных поисковых системах.

Но, у него есть один существенный недостаток, при большом количестве товара он сильно нагружает систему. А при её и так приличной нагрузке может и не дойти до конца. Что конечно же отразиться ошибкой в кабинете веб мастера Google, Yandex и т.д.

Предлагаю скромное решение, которое попросту кеширует этот файл после его создания на 24 часа.

Для этого нужно лишь слегка изменить файл /catalog/controller/feed/google_sitemap.php, ниже я предлагаю полный код файла. Из изменений в нём только проверка на существование файла кеш и даты его последнего изменения, а так же создание кеш файла после формирования содержания файла sitemap.

Собственно код файла:

<?php

class ControllerFeedGoogleSitemap extends Controller {

    public function index() {
        if ($this->config->get('google_sitemap_status')) {
            if (!file_exists("sitemap.pre.txt") || time() - filemtime("sitemap.pre.txt") > 86400) {
                $output = '<?xml version="1.0" encoding="UTF-8"?>';
                $output .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

                $this->load->model('catalog/product');

                $products = $this->model_catalog_product->getProducts();

                foreach ($products as $product) {
                    $output .= '<url>';
                    $output .= '<loc>' . $this->url->link('product/product', 'product_id=' . $product['product_id']) . '</loc>';
                    $output .= '<changefreq>weekly</changefreq>';
                    $output .= '<priority>1.0</priority>';
                    $output .= '</url>';
                }

                $this->load->model('catalog/category');

                $output .= $this->getCategories(0);

                $this->load->model('catalog/manufacturer');

                $manufacturers = $this->model_catalog_manufacturer->getManufacturers();

                foreach ($manufacturers as $manufacturer) {
                    $output .= '<url>';
                    $output .= '<loc>' . $this->url->link('product/manufacturer/info', 'manufacturer_id=' . $manufacturer['manufacturer_id']) . '</loc>';
                    $output .= '<changefreq>weekly</changefreq>';
                    $output .= '<priority>0.7</priority>';
                    $output .= '</url>';

                    $products = $this->model_catalog_product->getProducts(array('filter_manufacturer_id' => $manufacturer['manufacturer_id']));

                    foreach ($products as $product) {
                        $output .= '<url>';
                        $output .= '<loc>' . $this->url->link('product/product', 'manufacturer_id=' . $manufacturer['manufacturer_id'] . '&product_id=' . $product['product_id']) . '</loc>';
                        $output .= '<changefreq>weekly</changefreq>';
                        $output .= '<priority>1.0</priority>';
                        $output .= '</url>';
                    }
                }

                $this->load->model('catalog/information');

                $informations = $this->model_catalog_information->getInformations();

                foreach ($informations as $information) {
                    $output .= '<url>';
                    $output .= '<loc>' . $this->url->link('information/information', 'information_id=' . $information['information_id']) . '</loc>';
                    $output .= '<changefreq>weekly</changefreq>';
                    $output .= '<priority>0.5</priority>';
                    $output .= '</url>';
                }

                $output .= '</urlset>';
                file_put_contents("sitemap.pre.txt", $output, LOCK_EX);
                $this->response->addHeader('Content-Type: application/xhtml+xml');
                $this->response->setOutput($output);
            } else {
                $output = file_get_contents("sitemap.pre.txt");
                $this->response->addHeader('Content-Type: application/xhtml+xml');
                $this->response->setOutput($output);
            }//if
        }//if
    }

    protected function getCategories($parent_id, $current_path = '') {
        $output = '';

        $results = $this->model_catalog_category->getCategories($parent_id);

        foreach ($results as $result) {
            if (!$current_path) {
                $new_path = $result['category_id'];
            } else {
                $new_path = $current_path . '_' . $result['category_id'];
            }

            $output .= '<url>';
            $output .= '<loc>' . $this->url->link('product/category', 'path=' . $new_path) . '</loc>';
            $output .= '<changefreq>weekly</changefreq>';
            $output .= '<priority>0.7</priority>';
            $output .= '</url>';

            $products = $this->model_catalog_product->getProducts(array('filter_category_id' => $result['category_id']));

            foreach ($products as $product) {
                $output .= '<url>';
                $output .= '<loc>' . $this->url->link('product/product', 'path=' . $new_path . '&product_id=' . $product['product_id']) . '</loc>';
                $output .= '<changefreq>weekly</changefreq>';
                $output .= '<priority>1.0</priority>';
                $output .= '</url>';
            }

            $output .= $this->getCategories($result['category_id'], $new_path);
        }

        return $output;
    }

}

?>
  • +1
  • 14 ноября 2013, 13:58
  • igorrius

Комментарии (6)

RSS свернуть / развернуть
В приведенном коде присутствует 2 проблемы:
1. Использование штатного $this->model_catalog_product->getProducts() для выбора списка товаров. Вы даже не представляете какого голодного до ресурсов демона вы выпускаете на волю :)
2. Использование штатного механизма генерации чпу — $this->url->link('product/product', 'product_id='. $product['product_id']). Это по сути главная проблема, ибо там также дергается пачка запросов, да еще и дергается запись файлового кеша на каждое обращение.

В итоге — гайки.

Мне удалось оптимизировать генерацию карты сайта. Сам модуль и видеоролик к нему можно глянуть тут — opencartforum.ru/topic/30471-soforp-%D1%88%D1%83%D1%81%D1%82%D1%80%D1%8B%D0%B9-sitemap/
0
Алекс, я не лечу от всех болезней, я лишь выдаю направление мысли. OpenCart сам по себе голодный до ресурсов демон с огромным количеством проблем, начинает с его framework.
Если бы Вы правильно разобрали код, то обратили бы внимание, что файл дёргается только при записи, что не является сильно ресурсоёмкой операцией. Да, соглашусь, не создавал запросы, не переписывал существующие) НО!
И НЕ ПЫТАЮСЬ ПРОПИАРИТЬ СВОЙ КОММЕРЧЕСКИЙ МОДУЛЬ НА ЧУЖИХ САЙТАХ!!!!!

П.С. не буду удалять ссылку, Вы старались, а значит старание должно быть замечено. И на Ваш товар есть покупатель) И на мою идею)
+1
Хм, и действительно не дочитал.

Дело в том что я сталкивался с несколькими вариантами кеширования и все они грешат как либо проблемой неактуальности кеша, либо проблемой слишком быстрого устаревания кеша.

Например в вашем случае нет быстрого устаревания, вы записали в файл и данные там будут столько — сколько нужно. Однако это приводит к тому, что новые товары попадут в поисковик не так быстро как хотелось бы. Ну как бы логично, чем дольше живет кеш — тем дольше поисковик в неведении о существовании нового товара, ведь карта сайта отправная точка для него.

Другой вариант реализован в модуле ocCMS, который на мой взгляд является лучшим модулем блога ( не моим ). Там используется блочное кеширование ( отдельно товары, отдельно категории и т.д. ) но делается это средствами опенкарта ( $this->cache->set(....) ) а это приводит к тому что кеш умирает через час и когда поисковик вечером заходит, то фактически дергает генератор карты сайта на холодную.

Я ел этот кактус около года, но в конечном итоге озадачился созданием действительно быстрой генерации карты сайта, чтобы не приходилось что либо кешировать вообще и в принципе. Премного благодарен что не удаляете ссылку, могу поделиться за это модулем :)
+1
С удовольствием протестируем Ваш модуль и напишем характеристику)
0
Выслал. Разнесите его в пух и прах, все конструктивные замечания будут проработаны.

P.S. через пару недель ожидается доработка по разбивке карты сайта на несколько файлов. Актуально для сайтов с количеством товаров от 50,000.
0
Согласен, разбивка на файлы актуальна для больших магазинов.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
comments powered by Disqus