SEO URL в плагинах

  1. Генерация SEO URL для пользовательского контроллера
  2. Сценарий
  3. Давайте начнем
  4. Реализуйте логику для «Виа cronjob»
  5. Реализуйте логику для «Live»
  6. Реализуйте логику для «Ручной»
  7. Пользовательские параметры в SEO URL
  8. Добавить сторонние параметры
  9. Пример плагина
  10. Shopware 5.2 плагин

В мире электронной коммерции SEO является очень важной и постоянной темой. Таким образом, Shopware предлагает некоторые инструменты для создания магазина, оптимизированного для SEO, по умолчанию, включая URL, оптимизированные для SEO. Обязательно ознакомьтесь со следующим постом в блоге SEO, в котором содержится подробная информация о движке Shopware SEO: SEO-магазин Shopware

Но на данный момент, как мы на самом деле создаем правильные SEO-адреса для наших пользовательских плагинов?

Должно быть, это было около года назад, когда я наткнулся на ту же проблему, переделывая наш премиум плагин Торговый консультант ,

В этой записи блога я хочу предоставить краткое руководство о том, как реализовать собственные SEO-URL для ваших плагинов. Я также прикреплю пример плагина для Shopware 5.3 и 5.2 в конце урока.

Генерация SEO URL для пользовательского контроллера

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

Сценарий

В качестве примера я хотел бы создать плагин глоссария.

Используя плагин глоссария, владелец магазина должен иметь возможность создать описание для слова. Плагин предоставит обзор, показывающий все данные слова и их описание.

Чтобы сохранить их, я создал таблицу с именем s_glossary и столбцами id, word и description.

Позже в этом уроке мы также хотим добавить страницу с подробностями, показывающую только данное слово и соответствующее описание.

Предположим, что базовая структура плагина содержит зарегистрированный контроллер Frontend с именем Glossary, а также упомянутую таблицу базы данных.

Давайте начнем

Для обзора глоссария мы должны реализовать indexAction в нашем контроллере Glossary для обработки обзора. Чтобы вызвать наше действие сейчас, мы бы открыли следующий URL: http://myShop.com/glossary/

Этот URL выглядит гладким и оптимизированным для SEO, не так ли?

Что произойдет, если мы хотим, чтобы страница глоссария была доступна на международном уровне? Для ваших немецких клиентов вы бы хотели, чтобы глоссарий был доступен на http://myShop.com/glossar/.

Это можно и нужно сделать, используя SEO URL.

Прежде всего, SEO-адреса в Shopware хранятся в таблице базы данных s_core_rewrite_urls. Мы могли бы просто создать новую запись в этой таблице в процессе установки плагина. Это на самом деле будет работать на данный момент.

Тем не менее, мы хотим создать эти SEO-URL в зависимости от конфигурации «стратегии обновления».

Эту конфигурацию можно найти в бэкэнде: Конфигурация> Кэш / производительность> Настройки> SEO> Обновить стратегию. Наши SEO-URL создаются тремя различными способами, которые настраиваются в бэкэнде.

Доступные варианты:

  • Вручную
  • Виа Кронджоб
  • Жить

Опять же, обратитесь к этому сообщению в блоге, чтобы получить более подробную информацию о том, как они работают: SEO-магазин Shopware

Поскольку каждый из упомянутых выше вариантов требует немного другой логики плагина, я объясню их шаг за шагом.

Реализуйте логику для «Виа cronjob»

Следующий код совместим только с Shopware версии 5.3 или выше.

В Shopware 5.3 мы реализовали новое событие для генерации SEO-URL с помощью cronjob.
Каждый раз, когда запускается cronjob RefreshSeoIndex, метод onRefreshSeoIndex в Двигатель / Shopware / Plugins / Default / Ядро / RebuildIndex / Bootstrap.php называется.
Теперь он содержит новое событие уведомления Shopware_CronJob_RefreshSeoIndex_CreateRewriteTable, которое мы будем использовать для добавления нашего собственного процесса генерации URL-адреса SEO. Событие вызывается один раз для каждого магазина после того, как для этого магазина были сгенерированы все остальные URL-адреса SEO (например, Продукты, Категории, ...).

публичная статическая функция getSubscribeedEvents () {return ['Shopware_CronJob_RefreshSeoIndex_CreateRewriteTable' => 'createGlossaryRewriteTable']; } public function createGlossaryRewriteTable () {/ ** @var \ sRewriteTable $ rewriteTableModule * / $ rewriteTableModule = Shopware () -> Container () -> get ('modules') -> sRewriteTable (); // Вставляем новый URL перезаписи для нашего пользовательского контроллера $ rewriteTableModule-> sInsertUrl ('sViewport = glossary', 'glossary /'); }

В приведенном выше примере мы создали бы новый URL перезаписи для каждого магазина. Конечно, в этом коде мы могли и должны теперь построить нашу логику для создания переведенных URL перезаписи, например, http://myShop.com/glossar, который будет для него немецким переводом.

Реализуйте логику для «Live»

Эта опция не означает, что при каждом запросе URL-адреса SEO генерируются заново. Вы можете настроить интервал обновления в бэкэнде в разделе «Конфигурация»> «Кэш / производительность»> «Настройки»> «SEO»> «Обновить стратегию».

По сути, всякий раз, когда запрос отправляется в магазин, и ответ собирается быть отправлен обратно, Shopware проверяет, не пришло ли время заново сгенерировать URL-адреса SEO. Только в этом случае (стратегия обновления «живая» И интервал прошел), метод sCreateRewriteTable из нашего основного модуля sRewriteTable называется.

Этот метод генерирует только URL-адреса SEO для текущего активного магазина.

Следовательно, мы могли бы использовать метод after, упомянутый выше. Код для вставки нашего URL в базу данных одинаков, поэтому мы можем просто повторно использовать один и тот же код с другим событием.

публичная статическая функция getSubscribeedEvents () {return ['Shopware_CronJob_RefreshSeoIndex_CreateRewriteTable' => 'createGlossaryRewriteTable', 'sRewriteTable :: sCreateRewriteTable :: after' => 'createGlossaryRewriteTable',]; } public function createGlossaryRewriteTable () {/ ** @var \ sRewriteTable $ rewriteTableModule * / $ rewriteTableModule = Shopware () -> Container () -> get ('modules') -> sRewriteTable (); $ rewriteTableModule-> sInsertUrl ('sViewport = glossary', 'glossary /'); }

Вот и все для живого режима.

Реализуйте логику для «Ручной»

Следующий код совместим только с Shopware версии 5.3 или выше.

Окно генерации URL SEO вручную

Здесь вещи становятся немного сложнее. Ручная генерация URL фактически выполняется в ExtJs, генерируя URL в пакетном режиме.

Вы можете выбрать размер пакета, который определяет, сколько URL должно быть сгенерировано с каждым запросом.

Мы хотим, чтобы теперь в нижней части окна была собственная индикатор выполнения, чтобы сгенерировать наши URL-адреса SEO для выбранного в данный момент магазина в пакетном режиме.

Прежде всего мы должны расширить файл темы / Backend / ExtJs / бэкенд / производительность / вид / основные / multi_request_tasks.js , Мы должны расширить свойство 'seo', которое содержит все индикаторы выполнения, их фрагменты и, что наиболее важно, URL-адрес запроса, который будет вызываться для каждого пакетного вызова для генерации URL-адресов SEO.

Итак, давайте перепишем окно ExtJs. Я не буду вдаваться в подробности о том, как расширить файл ExtJs. Обратитесь к этому руководству о расширяя бэкэнд вместо.

Зарегистрировать новое событие:

публичная статическая функция getSubscribeedEvents () {return [... 'Enlight_Controller_Action_PostDispatch_Backend_Performance' => 'loadPerformanceExtension']; }

Соответствующий слушатель:

открытая функция loadPerformanceExtension (\ Enlight_Controller_ActionEventArgs $ args) {$ subject = $ args-> getSubject (); $ request = $ subject-> Request (); if ($ request-> getActionName ()! == 'load') {return; } $ subject-> View () -> addTemplateDir (__DIR__. '/ Resources / views /'); $ Субъект-> View () -> extendsTemplate ( 'Серверные / производительность / вид / glossary.js'); }

В Shopware 5.3 мы реализовали новый метод addProgressBar для multi_request_tasks.js. В качестве первого параметра вы должны предоставить объект, содержащий «initialText», который будет отображаться изначально, «progressText», который будет отображаться при генерации URL-адресов SEO, и «requestUrl», который будет вызываться на каждом этапе пакетной обработки. Второй параметр должен быть именем для нового индикатора выполнения - он понадобится нам позже. Третий параметр должен быть целью. Возможные значения: «seo» и «httpCache». Поскольку мы хотим создать новую строку прогресса для окна SEO, мы, очевидно, будем использовать «seo».

// {block name = "backend / performance / view / main / multi_request_tasks" append} Ext.define ('Shopware.apps.Performance.view.main.Glossary', {override: 'Shopware.apps.Performance.view.main .MultiRequestTasks ', initComponent: function () {this.addProgressBar ({initialText:' URL-адреса глоссария ', progressText:' [0] из [1] URL-адресов глоссария ', requestUrl:' {контроллер url = глоссарий action = generateSeoUrl} '}} , 'glossary', 'seo'); this.callParent (arguments);}}); // {/ блок}

Как только мы обновим бэкэнд и, возможно, очистим кеш, окно SEO теперь должно содержать наш новый индикатор выполнения. Теперь нам нужно создать наш бэкэнд-контроллер и generateSeoUrlAction.

С каждым AJAX-запросом на пакетную обработку мы получим shopId, смещение и лимит для правильной генерации наших SEO-URL. Мы можем игнорировать смещение и ограничение на данный момент , так как для каждого магазина создается только один URL. Просто запомните их позже в этом уроке.

Контроллеры / Backend / Glossary.php

<? php class Shopware_Controllers_Backend_Glossary extends Shopware_Controllers_Backend_ExtJs {публичная функция generateSeoUrlAction () {$ shopId = $ this-> Request () -> getParam ('shopId'); / ** @var Shopware_Components_SeoIndex $ seoIndex * / $ seoIndex = $ this-> container-> get ('SeoIndex'); $ SeoIndex-> ​​registerShop ($ shopId); / ** @var sRewriteTable $ rewriteTableModule * / $ rewriteTableModule = $ this-> container-> get ('modules') -> RewriteTable (); $ RewriteTableModule-> baseSetup (); $ rewriteTableModule-> sInsertUrl ('sViewport = glossary', 'glossary /'); $ this-> View () -> assign (['success' => true]); }}

Мы выбираем shopId, регистрируем магазин, используя данный shopId, а затем просто вставляем наш URL перезаписи снова.

Теперь еще одна вещь отсутствует. Как только мы выбираем магазин в модуле бэкэнда SEO, отправляется AJAX-вызов, чтобы собрать общее количество URL-адресов, которые будут созданы с каждым индикатором выполнения. Наши URL глоссария еще не собраны, поэтому модуль пока не может правильно обрабатывать наши глоссарии URL.

Для сбора URL-адресов getCountAction объекта SEO контроллер называется. К счастью, он предоставляет событие фильтра Shopware_Controllers_Seo_filterCounts для правильного добавления наших собственных подсчетов. Для этого нам нужно использовать имя, которое мы использовали ранее для индикатора выполнения.

публичная статическая функция getSubscribeedEvents () {return [... 'Shopware_Controllers_Seo_filterCounts' => 'addGlossaryCount']; } публичная функция addGlossaryCount (\ Enlight_Event_EventArgs $ args) {$ countts = $ args-> getReturn (); $ countts ['glossary'] = 1; вернуть $ count; }

В настоящее время для каждого магазина создается только один URL, поэтому мы просто вернем статический 1.

Итак, теперь давайте попробуем. Если вы все правильно реализовали, то теперь все должно работать идеально.

Пользовательские параметры в SEO URL

Теперь мы реализовали простую генерацию URL-адреса для нашего плагина глоссария. Обзор теперь поддерживается SEO-дружественными URL-адресами, и мы даже генерируем эти URL-адреса надлежащим образом, в зависимости от заданной конфигурации.

Теперь мы хотим иметь какую-то «детальную» страницу для каждого слова. При вызове этой подробной страницы мы видим только одно слово с соответствующим описанием.

Для этого нам понадобится новое действие в нашем контроллере внешнего интерфейса, например «detailAction». Мы можем вызвать это действие, используя URL-адрес, например http://myShop.com/glossary/detail. Однако в этом случае нам нужно будет прикрепить идентификатор для слова, которое мы хотим показать сейчас.

Звучит просто, давайте просто прикрепим его к URL: http://myShop.com/glossary/detail?wordId=1

Эта ссылка теперь будет отображать слово с идентификатором 1. Разве не было бы круче, чтобы само слово было частью URL сейчас? Например, если вы хотите объяснить слово «рекурсия», URL-адрес может выглядеть следующим образом: http://myShop.com/glossary/recursion

Гораздо лучше, не так ли?

Теперь это уже требует нескольких изменений в нашем коде. Прежде всего, каждый раз, когда мы генерируем наши URL-адреса SEO, мы должны перебирать все слова в нашей базе данных.

public function createGlossaryRewriteTable () {/ ** @var \ sRewriteTable $ rewriteTableModule * / $ rewriteTableModule = Shopware () -> Container () -> get ('modules') -> sRewriteTable (); $ rewriteTableModule-> sInsertUrl ('sViewport = glossary', 'glossary /'); / ** @var QueryBuilder $ dbalQueryBuilder * / $ dbalQueryBuilder = $ this-> container-> get ('dbal_connection') -> createQueryBuilder (); $ words = $ dbalQueryBuilder-> select ('glossary.id, glossary.word') -> from ('s_glossary', 'glossary') -> execute () -> fetchAll (\ PDO :: FETCH_KEY_PAIR); foreach ($ words as $ wordId => $ word) {$ rewriteTableModule-> sInsertUrl ('sViewport = glossary & sAction = detail & wordId ='. $ wordId, 'glossary /'. $ word); }}

Также нам нужно настроить количество URL для бэкенда.

публичная функция addGlossaryCount (\ Enlight_Event_EventArgs $ args) {$ counts = $ args-> getReturn (); / ** @var QueryBuilder $ dbalQueryBuilder * / $ dbalQueryBuilder = $ this-> container-> get ('dbal_connection') -> createQueryBuilder (); $ wordsCount = $ dbalQueryBuilder-> select ('COUNT (glossary.id)') -> from ('s_glossary', 'glossary') -> execute () -> fetchAll (\ PDO :: FETCH_COLUMN); $ countts ['glossary'] = $ wordsCount; вернуть $ count; }

Вы все еще помните смещение и параметр limit из пакетной обработки для URL-адресов SEO? Теперь нам нужно реализовать их, чтобы генерировать столько SEO-URL, сколько сконфигурировано в пакетном процессе.

публичная функция generateSeoUrlAction () {... / ** @var QueryBuilder $ dbalQueryBuilder * / $ dbalQueryBuilder = $ this-> container-> get ('dbal_connection') -> createQueryBuilder (); $ words = $ dbalQueryBuilder-> select ('glossary.id, glossary.word') -> from ('s_glossary', 'glossary') -> setMaxResults ($ limit) -> setFirstResult ($ offset) -> execute () -> fetchAll (\ PDO :: FETCH_KEY_PAIR); foreach ($ words as $ wordId => $ word) {$ rewriteTableModule-> sInsertUrl ('sViewport = glossary & sAction = detail & wordId ='. $ wordId, 'glossary /'. $ word); } $ this-> View () -> assign (['success' => true]); }

Добавить сторонние параметры

Хотя это уже выглядит хорошо, есть еще одна вещь, которую нужно сделать. Магазин должен знать в первую очередь наш пользовательский параметр « wordId ». В противном случае наш параметр просто будет удален, а наш SEO-URL не будет работать.

Возможные случаи для параметров обрабатываются в RewriteGenerator , Это имеет множество случаев, например, параметр " sArticle " разрешен только при использовании с детальным контроллером.

К счастью, начиная с Shopware 5.2, этот метод предоставляет событие для добавления пользовательских параметров.

Итак, давайте добавим событие и реализуем наш пользовательский параметр.

публичная статическая функция getSubscribeedEvents () {return [... 'Shopware_Components_RewriteGenerator_FilterQuery' => 'filterParameterQuery']; } публичная функция filterParameterQuery (\ Enlight_Event_EventArgs $ args) {$ orgQuery = $ args-> getReturn (); $ query = $ args-> getQuery (); if ($ query ['controller'] === 'глоссарий' && isset ($ query ['wordId'])) {$ orgQuery ['wordId'] = $ query ['wordId']; } return $ orgQuery; }

Итак, что я здесь сделал? Прежде всего, Shopware не знает таких вещей, как «контроллеры» или «подобные действия». Из-за устаревших причин Shopware все еще нуждается в их обработке как sViewport, который будет контроллером, и sAction, который, очевидно, представляет действие. Вот что содержит $ orgQuery: контроллер, сопоставленный с 'sViewport', и действие, сопоставленное с элементом массива 'sAction'. Поскольку $ orgQuery будет использоваться для сборки нашего SEO URL позже, нам нужно добавить наш параметр к нему.

Между тем, $ query содержит фактические параметры запроса, какими мы их знаем.

Нам нужно только добавить наш пользовательский параметр wordId, если и контроллер равен 'глоссарию', и сам параметр установлен. В этом случае мы добавляем wordId в $ orgQuery и возвращаем его позже.

Пример плагина

Вы можете найти пример плагина для Shopware 5.3 Вот ,

Просто чтобы убедиться: это не полностью функциональный плагин, так как он должен быть только примером. Это создаст необходимую таблицу плагинов s_glossary с несколькими примерами слов. Этот плагин не предоставляет бэкэнд-модуль для работы, а шаблоны внешнего интерфейса очень тонкие, чтобы показать основные функциональные возможности.

Shopware 5.2 плагин

Мы также создали пример плагина для Shopware 5.2 , который можно найти Вот ,

Есть несколько отличий, например, весь каталог Resources / views / backend отличается. В дополнение к этому, необходимо было изменить логику для подсчета доступных URL глоссария, так как событие, которое мы использовали выше, было реализовано в 5.3.

Что произойдет, если мы хотим, чтобы страница глоссария была доступна на международном уровне?
Com/glossary/detail?
1. Разве не было бы круче, чтобы само слово было частью URL сейчас?