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

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

 

<fields>  <!-- ... --->   <fieldname translate="label">    <label>Field Name</label>    <frontend_type>text</frontend_type>    <sort_order>2</sort_order>    <show_in_default>1</show_in_default>    <show_in_website>1</show_in_website>    <show_in_store>0</show_in_store>   </fieldname>  <!-- ... --->  </fields>  

 

Итак, что означают все эти теги?

 

<label/> та <comment/>

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

Заголовок (label) отображается слева от поля формы, а комментарий отображается непосредственно под полем.

 

<show_in_default/>, <show_in_website/>, <show_in_store/>

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

 

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

<show_in_store>0</show_in_store>

но все равно будет возможно (хотя и не рекомендуется) устанавливать и получать значение этого поля на уровне магазина с помощью программных средств.

 

<sort_order/>

<sort_order/> — это численное значение, которое используется для определения порядка полей в их родительском контейнере. Чем выше число, тем ниже поле будет показываться на экране.



 

<frontend_type/>

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

  • image
  • label
  • multiselect
  • password
  • select
  • text
  • textarea
  • time

 

Значение этого поля используется в паттерне стиля для создания экземпляра класса в формате:

Varien_Data_Form_Element_Type  

где «Type» – это значение текстового узла <frontend_type/>. Это происходит в методе addField класса Varien_Data_Form_Element_Abstract, как показано ниже:

 

class Varien_Data_Form_Abstract extends Varien_Object {    //...  public function addField($elementId, $type, $config, $after=false) {    if (isset($this->_types[$type])) {      $className = $this->_types[$type];    }    else {      $className = 'Varien_Data_Form_Element_'.ucfirst(strtolower($type));    }      $element = new $className($config);    $element->setId($elementId);    if ($element->getRequired()) {      $element->addClass('required-entry');    }    $this->addElement($element, $after);    return $element;   }  }  

 

<frontend_class/>

Не дайте себя обмануть, <frontend_class/> не является Сгруппированным Названием Класса. Тег <frontend_class/> может использоваться для изменения атрибута класса тега в элементе формы, созданного для поля. То есть это поле конфигурации позволяет добавить CSS класс для тега формы.

 

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

<frontend_type>select</frontend_type>  <frontend_class>free-method</frontend_class>  

 

будет выглядеть так:

<select class="free-method">  

 

 

<validate/>

На первый взгляд <validate/> кажется чем-то очень сложным. Но этот тег всего лишь добавляет CSS класс полю формы. Такая конфигурация:

<validate>validate-email</validate>  

 

добавит следующий CSS-класс элементу формы:

<input type="text" class="validate-email" />  

 

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

 

Вы можете ознакомиться с доступными процедурами JavaScript проверки в файле:

js/prototype/validation.js  

 

и вот так выглядит вышеуказанная процедура проверки электронной почты в этом файле:

['validate-email', 'Please enter a valid email address. For example johndoe@domain.com.', function (v) {    return Validation.get('IsEmpty').test(v) || /^[a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]+(\.[a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})/i.test(v)  }],  

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

 

 

<can_be_empty/>

Тег <can_be_empty/> используется в полях с множественным выбором. Короче говоря: если вы хотите разрешить валидный «не выбрано» в конфигурации, воспользуйтесь этим полем.

 

Что происходит за кулисами, если значением can_be_empty является true? Система генерирует скрытое поле на странице настройки системы:

Файл: lib/Varien/Data/Form/Element/Multiselect.php    if ($this->getCanBeEmpty()) {    $html .= '<input type="hidden" name="' . parent::getName() . '" value="" />';  }  

которое обеспечивает то, что код обработки формы позволит «пустой» выбор.

 

 

<depends/>

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

Например, конфигурация системы Paypal Express имеет следующую определенную зависимость:

 

<specificcountry translate="label">    <label>Countries Payment Applicable From</label>    <frontend_type>multiselect</frontend_type>    <sort_order>110</sort_order>    <source_model>adminhtml/system_config_source_country</source_model>    <show_in_default>1</show_in_default>    <show_in_website>1</show_in_website>    <show_in_store>0</show_in_store>    <depends><allowspecific>1</allowspecific></depends>  </specificcountry>  

 

Вы заметили этот тег:

<depends><allowspecific>1</allowspecific></depends>  

 

Он говорит системе, что если есть поле <allowspecific> (определенное следующим образом):

 

<allowspecific translate="label">    <label>Payment Applicable From</label>    <frontend_type>select</frontend_type>    <sort_order>100</sort_order>    <source_model>adminhtml/system_config_source_payment_allspecificcountries</source_model>    <show_in_default>1</show_in_default>    <show_in_website>1</show_in_website>    <show_in_store>0</show_in_store>  </allowspecific>  

 

которое имеет значение «1», тогда поле «specificcountry» должно отображаться. Это происходит мгновенно с помощью определенного кода JavaScript.

 

Хотя это работает с любыми полями, которые присылают события onchange, система core Magento использует эту функцию только тогда, когда родительское поле выбрано.

 

 

<source_model/>

Тег <source_model/> указывает на класс Модели (в формате URI/Сгруппированное Имя Класса) для заполнения полей параметрами по умолчанию. В дополнение к стандартному Сгруппированному Имени Класса Magento, расширенный поддерживаемый синтаксис выглядит так:

module/modelname::methodName  

 

Система будет делать экземпляр модели с getModel('module/modelname') и вызывать его метод methodName для получения массива пар значение/заголовок для использования в качестве источника. Если имя метода отсутствует, будет вызван метод toOptionArray по умолчанию.

 

 

<frontend_model/>

По умолчанию Элементы формы Magento рендерятся с помощью класса Блока:

Mage_Adminhtml_Block_System_Config_Form_Field  

 

Однако, если вы хотите использовать специальный рендер для поля «Настройка системы», вы можете указать другой класс блока (в формате URI/Сгруппированное Имя Класса) используя тег <frontend_model/>.

Например, поле last_update в группе adminnotification:

 

<last_update translate="label">    <label>Last update</label>    <frontend_type>label</frontend_type>    <frontend_model>adminhtml/system_config_form_field_notification</frontend_model>    <sort_order>3</sort_order>    <show_in_default>1</show_in_default>    <show_in_website>0</show_in_website>    <show_in_store>0</show_in_store>  </last_update>  

 

указывает, что следует использовать для рендеринга поле adminhtml/system_config_form_field_notification. Эта запись переводится в следующий класс:

 

Файл: app/code/core/Mage/Adminhtml/Block/System/Config/Form/Field/Notification.php    class Mage_Adminhtml_Block_System_Config_Form_Field_Notification extends Mage_Adminhtml_Block_System_Config_Form_Field {    protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {      $element->setValue(Mage::app()->loadCache('admin_notifications_lastcheck'));      $format = Mage::app()->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM);      return Mage::app()->getLocale()->date(intval($element->getValue()))->toString($format);    }  }  

 

Метод _getElementHtml обеспечивает отображение введенной даты с таким же форматом.

 

 

<backend_model/>

После того, как форма будет отправлена Magento, ее значения должны быть сохранены в базе данных. В полях «Конфигурация системы», как правило, это касается класса Модели:

Mage_Core_Model_Config_Data  

Однако могут быть случаи, когда вам нужно, чтобы ваша конфигурация системы использовала другую модель бэкэнда. Тег <backend_model/> позволяет указать другой класс модели (с помощью формата URI/Сгруппированное Имя Класса).

Чаще всего это нужно для того, чтобы выполнить дополнительные действия, когда поле сохранено. Расширяя класс Mage_Core_Model_Config_Data вашей собственной моделью и определяя метод _beforeSave и/или _afterSave в вашей модели, вы можете применять дополнительные действия, когда изменяется значение конфигурации.

 

Например, рассмотрим поле import в группе tablerate:

 

<import translate="label">    <label>Import</label>    <frontend_type>import</frontend_type>    <backend_model>adminhtml/system_config_backend_shipping_tablerate</backend_model>    <sort_order>6</sort_order>    <show_in_default>0</show_in_default>    <show_in_website>1</show_in_website>    <show_in_store>0</show_in_store>  </import>  

 

Сгруппированное Имя Класса adminhtml/system_config_backend_shipping_tablerate превращается в следующий класс:

 

class Mage_Adminhtml_Model_System_Config_Backend_Shipping_Tablerate extends Mage_Core_Model_Config_Data {    public function _afterSave() {      Mage::getResourceModel('shipping/carrier_tablerate')->uploadAndImport($this);    }  }  

 

Здесь срабатывает метод _afterSave (который вызывается после сохранения модели), чтобы обновить Модель shipping/carrier_tablerate информацией с только что загруженного файла.

 

 

<upload_dir/> и <base_url/>

Оба этих тега используются в полях «Конфигурация системы», которые используют поле

<frontend_type>image</frontend_type>  

с моделью бэкенда

<backend_model>adminhtml/system_config_backend_image</backend_model>.  

Они определяют:

  1. Где загружается файл с изображением
  2. Базовый путь URI, который используется при воспроизведении тега <img>

 

Во-первых, давайте рассмотрим тег <upload_dir/>

<upload_dir config="system/filesystem/media" scope_info="1">sales/store/logo</upload_dir>  

 

Здесь есть три основные вещи:

  1. Базовый путь для загрузки изображения
  2. Путь, от базового, по которому нужно загружать это конкретное поле изображения
  3. Следует ли добавлять текущую конфигурацию к пути

 

Путь к загрузке базового изображения устанавливается с помощью атрибута config (выше это system/filesystem/media). Он указывает путь к конфигурации системы. То есть это значение системной конфигурации Magento (которая относится к {{root_dir}}/media в инсталляции Community Edition по умолчанию).

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

sales/store/logo  

к значению базового пути загрузки изображения, что даст нам нечто подобное:

{root-magento}/media/sales/store/logo  

 

Наконец, если для атрибута scope установлено значение «1», текущий контекст конфигурации будет преобразован в путь. Если вы загружали изображения в контексте default, то вы получите путь типа:

{root-magento}/media/sales/store/logo/default  

 

Однако, если вы загрузили изображение в контексте определенного магазина, вы получите путь типа:

{root-magento}/media/sales/store/logo/stores/5  

 

где «5» – это идентификатор магазина, из которого вы сейчас редактируете настройки.
Когда мы загружаем изображения, только контекст и название картинки сохраняются в конфиге. Это означает, что нам нужно сообщить системе, какой базовый URL-адрес использовать для нашего изображения.

<base_url type="media" scope_info="1">sales/store/logo</base_url>  

 

Область scope_info и текстовый узел функционируют так же, как и <upload_dir/>. Где <base_url/> отличается в настройке базового URI изображения (который, естественно, будет отличаться от локального базового файлового пути).

Базовый путь устанавливается с помощью атрибута type. Заданное значение будет передано в метод getBaseUrl в глобальном объекте Mage для установления базового URL-адреса изображения. Приведенный выше пример будет выглядеть примерно так:

Mage::getBaseUrl('media')  

 

Вы можете увидеть весь код в классе Mage_Adminhtml_Block_System_Config_Form_Field_Image.

 

class Mage_Adminhtml_Block_System_Config_Form_Field_Image extends Varien_Data_Form_Element_Image {  //...    protected function _getUrl() {      $url = parent::_getUrl();      $config = $this->getFieldConfig();      /* @var $config Varien_Simplexml_Element */      if (!empty($config->base_url)) {        $el = $config->descend('base_url');        $urlType = empty($el['type']) ? 'link' : (string)$el['type'];        $url = Mage::getBaseUrl($urlType) . (string)$config->base_url . '/' . $url;      }      return $url;    }  //...  }  

 

 

 

Краткий вывод

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

 

 

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

Перевод на русский: 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)