Magento для PHP MVC разработчиков – Особая конфигурация системы (ч.7/11)

Magento для PHP MVC разработчиков – Особая конфигурация системы (ч.7/11)



Одной из наиболее мощных частей Magento является админский раздел Конфигурации системы. Вам, как разработчикам, нужно знать, как здесь все устроено и как тут что делается.

Как и многие вещи в Magento, сначала это может отпугивать, но как только вы попробуете это, вам понравится вся мощь системы. Поэтому, давайте начнем.

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

 

Ниже представлена часть большой серии статей, ориентированную на Мадженто разработчиков, знакомых с PHP MVC. Хотя каждая статья может быть прочитана отдельно, каждая из них опирается на понятие и код, описанный в предыдущих статьях. Если вы сбились с толку, для начала просмотрите предыдущие статьи.

 

 

Добавление файла конфигурации системы

Первое, что нам нужно сделать – добавить в модуль файл системной конфигурации. Этот файл идет отдельно от config.xml и его можно найти в следующем месте:

app/code/local/Alanstormdotcom/Helloworld/etc/system.xml

 

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

 

//header('Content-Type: text/xml');
header('Content-Type: text/plain');
echo $config = Mage::getConfig()
->loadModulesConfiguration('system.xml')
->getNode()
->asXML();
exit;

 

Метод loadModulesConfiguration будет осматривать каждую папку etc в каждом включенном модуле в поисках файла с указанным названием (в данном случае, system.xml). Magento имеет ряд других конфигурационных файлов (api.xml, wsdl.xml, wsdl2.xml, convert.xml, compilation.xml, install.xml), и как разработчик модулей вы можете использовать эту функцию для создания собственного файла.



 

 

Добавление новой вкладки

Первое, что мы собираемся сделать – это добавить собственную «вкладку» к конфигурации системы. Вкладки – это заголовки навигации в левом меню админки System -> Configuration (Система -> Конфигурация). Вкладки по умолчанию следующие: Общее, Каталог, Клиенты, Продажи, Сервисы и Расширенные.

 

Создадим новую вкладку с названием «Hello Config«. Создайте новый файл конфигурации системы и добавьте следующее:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/system.xml

<config>
  <tabs>
    <helloconfig translate="label" module="helloworld">
     <label>Hello Config</label>
     <sort_order>99999</sort_order>
    </helloconfig>
  </tabs>
</config>

 

Здесь нужно сделать несколько пояснений. Название узла <helloconfig/> является произвольным, но должно быть уникальным среди вкладок. Оно будет служить идентификатором вашей вкладки, которую мы используем позже в конфигурации.

Атрибут module="helloworld" определяет, какому модулю эта вкладка «принадлежит», <label> определяет имя, которое будет использоваться для вкладки, а <sort_order> определяет, как отображается вкладка по отношению к другим вкладкам в левом меню.

 

После этого перейдите в раздел Система -> Конфигурация. И одно из двух событий должно произойти:

  1. Страница будет загружаться, но без вашей новой вкладки
  2. Вы получите ошибку типа:
    Fatal error: Class 'Mage_Helloworld_Helper_Data' not found in

 

Краткий обзор Хелпер классов

Как и в других популярных PHP MVC-системах, в Magento также есть Helper классы, которые используются для различных задач, не применимых к Model, View или Controller. Хелпер класс – это один из примеров абстрактных групповых имен классов, который означает, что пользователи системы могут переопределять классы по умолчанию, и разработчикам модулей нужно добавлять соответствующий раздел к файлам config.xml, чтобы указывать имя базового класса для Хелперов.

Большинство кода в системе Magento предусматривает, что модуль имеет дефолтный Хелпер класс. Если вы получили вышеуказанное исключение, это связано с тем, что ваш модуль Helloworld не имеет этого Хелпер класса, но система пыталась его использовать. Поэтому, давайте добавим его сейчас.

Во-первых, нам нужно добавить раздел в основной файл config.xml модуля (НЕ системную конфигурацию):

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/config.xml

<!-- ... -->
<global>
<!-- ... -->
  <helpers>
    <helloworld>
       <class>Alanstormdotcom_Helloworld_Helper</class>
    </helloworld>
  </helpers>
<!-- ... -->
</global>
<!-- ... -->

 

Если вы уже настраивали конфигурацию Magento, эта запись должна быть вам понятной. Тег <helloworld/> следует именовать названием модуля, а тег <class/> должен содержать базовое название всех Helper классов, которое именуется в соответствии со стандартной конвенцией Magento:

Packagename_Modulename_Helper

 

Хелперы загружаются статическим методом helper глобального объекта Mage. Следующий вызов (предполагая, что вышеуказанный файл конфигурации в наличии):

Mage::helper('helloworld/foo');

 

будет загружать следующий класс:

app/code/local/Alanstormdotcom/Helloworld/Helper/Foo.php

class Alanstormdotcom_Helloworld_Helper_Foo

 

Magento также имеет понятие Хелпера по умолчанию для модуля. Если вы указываете класс Хелперов лишь с именем модуля:

Mage::helper('helloworld');

 

он будет искать данные Хелпера, которые находятся в:

app/code/local/Alanstormdotcom/Helloworld/Helper/Data.php

class Alanstormdotcom_Helloworld_Helper_Data ...

 

Это означает, что следующие два вызова эквивалентны:

Mage::helper('helloworld');
Mage::helper('helloworld/data');

 

Наконец, нам нужно добавить актуальный Helper класс. Добавьте следующий файл, и все заработает:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/Helper/Data.php

class Alanstormdotcom_Helloworld_Helper_Data extends Mage_Core_Helper_Abstract {

}

 

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

Примечание. Если вас интересует то, что может дать вам метод helper, проверьте класс Mage_Core_Helper_Abstract для осмотра списка полезных методов, которые будут иметь все Хелперы.

 

 

Добавление новой секции

Реализация Хелпера не подошла, поэтому нашим следующим шагом будет выяснение того, почему настроена вкладка не отображается. Каждая вкладка имеет ряд секций. Например, вкладка Расширенное имеет (по умолчанию) следующие секции: «Администратор», «Система», «Расширенные» и «Разработчик».

Если вкладка настроена без секций, она не будет отображаться. Итак, исправим ошибку, добавив узел <sections/> к файлу системной конфигурации:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/system.xml

<config>
  <tabs>
    <helloconfig translate="label" module="helloworld">
      <label>Hello Config</label>
      <sort_order>99999</sort_order>
    </helloconfig>
  </tabs>
  <sections>
    <helloworld_options translate="label" module="helloworld">
      <label>Hello World Config Options</label>
      <tab>helloconfig</tab>
      <frontend_type>text</frontend_type>
      <sort_order>1000</sort_order>
      <show_in_default>1</show_in_default>
      <show_in_website>1</show_in_website>
      <show_in_store>1</show_in_store>
    </helloworld_options>
  </sections>
</config>

 

В этой новой части конфигурации есть несколько знакомых узлов, а также несколько новых.

 

Что такое <helloworld_options/>?

Этот тег похож на тег <helloconfig/>, который определен выше. Он с помощью произвольного имени определяет опции нового раздела (секции).

 

Что такое <label/>?

Тег label определяет отображение значения, которое используется в интерфейсе HTML для нового раздела (то есть, это название секции).

 

Что такое <tab/>?

Этот тег определяет, в какую вкладку должен быть сгруппирован ниже новый раздел. Мы хотим, чтобы наш раздел отображался в новой вкладке helloconfig. Название helloconfig происходит от тега, который используется для создания вкладки (<helloconfig/>)

 

Что такое <frontend_type/>?

Это достаточно сложный тег. <frontend_type/> имеет значение в других разделах конфигурации (см. ниже) но, кажется, здесь он ничего не делает. Однако, секции в Core модулях используют этот тег, поэтому лучше будет следовать конвенции, даже если вы не знаете, что практически она делает.

 

Что такое <sort_order/>?

Опять же, <sort_order/> определяет распределение вертикального отображения секций в меню, по сравнению с другими секциями вкладки.

 

Что такое <show_in_default/>, <show_in_website/>, <show_in_store/>?

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

 

Настроив этот раздел, давайте снова перейдем в System -> Config (Система -> Конфигурация). Теперь вы должны увидеть свой раздел и вкладку в нижней части левого меню. Вы можете добавить другие разделы, добавив к узлу <sections/> дополнительные узлы.

 

 

Контроль доступа

Если вы нажмете на ссылку новой секции, вы будете разочарованы результатами. Будет загружена пустая страница администратора, а меню слева полностью исчезнет. Это происходит потому, что приложение Adminhtml не может найти запись для новой секции в Списке Контроля Доступа (ACL).

 

ACL – это достаточно широкая тема, но здесь я постараюсь объяснить достаточно для первых шагов. Есть определенные ресурсы, которые требуют, чтобы пользователь был авторизован перед их использованием. Ресурс здесь – это абстрагированный термин. Это может быть страница администратора, или это может быть доступ к определенной функции. Группа разработчиков Magento решила, что разделы System Config должны иметь защиту ACL.

 

Ресурсы определяются через URI. Например, раздел «веб-конфигурация» (web) (на вкладке «Общие») определяется URI:

admin/system/config/web

 

тогда наша секция helloworld_options будет иметь следующее URI:

admin/system/config/helloworld_options

 

Приложение для Администрирования (часто называется adminhtml) построено с использованием того же фреймворка, что и приложение для Магазина (приложение для Магазина часто называется приложением frontend). В контроллере действий Adminhml, когда пользователю нужно получить доступ к ресурсу, защищенному ACL, разработчик Adminhtml должен:

  1. Определить URI для любого ресурса, к которому пользователь пытается получить доступ
  2. Проверить, указано ли это URI в системе ACL, которая будет определять, имеет ли залогиненный пользователь право доступа к этому конкретному ресурсу
  3. Если пользователь имеет правильные права доступа, продолжить выполнение приложения. Если нет – отклонить выполнение, или сделать что-то подобное (например, остановить отображения меню и контента)

 

Для тех, кто интересуется этим больше, данная процедура определяется для разделов System Config с помощью метода _isSectionAllowed в следующем контроллере:

app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php

 

Если вы перейдете в Система -> Разрешения -> Роли и нажмете кнопку «Добавить новую роль», вы сможете увидеть графическое представление дерева всех ресурсов роли, определенной в текущей инсталляции Magento.

 

 

Добавление роли ACL

Мы должны определить ресурс ACL для нашего нового раздела. Вам нужно делать это только, если вы добавляете новый раздел. Если вы добавляете параметры настройки к существующему разделу, не нужно вмешиваться в ACL.

 

В конфигурационном файле модуля config.xml добавьте следующий раздел:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/config.xml

<config>
<!-- ... -->
  <adminhtml>
   <acl>
    <resources>
     <admin>
      <children>
       <system>
        <children>
         <config>
          <children>
           <helloworld_options>
            <title>Store Hello World Module Section</title>
           </helloworld_options>
          </children>
         </config>
        </children>
       </system>
      </children>
     </admin>
    </resources>
   </acl>
  </adminhtml>
<!-- ... -->
</config>

 

Так, здесь достаточно много кода. Давайте разобьем его на составляющие. Во-первых, все определенные ресурсы содержатся в следующей структуре узла:

 

<adminhtml>
  <acl>
    <resources>
    </resources>
  </acl>
</adminhtml>

 

Внутри ресурса (<resources>) каждый нисходящий узел представляет собой часть URI. Итак, ниже идет:

<admin>
 <children>
  <system>
   <children>

 

что дает нам URI:

admin/system

 

Если вы внимательно следите за уроком, вы не пропустите узел для нашей конфигурации:

<helloworld_options>
  <title>Store Hello World Module Section</title>
</helloworld_options>

 

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

 

Добавив этот код в конфигурацию и очистив кэш, вам следует пересмотреть раздел настроек. Возможно, для этого вам придется выйти из админки и затем повторно залогиниться. Ведь раздел Администратора имеет свое дополнительное кэширование в дополнение к стандартному кэшу Magento.

Перейдите к своему новому разделу и вы увидите пустую страницу конфигурации под названием «Hello World Config Options».

 

 

Добавление групп

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

Группы используются для группировки различных вариантов конфигурации, и они отражаются в административной части с помощью вкладки, которая раскрывается. Например, в начальной инсталляции раздел Расширенные имеет одну группу под названием «Отключить вывод модулей».

Создадим группу под названием «messages», добавив узел <groups/> в нашу конфигурацию, которая вложена в узел <sections>:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/system.xml

<config>
  <tabs>
   <helloconfig translate="label" module="helloworld">
    <label>Hello Config</label>
    <sort_order>99999</sort_order>
   </helloconfig>
  </tabs>
  <sections>
   <helloworld_options translate="label" module="helloworld">
    <label>Hello World Config Options</label>
    <tab>helloconfig</tab>
    <frontend_type>text</frontend_type>
    <sort_order>1000</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>1</show_in_store>
    <groups>
     <messages translate="label">
      <label>Demo Of Config Fields</label>
      <frontend_type>text</frontend_type>
      <sort_order>1</sort_order>
      <show_in_default>1</show_in_default>
      <show_in_website>1</show_in_website>
      <show_in_store>1</show_in_store>
     </messages>
    </groups>
   </helloworld_options>
  </sections>
</config>

 

Каждый тег в этом узле аналогичный тегам с узла верхнего уровня <sections/>.

 

Если вы перезагрузите страницу, должна появиться пустая раскрывающаяся вкладка под названием «Demo Of Config Fields».

 

 

Добавление полей конфигурации

Наконец, нам нужно добавить отдельные поля настроек. Вы можете сделаете это, добавив в узел <messages/> узел <fields/>. Начнем с текстового поля «hello_message»:

 

<!-- ... -->
<messages translate="label">
 <label>Demo Of Config Fields</label>
 <frontend_type>text</frontend_type>
 <sort_order>1</sort_order>
 <show_in_default>1</show_in_default>
 <show_in_website>1</show_in_website>
 <show_in_store>1</show_in_store>
 <fields>
  <hello_message>
   <label>Message</label>
   <frontend_type>text</frontend_type>
   <sort_order>1</sort_order>
   <show_in_default>1</show_in_default>
   <show_in_website>1</show_in_website>
   <show_in_store>1</show_in_store>
  </hello_message>
 </fields>
</messages>
<!-- ... -->

 

Опять же, поля в новом узле <hello_message> аналогичные другим узлам, которые мы добавляли до сих пор. Однако на этот раз <frontend_type>text</frontend_type> действительно делает полезную вещь, указывая системе, какой элемент формы нам нужен. Перезагрузите страницу, и теперь вы увидите отдельное текстовое поле в окне настроек, которое разворачивается.

Когда вся эта информация о конфигурации записана, больше ничего не нужно делать. Не нужно никакого кода для сохранения/загрузки/обновления значений настройки. Система обработает это все самостоятельно.

 

Вас никто не ограничивает только текстовыми полями. Поэтому, давайте добавим другое поле, которое называется <hello_time/>:

 

<!-- ...-->
<fields>
 <hello_message>
  <label>Message</label>
  <frontend_type>text</frontend_type>
  <sort_order>1</sort_order>
  <show_in_default>1</show_in_default>
  <show_in_website>1</show_in_website>
  <show_in_store>1</show_in_store>
 </hello_message>
 <hello_time>
  <label>Time to Say Hello</label>
  <frontend_type>time</frontend_type>
  <sort_order>1</sort_order>
  <show_in_default>1</show_in_default>
  <show_in_website>1</show_in_website>
  <show_in_store>1</show_in_store>
 </hello_time>
</fields>
<!-- ... -->

 

Обратите внимание, что главное отличие здесь – это следующий тег:

<frontend_type>time</frontend_type>

 

Перезагрузите страницу, и теперь у вас будет поле конфигурации для сохранения значения времени.

Многие, но не все из встроенных в класс Varien форм данных (lib/Varien/Data/Form/Element) поддерживаются. Тег <frontend_type/> выступает в качестве идентификатора паттерна. Давайте попробуем изменить наше приветственное сообщение на select (выпадающий список):

 

<!-- ... -->
<hello_message>
  <label>Message</label>
  <frontend_type>select</frontend_type>
  <sort_order>1</sort_order>
  <show_in_default>1</show_in_default>
  <show_in_website>1</show_in_website>
  <show_in_store>1</show_in_store>
</hello_message>
<!-- ... -->

 

Если вы после этого перезагрузите страницу, то увидите, что у вас есть выпадающий список HTML, но он не содержит никаких значений. Нам нужно будет добавить источник Модели для определения нашего поля. Попробуйте такой код вместо верхнего:

 

<hello_message>
  <label>Message</label>
  <frontend_type>select</frontend_type>
  <!-- добавляем ресурс Модели -->
  <source_model>helloworld/words</source_model>
  <sort_order>1</sort_order>
  <show_in_default>1</show_in_default>
  <show_in_website>1</show_in_website>
  <show_in_store>1</show_in_store>
</hello_message>

 

Элемент <source_model> определяет URI для класса модели, которую мы будем использовать для предоставления значений по умолчанию для выпадающего списка. Это значит, что мы должны убедиться, что наш файл config.xml модуля имеет набор разделов Моделей:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/config.xml
<config>
 <!-- ... -->
 <global>
  <!-- ... -->
  <models>
  <!-- ... -->
   <helloworld>
     <class>Alanstormdotcom_Helloworld_Model</class>
   </helloworld>
  <!-- ... -->
  </models>
 </global>
</config>

 

Смотрите предыдущие статьи серии, если вы не знаете, что происходит в этой конфигурации.

 

Итак, если мы добавим вышеуказанный код и перезагрузим нашу страницу после очистки кэша, мы получим ошибку типа:

Warning: include(Alanstormdotcom/Helloworld/Model/Words.php)

 

Это произошло потому, что мы не определили наш класс ресурса Модели. Давайте сделаем это сейчас.

Примечание. Если в предупреждении указывается путь Mage/Helloworld/..., это означает, что вы неправильно настроили раздел <models/> в файле config.xml.

 

Чтобы определить наш ресурс Модели, добавьте следующий файл:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/Model/Words.php

class Alanstormdotcom_Helloworld_Model_Words {
  public function toOptionArray() {
   return array(
    array('value'=>1, 'label'=>Mage::helper('helloworld')->__('Hello')),
    array('value'=>2, 'label'=>Mage::helper('helloworld')->__('Goodbye')),
    array('value'=>3, 'label'=>Mage::helper('helloworld')->__('Yes')),
    array('value'=>4, 'label'=>Mage::helper('helloworld')->__('No')),
   );
  }
}

 

Ресурсы Модели – это классы, которые реагируют на метод под названием toOptionsArray. Этот метод должен возвращать массив значений, используемых для заполнения значений по умолчанию в наших элементах формы (которые наследуются от класса Varien_Data_Form_Element_Abstract). Для элемента выпадающего списка это означает определение набора пары значение/заголовок. В приведенном выше примере мы передаем наши заголовки через Хелпер метод перевода (__). Хотя это и не является необходимым, использование такого кода всегда является хорошей практикой. Ведь вы никогда не знаете, на какой язык нужно будет переводить ваш модуль!

 

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

 

Для тех, кто интересуется более подробно устройством Magento, метод initFields в следующем классе – это то место, где ресурс Модели используется для определения значения поля:

app/code/core/Mage/Adminhtml/Block/System/Config/Form.php

 

 

Добавление полей к существующим разделам/группам конфигурации

Кроме настройки конфигурации собственных вкладок и разделов, вы можете добавить к существующему разделу System Config поля с помощью соответствующих разделов в своем собственном файле system.xml.

 

Например, если вы добавите следующее:

 

Файл: app/code/local/Alanstormdotcom/Helloworld/etc/system.xml

<config>
 <!-- ... -->
 <sections>
  <!-- ... -->
  <general>
   <groups>
    <example>
     <label>Example of Adding a Group</label>
     <frontend_type>text</frontend_type>
     <sort_order>1</sort_order>
     <show_in_default>1</show_in_default>
     <show_in_website>1</show_in_website>
     <show_in_store>1</show_in_store>
    </example>
   </groups>
  </general>
  <!-- ... -->
 </section>
</config>

 

у вас будет новая группа «Example of Adding a Group» в общей вкладке (General).

 

 

Получение значений

Мы рассмотрели процесс настройки формы для создания значений конфигурации. Чтобы получить значение в приложениях и модулях, мы будем использовать метод getStoreConfig глобального объекта Mage. Например, чтобы получить значение выпадающего списка, созданного выше, мы будем использовать:

Mage::getStoreConfig('helloworld_options/messages/hello_message');

 

Метод getStoreConfig принимает один параметр, который является URI в следующем формате:

section_name/group_name/field_name

 

Вы также можете получить массив всех настроек, указав частичный путь:

Mage::getStoreConfig('helloworld_options/messages');
Mage::getStoreConfig('helloworld_options');

 

Наконец, если вам нужно получить значение для магазина, который не используется в текущей сессии, getStoreConfig принимает второй параметр, — идентификатор магазина:

Mage::getStoreConfig('helloworld_options',1);

 

 

Краткий итог статьи

Мы начали эту статью с рассмотрения установки отдельных разделов в настройке системы (System Config) и закончили изучением Хелпер классов, Списком контроля доступа (ACL) и иерархией Varian Form. Кроме того, что мы рассмотрели выше, есть возможность создания параметров System Config, которые используют специальные frontend и backend модели. Это мы рассмотрим в следующей статье.

 

 

 

Автор: Alan Storm (http://alanstorm.com/custom_magento_system_configuration/)

Перевод на русский: SebWeo

 
 

Все статьи данной серии:

  1. Magento для PHP MVC разработчиков (Alan Storm) – ч.1/11
  2. Magento для PHP MVC разработчиков – разбор контроллера (ч.2/11)
  3. Magento для PHP MVC разработчиков – Макеты, Блоки и Шаблоны (ч.3/11)
  4. Magento для PHP MVC разработчиков – Модели и основы ORM (ч.4/11)
  5. Magento для PHP MVC разработчиков – Инсталлирование Ресурса (ч.5/11)
  6. Magento для PHP MVC разработчиков – Расширенный ORM – EAV (ч.6/11)
  7. Magento для PHP MVC разработчиков – Особая конфигурация системы (ч.7/11)
  8. Magento для PHP MVC разработчиков – Углубленная настройка системы (ч.8/11)
  9. Magento для PHP MVC разработчиков – Коллекции Varien Data (ч.9/11)
  10. Magento для PHP MVC разработчиков – Переопределение и обновляемость системы (ч.10/11)
  11. Magento для PHP MVC разработчиков – Конфигурация системы по умолчанию (ч.11/11)

 



Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *