Разработка модулей для Magento 1.x — большой гайд + видео
Привет, Хабр! Несмотря на давно уже выпущеную Magento 2, Magento первой версии еще живее всех живых и пока еще не собирается нас покидать. Команда Magento будет поддерживать первую версию продукта 3 года с даты выпуска версии 2, т.е. примерно до ноября 2018. Рынок пестрит широчайшим выбором тем, модулей и сервисов заточеных под Magento 1.x версии. И большое количество сайтов, которые сейчас на Magento 1.x, не торопятся обновляться. Работы много — выхлопа мало. А значит, разработка под Magento первых версий еще актуальна и так будет несколько лет.
Но не о перспективах развития e-commerce решений пойдет речь в этой статье. Тут я решил собрать своеобразный гайд по созданию модулей для Magento 1.x (далее просто Magento). Но не простой гайд, в котором надо всего лишь следовать инструкциям, а с небольшими пояснениями «почему пишем так, а не иначе». Я старался найти золотую середину между краткостью и достаточностью. И в первую очередь, гайд несет пользу новичкам в деле разработки модулей для Magento. Но и более опытным пользователям данный материал может принести пользу.
Собственно, я старался сделать каждую часть самодостаточной, т.е. если вас интересует только отдельный момент, то вы можете взять всю необходимую информацию из конкретного раздела и не бегать по всему гайду. А если уже какие-то участки из раздела у вас реализованы, то их можно и пропустить. Такое же и отношение к видео. Только видео уроков достаточно для работы, но и без видео можно обойтись, порядок дейтсвий и листинги с комментариями есть. Хотя некоторые вещи лучше глянуть в видео, т.к. там по мимо кодинга еще присутствуют и демонстрации работоспособности. Да и я просто мог, что-то упустить. Так что в видео могут присутствуют некоторые незадокументированные моменты, и в текстовой версии могут быть дополнения, которых нет в видео. Это было не избежно, т.к. все делалось в разное время.
- Сервер на Ubuntu 16.04 LTS
- Установка тестового магазина
- Структура и конфигурация модуля
- Отладка кода XDEBUG + PHPSTORM
- Модели, коллекции. Работа с базой данных
- Контроллеры и роутинг
- Хелперы
- Конфигурация модуля в админке
- Frontend блоки. Макеты. Темплейты
- Admin интерфейс. Грид. Форма редактирования
- События и слушатели
- Крон и задачи по расписанию
- Использование рендереров в админке
- Использование WYSIWYG редактора
- Использование Rule Conditions (условий)
- Использование вкладок на странице редактирования
- Вывод таблицы (grid) товаров на странице редактирования и на frontend.
- Создание модуля способа оплаты (Payment Method)
- Модуль способа доставки (Shipping Method)
Подготовка
Все начинается с подготовки рабочего места, а в нашем случае — сервера с установленым тестовым магазином.
Если, у вас окружение уже готово — можете перейти к следующему разделу.
Сервер на Ubuntu 16.04 LTS
Скачиваем дистрибутив Ubuntu 16.04, конфигурируем «виртуалку». И устанавливаем Ubuntu на наш виртуальный компьютер. Процесс установки в целом простой и не требует документации, но весь процесс установки и настройки можно пройти в видео ниже.
Установим и настроим необходимый софт.
sudo su
apt-get install && apt-get upgrade
Ставим файловый менеджер, редактор и диспетчер задач
apt-get install mc nano htop
Настроим статически IP адрес (в принципе это можно и не делать, а статический адрес назначить на стороне роутера):
nano /etc/network/interfaces
Пример настройки:
iface eth0 inet static
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
dns-nameservers 192.168.0.1 8.8.8.8
auto eth0
где eth0 — сетевой интерфейс. Его можно посмотреть написав ifconfig
Вебсервер Nginx:
apt-get install nginx
PHP 7.0 FPM:
apt-get install php-fpm php-xdebug php-soap php-gd php-mbstring php-mcrypt php-curl php-xml
MySQL 5.7 и phpMyAdmin:
apt-get install mysql-server-5.7 phpmyadmin
Сменим владельца и права на папку, где будут файлы магазина:
chown -R dev:dev /var/www
chmod -R 777 /var/www
dev: dev — имя и группа пользователя. Я использовал это имя при установке Ubuntu.
Теперь необходимо настроить установленое ПО.
Nginx
Я сделал 3 конфига для Nginx: динамический домен, конфиг для Magento 2 (пригодится), конфиг для phpMyAdmin. Прицнип действия так называемого конфига с динамическими доменами прост.
- Мы настраиваем у себя соответствие домен — IP. Как мы это делаем, не важно, я прописываю в hosts файле. Например, magento.dev 192.168.0.100
- Когда Nginx получает запрос, он делает server_root путь вида /var/www/(доменное имя). Пример: пишем в браузере magento.dev — server_root /var/www/magento.dev
- Ну, а наш магазин необходимо разместить в папке /var/www/magento.dev
server {
listen 80;
server_name $http_host;
root /var/www/$http_host;
location / {
index index.html index.php;
try_files $uri $uri/ @handler;
expires 30d;
}
location /. {
return 404;
}
location @handler {
rewrite / /index.php;
}
location ~ .php/ {
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ {
if (!-e $request_filename) { rewrite / /index.php last; }
expires off;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name;
fastcgi_param MAGE_RUN_TYPE store;
include fastcgi_params;
}
}
# Magento Vars
#
# Example configuration:
upstream fastcgi_backend {
server unix:unix:/run/php/php7.0-fpm.sock;
}
server {
set $MAGE_ROOT /var/www/m2.dev;
set $MAGE_MODE default; # or production or developer
listen 80;
server_name m2.dev;
root /var/www/m2.dev/pub;
index index.php;
autoindex off;
charset off;
add_header 'X-Content-Type-Options' 'nosniff';
add_header 'X-XSS-Protection' '1; mode=block';
location /setup {
root $MAGE_ROOT;
location ~ ^/setup/index.php {
fastcgi_pass fastcgi_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ ^/setup/(?!pub/). {
deny all;
}
location ~ ^/setup/pub/ {
add_header X-Frame-Options "SAMEORIGIN";
}
}
location /update {
root $MAGE_ROOT;
location ~ ^/update/index.php {
fastcgi_split_path_info ^(/update/index.php)(/.+)$;
fastcgi_pass fastcgi_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
# deny everything but index.php
location ~ ^/update/(?!pub/). {
deny all;
}
location ~ ^/update/pub/ {
add_header X-Frame-Options "SAMEORIGIN";
}
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location /pub {
location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) {
deny all;
}
alias $MAGE_ROOT/pub;
add_header X-Frame-Options "SAMEORIGIN";
}
location /static/ {
if ($MAGE_MODE = "production") {
expires max;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
add_header X-Frame-Options "SAMEORIGIN";
}
location /media/ {
try_files $uri $uri/ /get.php?$args;
location ~ ^/media/theme_customization/.*\.xml {
deny all;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;
try_files $uri $uri/ /get.php?$args;
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;
try_files $uri $uri/ /get.php?$args;
}
add_header X-Frame-Options "SAMEORIGIN";
}
location /media/customer/ {
deny all;
}
location /media/downloadable/ {
deny all;
}
location /media/import/ {
deny all;
}
location ~ cron\.php {
deny all;
}
location ~ (index|get|static|report|404|503)\.php$ {
try_files $uri =404;
fastcgi_pass fastcgi_backend;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
fastcgi_param PHP_VALUE "memory_limit=256M \n max_execution_time=600";
fastcgi_read_timeout 600s;
fastcgi_connect_timeout 600s;
fastcgi_param MAGE_MODE $MAGE_MODE;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
server {
listen 80;
server_name pma myadmin;
root /usr/share/phpmyadmin/;
index index.php;
location /setup/index.php {
deny all;
}
location ~ .php$ {
if (!-e $request_filename) { rewrite / /index.php last; }
expires off;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name;
fastcgi_param MAGE_RUN_TYPE store;
include fastcgi_params;
}
include fastcgi_params;
}
Кладем конфиги в папку /etc/nginx/sites-availiable/ и делаем симлинки на них в папке /etc/nginx/sites-enabled/. Или просто складываем их в папку /etc/nginx/sites-enabled/
PHP 7.0 FPM
Редактируем /etc/php/7.0/fpm/php.ini. Нас волнуют только некоторые параметры, которые в принципе можно настроить на свой вкус.
max_execution_time = 300
max_input_time = 160
memory_limit = 512M
display_errors = On
log_errors = On
html_errors = On
date.timezone = (тут свою таймзону указать)
Samba server
Мне нравится работать через самбу, подмонтировать себе сетевой диск и спокойно копировать файлы. Но вам она может и не понадобиться. На вкус и цвет, как говорится… Мой конфиг таков:
[global]
workgroup = WORKGROUP
server string = %h server (Samba, Ubuntu)
dns proxy = no
log file = /var/log/samba/log.%m
max log size = 1000
syslog = 0
panic action = /usr/share/samba/panic-action %d
server role = standalone server
passdb backend = tdbsam
obey pam restrictions = yes
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
pam password change = yes
map to guest = bad user
null passwords = Yes
guest account = www-data
[www]
path = /var/www/
comment = WWW folder
guest ok = yes
browseable = yes
read only = no
locking = no
force user = www-data
force group = www-data
Установка тестового магазина
Процесс установки прост и не требует каких-то особых умений. Но для внесения ясности, оставлю видео-инструкцию спрятанную под спойлером.
Cоздание модуля
Структура и конфигурация
Созданная в уроке структура модуля IGN_Siteblocks-1.zip
Учиться создавать модули будем на примере модуля для вывода блоков на страницах магазина (его frontend части). И первым делом мы придумываем название модуля. Название должно быть коротким и нести смысл. А еще нам нужно выбрать неймспейс (обычно название компании разработчика или его ФИО). И финальное наименование принимает вид Namespace_Modulename. В нашем случае я назвал IGN_Siteblocks.
Создадим регистрационный XML файл:
true
local
Поговорим о codePool. Всего их 3: local, community, core (и enterprise в Enterprise версии Magento).
И сразу решим, что в core мы ничего изменять не будем, там базовые файлы системы и если их надо изменить, то есть другие способы, помимо их непосредственного редактирования.
Мы можем спокойно использовать local и community (На самом деле, лучше сразу взять community, но в этом примере будет local).
Зайдем в админку магазина, в раздел System > Configuration > Advanced > Disable Modules Output и увидим наш IGN_Siteblocks.
Создадим папки для нашего модуля:
app/code/local/IGN/Siteblocks/
- Block — классы блоков, отвечают за рендеринг страниц
- controllers — контроллеры принимают запросы
- etc — тут всякие конфигурационные файлы
- Helper — дополнительные классы помощники
- Model — модели
- sql — инсталяционные скрипты
Модули в Magento реализуют паттерн MVC. У нас есть модели, вид (блоки, темплейты и макеты) и контроллеры. В папке etc создадим config.xml
1.0.0
Тут мы будем декларировать наши блоки, модели, контроллеры, хелперы, обсерверы, реврайты, макеты, переводы и стандартные значения некоторых настроек модуля.
Отладка кода XDEBUG + PHPSTORM
Тут я бы все-таки рекомендовал посмотреть на видеоинструкцию. Сначала настроим сервер:
apt-get install php-xdebug
Отредактируем настройки в php.ini или xdebug.ini
zend_extension = xdebug.so
xdebug.idekey = "PHPSTORM"
xdebug.remote_autostart = 1
xdebug.remote_connect_back = 1
xdebug.remote_enable = 1
xdebug.remote_port = 9000
Сохраняем и не забываем перезагрузить сервис service php7.0-fpm restart. В PHPSTORM создаем новый Remote Debug конфиг.
Добавляем сервер с соответсвтующим адресом и портом. В поле IDE key вводим слово PHPSTORM.
Модели, коллекции. Работа с базой данных.
Созданная в уроке структура модуля IGN_Siteblocks-2.zip
Модели представляют собой классы для работы с данными и только данными. Никаких тонкостей со способом сохранения этих данных в базе. Никакого кода связанного с рендерингом этих данных. В Magento это: Customer, Product, Order и тд.
Что бы наш модуль мог использовать модели, необходимо отконфигурировать config.xml
Напомню, что модели, блоки и хелперы добавляются в global секцию. config.xml принимает следующий вид:
1.0.0
IGN_Siteblocks_Model
siteblocks_resource
IGN_Siteblocks_Resource
ign_siteblock
IGN_Siteblocks
Важно определиться с названием префикса (не знаю какой термин тут подойдет лучше). Я выбрал siteblocks. Это произвольное название и как правило формируется из неймспейса и имя модуля или только имени модуля. Ну или для запутывания разработчиков, можно выбрать совершенно произвольную строку, заранее прикупив оберег от проклятий.
Выбирайте четко и желательно без использования заглавных символов. Одна опечатка, и будете долго копаться, искать проблему. Название модели и привязка к таблице. Имя модели соответствует названию файла модели. Название таблицы в базе произвольное. В моем случае что бы обратиться к модели, нужно написать так:
Mage::getModel('siteblocks/block');
Теперь можно добавлять модели. Создадим модель Block. Для каждой, привязанной к таблице, модели нужно создавать 3 файла: модель, ресурсная модель, модель коллекции. Модель абстрагируется от работы с базой, ресурсные модели находятся уровнем ниже. Там мы реализуем логику фильтрации, сортировки, обработки данных до их сохранения и после загрузки из базы.
Код модели Block.php:
_init('siteblocks/block'); //Все в соотвествии с указанными в config.xml параметрами
}
}
Модели наследуется от Mage_Core_Model_Abstract. Ресурсные модели сохраняем в папке Model/Resource.
_init('siteblocks/block','block_id'); //block_id это наш PRIMARY KEY в таблице, по умолчанию entity_id
}
}
_init('siteblocks/block');
}
}
Наши классы пусты, но они уже реализуют необходимый минимум функционала по наследованию.
Добавлять в них код будем по необходимости. А если мы хотим добавить еще моделей, то добавляем еще одну привязку модели к таблице и новых 3 файла. Можно сколько угодно добавлять моделей, не привязанных к таблице (просто для реализации какого-то функционала), то просто добавляем новый файл, наследоваться от Mage_Core_Model_Abstract не обязательно.
Не забываем создать инсталяционный скрипт, который будет создавать таблицу для нашей модели.
startSetup();
$installer->run("
CREATE TABLE IF NOT EXISTS `{$this->getTable('siteblocks/block')}` (
`block_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(500) NOT NULL,
`content` text NOT NULL,
`block_status` tinyint(4) NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`block_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
");
//Альтернативный способ создания таблицы
$table = $installer->getConnection()
->newTable($this->getTable('siteblocks/block'))
->addColumn('block_id',Varien_Db_Ddl_Table::TYPE_INTEGER,null,array(
'identity' => true,
'unsigned' => true,
'nullable' => false,
'primary' => true
))
->addColumn('title',Varien_Db_Ddl_Table::TYPE_VARCHAR,null,array(
'nullable' => false
))
->addColumn('content',Varien_Db_Ddl_Table::TYPE_TEXT,null,array(
'nullable' => false
))
->addColumn('block_status',Varien_Db_Ddl_Table::TYPE_TINYINT,null,array(
'nullable' => false
))
->addColumn('created_at',Varien_Db_Ddl_Table::TYPE_DATETIME,null,array(
'nullable' => false
));
$installer->endSetup();
ВАЖНЫЙ МОМЕНТ!
Если вы уже пробовали зайти в админку, при установленом модуле, когда еще не было инсталяционного скрипта. Скорее всего ваш инсталл скрипт больше никогда не запустится. В этом случае необходимо найти и удалить запись siteblocks_setup из таблицы core_resource в базе магазина.
При апгрейде версии модуля. Мы указываем новую версию в config.xml, например: 1.0.1. И создаем апгрейд скрипт: upgrade-1.0.0–1.0.1.php. И в таком же духе при последующих апгрейдах.
Говоря о моделях и коллекциях, нельзя не упомянуть о самых базовых методах этих классов.
//Загрузить объект из таблицы block_id = 1
$block = Mage::getModel('siteblocks/block')->load(1);
//Удалить блок
$block->delete();
//Cохранить
$block->save();
//удалить блок не делая его загрузки из базы
Mage::getModel('siteblocks/block')->setId(1)->delete();
//Загрузить коллекцию блоков из таблицы
$blocks = Mage::getModel('siteblocks/block')->getCollection();
//Коллекция блоков где block_id = 1, 2 и 3
$blocks->addFieldToFilter('block_id',array('in'=>array(1,2,3))) ;
echo $blocks->getSelect(); //выведет сформировавшийся SQL запрос
//Альтернативный способ загрузки коллекции
$blocks = Mage::getResourceModel('siteblocks/block_collection');
Контроллеры и роутинг
Созданная в уроке структура модуля IGN_Siteblocks-3.zip
Контроллеры, согласно паттерну MVC, отвечают за обработку запросов. Принимают на себя так называемый входной сигнал в виде HTTP запроса. Перешел по ссылке — отработал соответствующий контроллер.
Перед созданием контроллеров сконфигурируем роутинг в config.xml. Роутинг для frontend и admin части настраивается отдельно. А значит добавляем routers в секцию frontend и admin.
config.xml принимает вид:
1.0.0
IGN_Siteblocks_Model
siteblocks_resource
IGN_Siteblocks_Resource
ign_siteblock
IGN_Siteblocks
IGN_Siteblocks
siteblocks
IGN_Siteblocks_Adminhtml
Теперь можно создавать свои контроллеры в папке controllers нашего модуля. Класс контроллера для frontend части должен наследоваться от класса Mage_Core_Controller_Front_Action.
Создадим тестовый контроллер TestController.php
Если сейчас перейти по URL вида example.com/siteblocks/test/mytest. Вы увидете белый экран с надписью «test». Если этого не произошло, значит на каком-то этапе произошла ошибка.
Перепроверяйте код и читайте логи. URL состоит из router (siteblocks) / controller (TestController) / action (mytestAction)
GET параметры можно передавать 2 мя способами:
- Классическим способом: example.com/siteblocks/test/mytest? param=val¶m2=val
- Через слэши: example.com/siteblocks/test/mytest/param/val/param2/val
Контроллеры для админки создаются в папке controllers/Adminhtml. Класс контроллера для frontend части должен наследоваться от класса Mage_Adminhtml_Controller_Action.
Создадим тестовый контроллер TestController.php:
На него можно зайти по URL: example.com/admin/test/mytest — где admin это ваш путь в админку.
И тут есть ньюанс: такой урл уже может быть занят другим модулем. Выхода тут 2: меняем название контроллера на заведомо неконфликтное (например IgntestController.php) или складываем контроллеры в подпапку.
Теперь наш URL принимает вид: example.com/admin/siteblocks_test/mytest
Хелперы
Созданная в уроке структура модуля IGN_Siteblocks-4.zip
Классы хелперов в Magento используются как дополнительные классы. В них стоит реализовывать стороннюю логику, которая не вписывается в функционал моделей, блоков или контроллеров. Но модуль нуждается как минимум в одном классе хелпера Data.php.
Этот хелпер используется по-умолчанию для перевода текста (лейблов, пунктов меню и тд) и другой логики.
В хелпере рекомендуется декларировать методы чтения настроек из конфига. Хелперы должны наследоваться от класса Mage_Core_Helper_Abstract.
Для переводов текста в хелпере существует метод __(), а его применение выглядит так:
echo Mage::helper('siteblocks')->__('Some text')
Файлы переводов мы декларируем в config.xml.
1.0.0
IGN_Siteblocks_Model
siteblocks_resource
IGN_Siteblocks_Resource
ign_siteblock
IGN_Siteblocks
IGN_Siteblocks_Helper
IGN_Siteblocks
siteblocks
IGN_Siteblocks.csv
IGN_Siteblocks_Adminhtml
А файл IGN_Siteblocks.csv создаем в папке app/locale/en_US/. Содержимое вида: «Some text», «Some text».
Стараемся выводить текст с использованием своего хелпера и в таком случае, упрощается локализация модуля на разные языки.
Достаточно скопировать файл переводов в соответствующую локаль и перевести второй столбец и нет необходимости копаться в коде.
Конфигурация модуля в админке
Созданная в уроке структура модуля IGN_Siteblocks-5.zip
Для придания модулю гибкости, мы создадим страницу с настройками модуля. Делается это сугубо через xml файлы. Нам необходимо создать 2 файла:
system.xml — где будут добавлены поля
adminhtml.xml — где будут указаны разделы и права доступа
А стандартные значения настроек мы можем указать в секции default в файле config.xml
1.0.0
IGN_Siteblocks_Model
siteblocks_resource
IGN_Siteblocks_Resource
ign_siteblock
IGN_Siteblocks
IGN_Siteblocks_Helper
IGN_Siteblocks
siteblocks
IGN_Siteblocks.csv
IGN_Siteblocks_Adminhtml
1
10
Siteblocks
2
ign
text
1
1
1
1
1
1
1
1
1
select
siteblocks/source_status
1
1
1
1
Is module enabled
text
2
1
1
1
1
textarea
3
1
1
1
1
В наших настройках выводится дропдаун с опциями, и используется собственная модель для этих опций:
self::ENABLED, 'label'=>Mage::helper('siteblocks')->__('Enabled')),
array('value' => self::DISABLED, 'label'=>Mage::helper('siteblocks')->__('Disabled')),
);
}
/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return array(
self::DISABLED => Mage::helper('siteblocks')->__('Disabled'),
self::ENABLED => Mage::helper('siteblocks')->__('Enabled'),
);
}
Frontend блоки. Макеты. Темплейты
Созданная в уроке структура модуля IGN_Siteblocks-6.zip
Займемся выводом информации на frontend части магазина. И, как не сложно догадаться из заголовка, у нас будут задействованы 3 типа файлов: блоки, макеты и темплейты.
Блоки это классы, отвечающие за подготовку и вывод информации. Блоки используют для вывода темплейты, но не всегда. Если используется темплейт, то он просто инклюдится в методе fetchView:
Поэтому из темплейта к блоку обращаемся через $this.
getCollection()
->addFieldToFilter('block_status',array('eq'=>IGN_Siteblocks_Model_Source_Status::ENABLED));
}
}
Блок наследуется от класса Mage_Core_Block_Template . Но это зависит от того, что наш блок будет выводить. Так, например, при выводе списка товаров, желательно наследоваться от блока Mage_Catalog_Block_Product_List. Макеты используются для построения структуры страницы, какие элементы выводить на странице и в каком порядке.
Создадим файл макетов:
My Siteblocks
В макете мы можем добавлять js, css файлы в head, мы можем добавить или удалить блок в на какой-то интересующей нас странице. Тема макетов довольно обширна и сверху я привел минимально простой макет, который добавит наш блок в нескольких местах сайта.
Альтернативным вариантом (без макето) вы можете в контроллере вывести HTML код:
$html = Mage::app()->getLayout()->createBlock('siteblocks/list')->setTemplate('siteblocks/list.phtml')->toHtml()
$this->getResponse()->setBody($html);
И будет выведен HTML код только этого блока. Такое часто нужно, например при использовании AJAX запросов.
В макете у нас упоминается файл siteblocks/list.phtml. Его можно и не указывать, если в темплейте указать его по-умолчанию.
class IGN_Siteblocks_Block_List extends Mage_Core_Block_Template {
protected $_template = 'siteblocks/list.phtml';
}
Создадим темплейт:
getBlocks() as $block):?>
getTitle()?>
getContent()?>
Как видно в коде, мы вызываем метод блока getBlocks, возвращающий коллекцию записей, которые мы и выводим. Переименуем TestController или создадим новый. IndexController
loadLayout(); #загружаем макеты
$this->renderLayout(); #выводим html
}
}
URL по которому мы увидим вывод имеет вид: example.com/siteblocks/index/index или example.com/siteblocks, т.к. index/index можно опустить.
А handle в макете будет использоваться такой: siteblocks_index_index. Чтобы посмотреть на вывод записей, необходимо добавить их на прямую в базу или перейти к следующему шагу разработки формы редактирования.
Admin интерфейс. Грид. Форма редактирования.
Созданная в уроке структура модуля IGN_Siteblocks-7.zip
Процесс создания Admin интерфейса состоит из нескольких этапов:
- Добавляем пункты в меню
- Создаем блоки
- Создаем контроллеры
Добавляем пункты в меню: