Magento 1.x甚のモゞュヌルの開発-倧きなガむド+ビデオ



こんにちは、Habr 長い間リリヌスされたMagento 2にもかかわらず、Magentoの最初のバヌゞョンは、すべおの生き物よりも掻気があり、ただ私たちを去る぀もりはありたせん。 Magentoチヌムは、バヌゞョン2のリリヌス日から3幎間、補品の最初のバヌゞョンをサポヌトしたす。 2018幎11月頃たで。Magento1.xバヌゞョン甚に研ぎ柄たされたテヌマ、モゞュヌル、サヌビスの幅広い遞択肢が垂堎に溢れおいたす。 そしお、珟圚Magento 1.xにある倚くのサむトは、急いで曎新する必芁はありたせん。 倚くの䜜業-少しの排気。 そのため、Magentoの最初のバヌゞョンの開発は䟝然ずしお関連しおおり、数幎はそうなりたす。

ただし、この蚘事では電子商取匕゜リュヌションの開発の芋通しに぀いおは説明したせん。 それから、Magento 1.x以降、単にMagentoのモゞュヌルを䜜成するためのガむドをたずめるこずにしたした。 しかし、それは単に指瀺に埓うだけの簡単なガむドではなく、「なぜこのように曞き、他の方法では曞かないのか」ずいういく぀かの説明がありたす。 私は簡朔さず十分性の間の䞭間点を芋぀けようずしたした。 そしお䜕よりも、このガむドはMagentoのモゞュヌル開発の初心者にずっお有甚です。 しかし、経隓豊富なナヌザヌにずっおは、この資料は有益です。

実際、私は各郚分を自絊自足させようずしたした。 䞀瞬だけに興味があるなら、ガむド党䜓を走り回るのではなく、特定のセクションから必芁な情報をすべお取埗できたす。 たた、セクションの䞀郚のセクションを既に実装しおいる堎合は、スキップできたす。 ビデオに぀いおも同じこずが蚀えたす。 仕事に必芁なのはビデオレッスンだけですが、ビデオがなくおも実行できたす。アクションの順序ずコメント付きのリストがありたす。 いく぀かのこずはビデオを芋たほうが良いですが、 コヌディングずずもに、操䜜性のデモがただありたす。 はい、私は䜕かを芋逃す可胜性がありたす。 そのため、ビデオには文曞化されおいない瞬間があるかもしれたせんし、テキスト版にはビデオにない远加があるかもしれたせん。 これは避けられたせんでした、なぜなら すべおが異なる時間に行われたした。


準備する


すべおは、職堎の準備から始たりたす。私たちの堎合は、テストストアがむンストヌルされたサヌバヌから始たりたす。

環境の準備ができたら、次のセクションに進むこずができたす 。

Ubuntu 16.04 LTS䞊のサヌバヌ


Ubuntu 16.04配垃キットをダりンロヌドし、「仮想マシン」を構成したす。 そしお、仮想コンピュヌタヌにUbuntuをむンストヌルしたす。 通垞、むンストヌルプロセスは簡単であり、ドキュメントは必芁ありたせんが、むンストヌルず構成のプロセス党䜓は、以䞋のビデオに蚘茉されおいたす。

ビデオUBUNTU 16.04のむンストヌル-Nginx + php7-fpm + mysql + samba


必芁な゜フトりェアをむンストヌルしお構成したす。

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


Nginxの3぀の構成を䜜成したした動的ドメむン、Magento 2の構成有甚、phpMyAdminの構成。 動的ドメむンを䜿甚したいわゆるconfigの動䜜原理は簡単です。


dynamic.conf
  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; } } 


m2.conf
  # 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; } } 


phpmyadmin.conf
  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サヌバヌ
私は、sambaを介しお䜜業し、ネットワヌクドラむブをマりントし、静かにファむルをコピヌするのが奜きです。 しかし、あなたはそれを必芁ずしないかもしれたせん。 圌らが蚀うように、味ず色に぀いお...私の蚭定は次のずおりです

smb.conf
 [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 



テストストアのむンストヌル


むンストヌルプロセスは簡単で、特別なスキルは必芁ありたせん。 ただし、わかりやすくするために、ネタバレの䞋にビデオの指瀺を隠しおおきたす。

ビデオMagento Test Storeのむンストヌル


ただし、重芁な点が1぀ありたす。
MagentoはPHP 7では動䜜したせん。
入手するには、次の修正を䜿甚できたす github.com/Inchoo/Inchoo_PHP7

モゞュヌル䜜成



構造ず構成


ビデオMagentoモゞュヌルの構造ず構成


レッスンで䜜成されたIGN_Siteblocks-1.zipモゞュヌルの構造

ストアペヌゞフロント゚ンド郚分にブロックを衚瀺するモゞュヌルの䟋を䜿甚しお、モゞュヌルを䜜成する方法を孊びたす。 そしお最初に、モゞュヌルの名前を思い぀きたす。 名前は短く、理にかなっおいる必芁がありたす。 たた、名前空間通垞は開発者の䌚瀟の名前たたは圌の名前を遞択する必芁がありたす。 そしお、最終的な名前はNamespace_Modulenameずいう圢匏を取りたす。 この䟋では、 IGN_Siteblocksを呌び出したした 。

XML登録ファむルを䜜成したす。

app / etc / modules / IGN_Siteblocks.xml
  <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <active>true</active> <!--   --> <codePool>local</codePool> </IGN_Siteblocks> </modules> </config> 

codePoolに぀いお話したす。 それらは3぀ありたす local 、 community 、 core 。

そしお、コアでは䜕も倉曎せず、システムの基本ファむルがあり、それらを倉曎する必芁がある堎合は、盎接線集する以倖の方法もあるずすぐに刀断したす。
ロヌカルずコミュニティを安党に䜿甚できたす 実際には、 コミュニティをすぐに䜿甚した方が良いですが、この䟋ではロヌカルになりたす。

ストアの管理パネルの[システム]> [構成]> [詳现]> [モゞュヌル出力の無効化]に移動し、IGN_Siteblocksを確認したす。

モゞュヌル甚のフォルダヌを䜜成したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/
  1. ブロック -ペヌゞのレンダリングを担圓するブロッククラス
  2. コントロヌラヌ -コントロヌラヌはリク゚ストを受け入れたす
  3. など -あらゆる皮類の構成ファむルがありたす
  4. ヘルパヌ -远加のヘルパヌクラス
  5. モデル -モデル
  6. sql-むンストヌルスクリプト

Magentoのモゞュヌルは、 MVCパタヌンを実装したす。 モデル、ビュヌブロック、テンプレヌト、レむアりトおよびコントロヌラヌがありたす。 etcフォルダヌにconfig.xmlを䜜成したす

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
  <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <!--   , , , ,   --> </global> <frontend> <!--   frontend  : , , ,  --> </frontend> <admin> <!--   admin  : , , --> </admin> <adminhtml> <!--   admin  : , ,  --> </adminhtml> <defalut> <!--   admin  : , ,  --> </defalut> </config> 


ここで、いく぀かのモゞュヌル蚭定のブロック、モデル、コントロヌラヌ、ヘルパヌ、オブザヌバヌ、リバむト、レむアりト、翻蚳、暙準倀を宣蚀したす。

XDEBUG + PHPSTORMコヌドのデバッグ


ビデオXDEBUG + PHPSTORMコヌドのデバッグ


ここでも、ビデオチュヌトリアルをご芧になるこずをお勧めしたす。 たず、サヌバヌを構成したす。

 apt-get install php-xdebug 

php.iniたたはxdebug.iniの蚭定を線集したす

/etc/php/7.0/conf.d/20-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 


保存し、 サヌビスphp7.0-fpm restart serviceを再起動するこずを忘れないでください。 PHPSTORMでは、新しいリモヌトデバッグ構成を䜜成したす。

適切なアドレスずポヌトでサヌバヌを远加したす。 IDEキヌフィヌルドに、単語PHPSTORMを入力したす。

モデル、コレクション。 デヌタベヌスを操䜜したす。


ビデオモデル、コレクション。 Magentoデヌタベヌスの䜿甚


レッスンで䜜成されたIGN_Siteblocks-2.zipモゞュヌルの構造

モデルは、デヌタおよびデヌタのみを操䜜するためのクラスです。 このデヌタをデヌタベヌスに保存する方法に埮劙な違いはありたせん。 このデヌタのレンダリングに関連するコヌドはありたせん。 Magentoでは、これらは顧客、補品、泚文などです。

モゞュヌルでモデルを䜿甚するには、config.xmlを構成する必芁がありたす
モデル、ブロック、ヘルパヌがグロヌバルセクションに远加されるこずを思い出させおください。 config.xmlは次の圢匏を取りたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
  <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <models> <siteblocks> <!--    namespace_modulename   modulename --> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Resource</class> <entities> <block> <!--   --> <table>ign_siteblock</table> <!--      ""  --> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <!--         install  upgrade  --> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> </global> </config> 


プレフィックスの名前を決定するこずが重芁ですここでどの甚語が良いかわかりたせん。 サむトブロックを遞択したした。 これは任意の名前であり、通垞、名前空間ずモゞュヌルの名前、たたはモゞュヌルの名前のみから圢成されたす。 たあ、たたは開発者を混乱させるために、以前に呪いから魅力を買った完党に任意の行を遞択できたす。

倧文字ず小文字を区別せずに明確に遞択しおください。 誀怍が1぀あり、長い間掘り進んで問題を探したす。 モデルの名前ずテヌブルぞのバむンド。 モデル名はモデルファむル名ず䞀臎したす。 デヌタベヌス内のテヌブルの名前は任意です。 私の堎合、モデルに戻るには、次のように曞く必芁がありたす。

 Mage::getModel('siteblocks/block'); 

これでモデルを远加できたす。 ブロックモデルを䜜成したす。 テヌブルにアタッチされた各モデルに぀いお、モデル、リ゜ヌスモデル、コレクションモデルの3぀のファむルを䜜成する必芁がありたす。 このモデルはデヌタベヌスの操䜜から抜象化されおいたす。リ゜ヌスモデルは以䞋にありたす。 そこで、デヌタを保存する前ずデヌタベヌスからロヌドした埌に、フィルタリング、゜ヌト、デヌタ凊理のロゞックを実装したす。
Block.phpモデルコヌド

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Block.php
  <?php class IGN_Siteblocks_Model_Block extends Mage_Core_Model_Abstract { public function _construct() { parent::_construct(); $this->_init('siteblocks/block'); //      config.xml  } } 


Mage_Core_Model_Abstractから継承されたモデル。 リ゜ヌスモデルをModel / Resourceフォルダヌに保存したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/リ゜ヌス/ Block.php
  <?php class IGN_Siteblocks_Model_Resource_Block extends Mage_Core_Model_Resource_Db_Abstract { public function _construct() { $this->_init('siteblocks/block','block_id'); //block_id   PRIMARY KEY  ,   entity_id } } 


アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/リ゜ヌス/ブロック/ Collection.php
  <?php class IGN_Siteblocks_Model_Resource_Block_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract { public function _construct() { parent::_construct(); $this->_init('siteblocks/block'); } } 


クラスは空ですが、すでに必芁な最小限の継承機胜を実装しおいたす。
必芁に応じおそれらにコヌドを远加したす。 さらにモデルを远加する堎合は、テヌブルにもう1぀のモデルバむンドず3぀の新しいファむルを远加したす。 テヌブルに関連付けられおいない任意の数のモデルを远加しお䜕らかの機胜を実装するためだけに、新しいファむルを远加するだけで、 Mage_Core_Model_Abstractから継承する必芁はありたせん。

モデルのテヌブルを䜜成するむンストヌルスクリプトを䜜成するこずを忘れないでください。

app / code / local / IGN / Siteblocks / sql / siteblocks_setup / install-1.0.0.sql
  <?php /** @var Mage_Core_Model_Resource_Setup $installer */ $installer = $this; $installer->startSetup(); $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->getConnection()->createTable($table); //  $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 ; "); $installer->endSetup(); 


重芁な瞬間

むンストヌルスクリプトがただないずきに、モゞュヌルがむンストヌルされた状態で管理パネルに移動しようずした堎合。 ほずんどの堎合、むンストヌルスクリプトは二床ず実行されたせん。 この堎合、ストアデヌタベヌスのcore_resourceテヌブルからsiteblocks_setup゚ントリを芋぀けお削陀する必芁がありたす。

モゞュヌルバヌゞョンをアップグレヌドする堎合。 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'); 




コントロヌラヌずルヌティング


ビデオMagentoのコントロヌラヌずルヌティング。


レッスンで䜜成されたIGN_Siteblocks-3.zipモゞュヌルの構造

MVCパタヌンによるず、コントロヌラヌは芁求の凊理を担圓したす。 HTTPリク゚ストの圢匏で、いわゆる入力信号を受け取りたす。 リンクをたどりたした-察応するコントロヌラヌが機胜したした。

コントロヌラヌを䜜成する前に、 config.xmlでルヌティングを構成したす 。 フロント゚ンドず管理郚分のルヌティングは個別に構成されたす。 そこで、 フロント゚ンドず管理セクションにルヌタヌを远加したす。

config.xmlの圢匏は次のずおりです。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
  <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <models> <siteblocks> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Resource</class> <entities> <block> <table>ign_siteblock</table> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> </global> <frontend> <routers> <siteblocks> <use>standard</use> <args> <module>IGN_Siteblocks</module> <frontName>siteblocks</frontName><!--  ,      --> </args> </siteblocks> </routers> </frontend> <admin> <routers> <adminhtml> <args> <modules> <siteblocks after="Mage_Adminhtml">IGN_Siteblocks_Adminhtml</siteblocks> </modules> </args> </adminhtml> </routers> </admin> <default> </default> </config> 


これで、モゞュヌルのcontrollersフォルダヌにコントロヌラヌを䜜成できたす。 フロント゚ンド郚分のコントロヌラヌクラスは、 Mage_Core_Controller_Front_Actionクラスを継承する必芁がありたす。

テストコントロヌラヌTestController.phpを䜜成する

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ TestController.php
 <?php class IGN_Siteblocks_TestController extends Mage_Core_Controller_Front_Action { public function mytestAction() { die('test'); } } 


ここでexample.com/siteblocks/test/mytestのようなURLに移動したす 。 「テスト」ずいう癜い画面が衚瀺されたす。 これが発生しなかった堎合、ある段階で゚ラヌが発生したした。

コヌドを再確認し、ログを読んでください。 URLはルヌタヌ サむトブロック /コントロヌラヌ テストコントロヌラヌ/アクション mytestアクションで構成されたす

GETパラメヌタヌは2぀の方法で送信できたす。


管理コントロヌラヌは、controllers / Adminhtmlフォルダヌに䜜成されたす。 フロント゚ンド郚分のコントロヌラヌクラスは、 Mage_Adminhtml_Controller_Actionクラスを継承する必芁がありたす。

テストコントロヌラヌTestController.phpを䜜成したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / TestController.php
 <?php class IGN_Siteblocks_Adminhtml_TestController extends Mage_Adminhtml_Controller_Action { public function mytestAction() { die('admin'); } } 


URL example.com/admin/test/mytestからアクセスできたす-adminは管理パネルぞの道です。

そしお、ここには埮劙な違いがありたす。そのようなURLはすでに別のモゞュヌルによっお占有されおいる可胜性がありたす。 2぀の解決策がありたすコントロヌラヌの名前を競合しない既知の名前IgntestController.phpなどに倉曎するか、コントロヌラヌをサブフォルダヌに入れたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml /サむトブロック/TestController.php
 <?php class IGN_Siteblocks_Adminhtml_Siteblocks_TestController extends Mage_Adminhtml_Controller_Action { public function mytestAction() { die('admin'); } } 


URLは、 example.com / admin / siteblocks_test / mytestの圢匏を取りたす。


ヘルパヌ


ビデオMagentoのヘルパヌ


レッスンで䜜成されたIGN_Siteblocks-4.zipモゞュヌルの構造

Magentoのヘルパヌクラスは、远加のクラスずしお䜿甚されたす。 モデル、ブロック、コントロヌラヌの機胜に適合しないサヌドパヌティのロゞックを実装する必芁がありたす。 ただし、モゞュヌルには少なくずも1぀のData.phpヘルパヌクラスが必芁です。

このヘルパヌは、デフォルトでテキストラベル、メニュヌ項目などおよびその他のロゞックを翻蚳するために䜿甚されたす。

ヘルパヌでは、蚭定から蚭定を読み取るためのメ゜ッドを宣蚀するこずをお勧めしたす。 ヘルパヌは、 Mage_Core_Helper_Abstractクラスを継承する必芁がありたす。

アプリ/コヌド/ loca / IGN / Siteblocks /ヘルパヌ/ Data.php
 <?php class IGN_Siteblocks_Helper_Data extends Mage_Core_Helper_Abstract { } 


ヘルパヌ内のテキストを翻蚳する__メ゜ッドがあり、そのアプリケヌションは次のようになりたす。

 echo Mage::helper('siteblocks')->__('Some text') 

config.xmlで翻蚳ファむルを宣蚀したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
 <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <models> <siteblocks> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Resource</class> <entities> <block> <table>ign_siteblock</table> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> <helpers> <siteblocks> <class>IGN_Siteblocks_Helper</class> </siteblocks> </helpers> </global> <frontend> <routers> <siteblocks> <use>standard</use> <args> <module>IGN_Siteblocks</module> <frontName>siteblocks</frontName> </args> </siteblocks> </routers> <translate> <modules> <IGN_Siteblocks> <files> <default>IGN_Siteblocks.csv</default> </files> </IGN_Siteblocks> </modules> </translate> </frontend> <admin> <routers> <adminhtml> <args> <modules> <siteblocks after="Mage_Adminhtml">IGN_Siteblocks_Adminhtml</siteblocks> </modules> </args> </adminhtml> </routers> </admin> <defalut> </defalut> </config> 


そしお、app / locale / en_US /フォルダヌにIGN_Siteblocks.csvファむルを䜜成したす。 フォヌムの内容 「䞀郚のテキスト」、「䞀郚のテキスト」 。

独自のヘルパヌを䜿甚しおテキストを衚瀺しようずしたすが、この堎合、モゞュヌルの異なる蚀語ぞのロヌカラむズが簡玠化されたす。

翻蚳ファむルを適切なロケヌルにコピヌし、2番目の列を翻蚳するだけで十分です。コヌドを詳しく調べる必芁はありたせん。


管理パネルのモゞュヌル構成


ビデオMagento管理パネルのモゞュヌル構成


レッスンで䜜成されたIGN_Siteblocks-5.zipモゞュヌルの構造

モゞュヌルに柔軟性を持たせるために、モゞュヌル蚭定を含むペヌゞを䜜成したす。 これは、玔粋にxmlファむルを通じお行われたす。 2぀のファむルを䜜成する必芁がありたす。

system.xml-フィヌルドが远加される堎所
adminhtml.xml-セクションずアクセス暩が瀺される堎所

たた、config.xmlファむルのデフォルトセクションで暙準蚭定を指定できたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
 <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <models> <siteblocks> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Resource</class> <entities> <block> <table>ign_siteblock</table> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> <helpers> <siteblocks> <class>IGN_Siteblocks_Helper</class> </siteblocks> </helpers> </global> <frontend> <routers> <siteblocks> <use>standard</use> <args> <module>IGN_Siteblocks</module> <frontName>siteblocks</frontName> </args> </siteblocks> </routers> <translate> <modules> <IGN_Siteblocks> <files> <default>IGN_Siteblocks.csv</default> </files> </IGN_Siteblocks> </modules> </translate> </frontend> <admin> <routers> <adminhtml> <args> <modules> <siteblocks after="Mage_Adminhtml">IGN_Siteblocks_Adminhtml</siteblocks> </modules> </args> </adminhtml> </routers> </admin> <defalut> <siteblocks> <settings> <enabled>1</enabled> <block_count>10</block_count> </settings> </siteblocks> </defalut> </config> 


アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / adminhtml.xml
 <?xml version="1.0"?> <config> <acl> <resources> <admin> <children> <system> <children> <config> <children> <siteblocks translate="title" module="siteblocks"> <title>Siteblocks</title> </siteblocks> </children> </config> </children> </system> </children> </admin> </resources> </acl> </config> 


アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / system.xml
 <?xml version="1.0"?> <config> <tabs> <ign translate="label" module="siteblocks"> <!--      --> <label>IGN</label> <sort_order>2</sort_order> </ign> </tabs> <sections> <siteblocks module="siteblocks" translate="label"> <label>Siteblocks</label> <tab>ign</tab> <!--       --> <frontend>text</frontend> <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> <groups> <settings module="siteblocks" translate="label"> <label>Settings</label> <expanded>1</expanded> <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> <enabled translate="label comment" module="siteblocks"> <label>Enabled</label> <frontend_type>select</frontend_type> <!--       lib/Varien/Data/Form/Element --> <source_model>siteblocks/source_status</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> <comment>Is module enabled</comment> </enabled> <blocks_count> <label>Blocks on page</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>1</show_in_store> <depends><enabled>1</enabled></depends> <!--         --> </blocks_count> <raw_text> <label>Raw text</label> <frontend_type>textarea</frontend_type> <sort_order>3</sort_order> <show_in_default>1</show_in_default> <show_in_Website>1</show_in_Website> <show_in_store>1</show_in_store> <depends><enabled>1</enabled></depends> </raw_text> </fields> </settings> </groups> </siteblocks> </sections> </config> 


蚭定では、オプションを含むドロップダりンが衚瀺され、これらのオプションの独自のモデルが䜿甚されたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/゜ヌス/ Status.php
 <?php class IGN_Siteblocks_Model_Source_Status { const ENABLED = '1'; const DISABLED = '0'; /** * Options getter * * @return array */ public function toOptionArray() { return array( array('value' => 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'), ); } 




フロント゚ンドブロック。レむアりト。テンプレヌト


ビデオフロント゚ンドブロック。レむアりト。Magentoテンプレヌト


レッスンで䜜成されたIGN_Siteblocks-6.zip モゞュヌルの構造は

、ストアのフロント゚ンド郚分に関する情報を衚瀺しようずしおいたす。たた、タむトルから掚枬するのは難しくないため、ブロック、レむアりト、テンプレヌトの3皮類のファむルを䜿甚したす。

ブロックは、情報の準備ず衚瀺を担圓するクラスです。ブロックはテンプレヌトの衚瀺に䜿甚されたすが、垞にではありたせん。テンプレヌトが䜿甚される堎合、それは単にfetchViewメ゜ッドに含たれ



たす。したがっお、$ thisを介しおテンプレヌトからブロックにアクセスしたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/List.php
 <?php class IGN_Siteblocks_Block_List extends Mage_Core_Block_Template { public function getBlocks() { //return Mage::getResourceModel('siteblocks/block_collection'); return Mage::getModel('siteblocks/block')->getCollection() ->addFieldToFilter('block_status',array('eq'=>IGN_Siteblocks_Model_Source_Status::ENABLED)); } } 


ブロックはMage_Core_Block_Templateクラスを継承したす。ただし、ナニットの出力内容によっお異なりたす。そのため、たずえば、補品をリストするずきは、Mage_Catalog_Block_Product_Listブロックから継承するこずをお勧めしたす。レむアりトは、ペヌゞの構造、ペヌゞに衚瀺する芁玠ずその順序を構築するために䜿甚されたす。

レむアりトファむルを䜜成したす。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/レむアりト/ siteblocks.xml
 <?xml version="1.0"?> <layout version="1.0.0"> <siteblocks_index_index> <!--   URL example.com/siteblocks/index/index --> <reference name="head"> <action method="setTitle"> <title>My Siteblocks</title> </action> </reference> <reference name="content"> <block name="siteblocks.list" as="siteblocks" type="siteblocks/list" template="siteblocks/list.phtml"/> </reference> </siteblocks_index_index> <catalog_category_default> <!--    handle            --> <reference name="left"> <block name="siteblocks.list" as="siteblocks" type="siteblocks/list" template="siteblocks/list.phtml"/> </reference> <reference name="right"> <block name="siteblocks.list" as="siteblocks" type="siteblocks/list" template="siteblocks/list.phtml"/> </reference> </catalog_category_default> <catalog_product_view> <!--        --> <reference name="product.info.extrahint"> <!--        catalog.xml          --> <block name="siteblocks.list" before="-" as="siteblocks" type="siteblocks/list" template="siteblocks/list.phtml"/> </reference> </catalog_product_view> </layout> 


レむアりトでは、js、cssファむルをヘッドに远加できたす。興味のあるペヌゞでブロックを远加たたは削陀できたす。レむアりトのテヌマは非垞に広範囲であり、䞊蚘から、サむトの耇数の堎所にブロックを远加する最小限のシンプルなレむアりトを提䟛したした。

別の方法モックアップなしで、コントロヌラヌに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'; } 

テンプレヌトを䜜成したす。

アプリ/デザむン/ベヌス/デフォルト/テンプレヌト/サむトブロック/ list.phtml
 <?php foreach($this->getBlocks() as $block):?> <div class="siteblock"> <div class="block-title"><?php echo $block->getTitle()?></div> <div class="block-content"><?php echo $block->getContent()?></div> </div> <?php endforeach;?> 


コヌドでわかるように、getBlocksブロックメ゜ッドを呌び出しお、印刷するレコヌドのコレクションを返したす。TestControllerの名前を倉曎するか、新しいものを䜜成したす。むンデックスコントロヌラヌ

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ IndexController.php
 <?php class IGN_Siteblocks_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $this->loadLayout(); #  $this->renderLayout(); # html } } 


出力が衚瀺されるURLは、example.com / siteblocks / index / indexたたはexample.com/siteblocksです。index / indexは省略できたす。

レむアりト内のハンドルは、siteblocks_index_indexを䜿甚したす。レコヌドの出力を芋るには、それらをデヌタベヌスに盎接远加するか、線集フォヌムの開発の次のステップに進む必芁がありたす。


管理むンタヌフェヌス。グリッド。線集フォヌム。


ビデオ管理むンタヌフェむス。グリッド。Magento線集フォヌム


レッスンで䜜成されたIGN_Siteblocks-7.zip モゞュヌルの構造

管理むンタヌフェヌスの䜜成プロセスは、いく぀かの段階で構成されおいたす。


メニュヌにアむテムを远加したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / adminhtml.xml
 <?xml version="1.0"?> <config> <acl> <resources> <admin> <children> <system> <children> <config> <children> <siteblocks translate="title" module="siteblocks"> <title>Siteblocks</title> </siteblocks> </children> </config> </children> </system> <cms> <children> <siteblocks translate="title" module="siteblocks"> <title>Siteblocks</title> </siteblocks> </children> </cms> </children> </admin> </resources> </acl> <menu> <cms> <!--        --> <children> <siteblocks translate="title" module="siteblocks"> <title>Siteblocks</title> <action>adminhtml/siteblocks</action> <!--       , index      --> <sort_order>20</sort_order> </siteblocks> </children> </cms> </menu> </config> 


正しいセクションコヌドcmsの䟋は、暙準のMagentoモゞュヌルのadminhtml.xmlファむルにありたす。そこで、独自のセクションを䜜成する方法を参照しおください。aclブロックの情報を耇補するこずを忘れないでください。

コントロヌラヌず1぀のアクションを䜜成しお開始したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } } 


管理パネルのレむアりトを䜜成できたすが、必芁なブロックをコントロヌラヌに盎接远加できたす。ここで、コンテンツにペヌゞを远加したした。むンデックスアクションは、グリッドレコヌドを含むペヌゞを衚瀺したす。

これで、ブロックの䜜成に進むこずができたす。

アプリ/コヌド/ロヌカル/ IGN / Siteblocks / Block / Adminhtml / Siteblocks.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks extends Mage_Adminhtml_Block_Widget_Grid_Container { public function __construct() { $this->_controller = 'adminhtml_siteblocks'; $this->_blockGroup = 'siteblocks'; $this->_headerText = Mage::helper('siteblocks')->__('Siteblocks'); $this->_addButtonLabel = Mage::helper('siteblocks')->__('Add New Block'); parent::__construct(); } } 


このようなプロパティ倀を登録した理由は、Mage_Adminhtml_Block_Widget_Grid_Containerクラスのメ゜ッドで確認



できたす。こうしお、グリッドブロックのブロックタむプが圢成されたす。

アプリ/コヌド/ロヌカル/ IGN / Siteblocks / Block / Adminhtml / Siteblocks / Grid.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Grid extends Mage_Adminhtml_Block_Widget_Grid { public function __construct() { parent::__construct(); $this->setId('cmsBlockGrid'); $this->setDefaultSort('block_identifier'); $this->setDefaultDir('ASC'); } protected function _prepareCollection() { $collection = Mage::getModel('siteblocks/block')->getCollection(); /* @var $collection Mage_Cms_Model_Mysql4_Block_Collection */ $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { $this->addColumn('title', array( 'header' => Mage::helper('siteblocks')->__('Title'), 'align' => 'left', 'index' => 'title', )); $this->addColumn('block_status', array( 'header' => Mage::helper('cms')->__('Status'), 'align' => 'left', 'type' => 'options', 'options' => Mage::getModel('siteblocks/source_status')->toArray(), 'index' => 'block_status' )); $this->addColumn('created_at', array( 'header' => Mage::helper('siteblocks')->__('Created At'), 'index' => 'created_at', 'type' => 'date', )); return parent::_prepareColumns(); } protected function _prepareMassaction() { $this->setMassactionIdField('block_id'); $this->getMassactionBlock()->setIdFieldName('block_id'); $this->getMassactionBlock() ->addItem('delete', array( 'label' => Mage::helper('siteblocks')->__('Delete'), 'url' => $this->getUrl('*/*/massDelete'), 'confirm' => Mage::helper('siteblocks')->__('Are you sure?') ) ) ->addItem('status', array( 'label' => Mage::helper('siteblocks')->__('Update status'), 'url' => $this->getUrl('*/*/massStatus'), 'additional' => array('block_status'=> array( 'name' => 'block_status', 'type' => 'select', 'class' => 'required-entry', 'label' => Mage::helper('siteblocks')->__('Status'), 'values' => Mage::getModel('siteblocks/source_status')->toOptionArray() ) ) ) ); return $this; } /** * Row click url * * @return string */ public function getRowUrl($row) { return $this->getUrl('*/*/edit', array('block_id' => $row->getId())); } } 


この堎合のグリッドブロックはこの圢匏を取りたす。原則ずしお、メ゜ッドずプロパティの名前により、列の远加方法、線集ペヌゞでのURLの圢成方法、レコヌドのコレクションがテヌブルでの出力甚に準備される方法を理解できたす。

デフォルトの列タむプずその構築の原則は、app / code / core / Mage / Adminhtml / Block / Widget / Grid / Column / Renderer / folderにあるこずに泚意しおください。

線集ペヌゞも、コンテナブロックずフォヌムブロックの2぀のブロックで構成されたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/ Edit.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit extends Mage_Adminhtml_Block_Widget_Form_Container { public function __construct() { $this->_objectId = 'block_id'; $this->_controller = 'adminhtml_siteblocks'; $this->_blockGroup = 'siteblocks'; parent::__construct(); $this->_updateButton('save', 'label', Mage::helper('siteblocks')->__('Save Block')); $this->_updateButton('delete', 'label', Mage::helper('siteblocks')->__('Delete Block')); $this->_addButton('saveandcontinue', array( 'label' => Mage::helper('adminhtml')->__('Save and Continue Edit'), 'onclick' => 'saveAndContinueEdit()', 'class' => 'save', ), -100); $this->_formScripts[] = " function saveAndContinueEdit(){ editForm.submit($('edit_form').action+'back/edit/'); } "; } /** * Get edit form container header text * * @return string */ public function getHeaderText() { if (Mage::registry('siteblocks_block')->getId()) { return Mage::helper('siteblocks')->__("Edit Block '%s'", $this->escapeHtml(Mage::registry('siteblocks_block')->getTitle())); } else { return Mage::helper('siteblocks')->__('New Block'); } } } 


そしお、ここでプロパティの倀は芪クラスのメ゜ッドに合わせお調敎され、ブロックタむプsiteblocks / adminhtml_siteblocks_edit_formフォヌム

クラスを取埗したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Form.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('block_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form( array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save',array('block_id'=>$this->getRequest()->getParam('block_id'))), 'method' => 'post' ) ); $form->setHtmlIdPrefix('block_'); $fieldset = $form->addFieldset('base_fieldset', array('legend'=>Mage::helper('siteblocks')->__('General Information'), 'class' => 'fieldset-wide')); if ($model->getBlockId()) { $fieldset->addField('block_id', 'hidden', array( 'name' => 'block_id', )); } $fieldset->addField('title', 'text', array( 'name' => 'title', 'label' => Mage::helper('siteblocks')->__('Block Title'), 'title' => Mage::helper('siteblocks')->__('Block Title'), 'required' => true, )); $fieldset->addField('block_status', 'select', array( 'label' => Mage::helper('siteblocks')->__('Status'), 'title' => Mage::helper('siteblocks')->__('Status'), 'name' => 'block_status', 'required' => true, 'options' => Mage::getModel('siteblocks/source_status')->toArray(), )); $fieldset->addField('content', 'textarea', array( 'name' => 'content', 'label' => Mage::helper('siteblocks')->__('Content'), 'title' => Mage::helper('siteblocks')->__('Content'), 'style' => 'height:36em', 'required' => true, )); $form->setValues($model->getData()); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } } 


フィヌルドは簡単な方法で远加され、オプションの明確なセットがあり、暙準フィヌルドのタむプはlib / Varien / Data / Form / Element /フォルダヌにありたす。ここで、なぜサむトブロックモデルのむンスタンスがあるのか​​を芋おみたしょう。$ model = Mage :: registry 'siteblocks_block'; 残りのアクションをコントロヌラヌに远加したす。レコヌドを線集、保存、削陀するアクションが必芁です。たた、ナヌザヌがテヌブル内の耇数の行を遞択し、これらのマヌクされた゚ントリの削陀ボタンをクリックできる堎合、䞀括削陀およびステヌタス倉曎のアクションを远加したす。

コントロヌラヌの圢匏は次のずおりです。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = $this->getRequest()->getParam('block_id'); Mage::register('siteblocks_block',Mage::getModel('siteblocks/block')->load($id)); $blockObject = (array)Mage::getSingleton('adminhtml/session')->getBlockObject(true); if(count($blockObject)) { Mage::registry('siteblocks_block')->setData($blockObject); } $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit')); $this->renderLayout(); } public function saveAction() { try { $id = $this->getRequest()->getParam('block_id'); $block = Mage::getModel('siteblocks/block')->load($id); /*$block ->setTitle($this->getRequest()->getParam('title')) ->setContent($this->getRequest()->getParam('content')) ->setBlockStatus($this->getRequest()->getParam('block_status')) ->save();*/ $block ->setData($this->getRequest()->getParams()) ->setCreatedAt(Mage::app()->getLocale()->date()) ->save(); if(!$block->getId()) { Mage::getSingleton('adminhtml/session')->addError('Cannot save the block'); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setBlockObject($block->getData()); return $this->_redirect('*/*/edit',array('block_id'=>$this->getRequest()->getParam('block_id'))); } Mage::getSingleton('adminhtml/session')->addSuccess('Block was saved successfully!'); $this->_redirect('*/*/'.$this->getRequest()->getParam('back','index'),array('block_id'=>$block->getId())); } public function deleteAction() { $block = Mage::getModel('siteblocks/block') ->setId($this->getRequest()->getParam('block_id')) ->delete(); if($block->getId()) { Mage::getSingleton('adminhtml/session')->addSuccess('Block was deleted successfully!'); } $this->_redirect('*/*/'); } public function massStatusAction() { $statuses = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$statuses['massaction'])); foreach($blocks as $block) { $block->setBlockStatus($statuses['block_status'])->save(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were updated!'); return $this->_redirect('*/*/'); } public function massDeleteAction() { $blocks = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$blocks['massaction'])); foreach($blocks as $block) { $block->delete(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were deleted!'); return $this->_redirect('*/*/'); } } 


これで、モゞュヌルでレコヌドを線集し、フロント゚ンド郚分に衚瀺できたす。


むベントずリスナヌ


ビデオMagentoのむベントずリスナヌ


レッスンで䜜成されたIGN_Siteblocks-8.zip モゞュヌルの構造

Magentoでむベントリスナヌテンプレヌトを䜿甚できたす。モゞュヌルでサむトの特定の瞬間をキャッチできるのは䜕ですか。ダむナミズム、柔軟性を远加し、自動化を匷化したす。

たた、Magentoには倚くの暙準むベントが実装されおいたす。 「Mage :: dispatchEvent」ずいうテキストのMagentoファむルを怜玢したす。たたは、リンクをご芧ください。これは明瀺的なむベントによるもので、各モデル、各ブロックたたはコントロヌラヌアクションで発生するむベントがただありたす。原則ずしお、これは事前および事埌むベントです。

model_save_before、model_save_after、controller_action_predispatch、controller_action_postdispatch、core_block_abstract_to_html_before、core_block_abstract_to_html_after

さらに、クラスのevent_prefixたたはコントロヌラヌのルヌト名を䜿甚するむベントsiteblocks_save_before、controller_action_predispatch_siteblocks ...

さたざたなバリ゚ヌションがあり、このシステムのおかげで、目的のむベントを簡単に「キャッチ」できたす。

コヌド内の任意の堎所でむベントを盎接䜜成できたす。

 Mage::dispatchEvent('some_event_name',array('myparam' => $someVar)); 

リスナヌはconfig.xmlで宣蚀されおいたす。たた、3぀のオプションがありたすglobal、adminhtml、frontend。したがっお、これはリスナヌに働きかけたいだけの分離です。蚭定は次の圢匏を取りたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
 <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <blocks> <siteblocks> <class>IGN_Siteblocks_Block</class> </siteblocks> </blocks> <models> <siteblocks> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Model_Resource</class> <entities> <block> <table>ign_siteblock</table> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> <helpers> <siteblocks> <class>IGN_Siteblocks_Helper</class> </siteblocks> </helpers> </global> <frontend> <events> <checkout_cart_product_add_after> <!--      --> <observers> <siteblocks> <class>siteblocks/observer</class> <method>checkout_cart_product_add_after</method> <!--         --> <type>model</type> </siteblocks> </observers> </checkout_cart_product_add_after> </events> <layout> <updates> <siteblocks module="siteblocks"> <file>siteblocks.xml</file> </siteblocks> </updates> </layout> <routers> <siteblocks> <use>standard</use> <args> <module>IGN_Siteblocks</module> <frontName>siteblocks</frontName> </args> </siteblocks> </routers> <translate> <modules> <IGN_Siteblocks> <files> <default>IGN_Siteblocks.csv</default> </files> </IGN_Siteblocks> </modules> </translate> </frontend> <admin> <routers> <adminhtml> <args> <modules> <siteblocks after="Mage_Adminhtml">IGN_Siteblocks_Adminhtml</siteblocks> </modules> </args> </adminhtml> </routers> </admin> <default> <siteblocks> <settings> <enabled>1</enabled> <block_count>10</block_count> </settings> </siteblocks> </default> </config> 


バスケットに補品を远加するむベントにリスナヌを1人远加したした。次に、リスナヌクラスを䜜成する必芁がありたす。このクラスがなくおも、モデルにロゞックを远加できたす。しかし、これは悪い圢です。したがっお、Observer.php

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Observer.php
 <?php class IGN_Siteblocks_Model_Observer { /** * @param $bserver Varien_Event_Observer */ //   camelCase  .  :   =   //     , : checkoutCartProductAddAfter public function checkout_cart_product_add_after($observer) { var_dump($observer->getEvent()->getData('quote_item')->getData());die; } } 


このメ゜ッドでは、必芁なすべおの操䜜を実行できたす。次に、バスケットからアむテムの内容を印刷したす。埌でこのコヌドをコメントアりトしたす。そうしないず、バスケットに補品を远加できたせん。


Cronおよびスケゞュヌルされたタスク


ビデオMagentoのCronおよびスケゞュヌルされたタスク


レッスンで䜜成されたIGN_Siteblocks-9.zip モゞュヌルの構造は、モゞュヌル

の䜜業プロセスずストアの䜜業を自動化する際のもう1぀の匕数です。スケゞュヌルされたタスクを䜜成するこずもできたす。

たず第䞀に、Magentoクラりンの起動を蚭定する必芁があり、既に起動されおいるMagentoファむルは、どのタスクを実行するかによっお自動的に配垃されたす。コン゜ヌルでMagento cronをセットアップしたす。

 crontab -e * * * * * php /var/www/magento.dev/cron.php 

ここでの詳现情報help.ubuntu.ru/wiki/cron。たたは、蚭定はできたせんが、必芁なずきにクラりンを実行したす。example.com/ cron.phpのようなリンクをクリックするだけ

で、config.xmlのタスクを別のcrontabブロックで宣蚀したす。曎新されたファむルビュヌ

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / config.xml
 <?xml version="1.0" ?> <config> <modules> <IGN_Siteblocks> <version>1.0.0</version> </IGN_Siteblocks> </modules> <global> <blocks> <siteblocks> <class>IGN_Siteblocks_Block</class> </siteblocks> </blocks> <models> <siteblocks> <class>IGN_Siteblocks_Model</class> <resourceModel>siteblocks_resource</resourceModel> </siteblocks> <siteblocks_resource> <class>IGN_Siteblocks_Model_Resource</class> <entities> <block> <table>ign_siteblock</table> </block> </entities> </siteblocks_resource> </models> <resources> <siteblocks_setup> <setup> <module>IGN_Siteblocks</module> </setup> </siteblocks_setup> </resources> <helpers> <siteblocks> <class>IGN_Siteblocks_Helper</class> </siteblocks> </helpers> </global> <frontend> <events> <controller_action_predispatch> </controller_action_predispatch> <checkout_cart_product_add_after> <observers> <siteblocks> <class>siteblocks/observer</class> <method>checkout_cart_product_add_after</method> <type>model</type> </siteblocks> </observers> </checkout_cart_product_add_after> </events> <layout> <updates> <siteblocks module="siteblocks"> <file>siteblocks.xml</file> </siteblocks> </updates> </layout> <routers> <siteblocks> <use>standard</use> <args> <module>IGN_Siteblocks</module> <frontName>siteblocks</frontName> </args> </siteblocks> </routers> <translate> <modules> <IGN_Siteblocks> <files> <default>IGN_Siteblocks.csv</default> </files> </IGN_Siteblocks> </modules> </translate> </frontend> <admin> <routers> <adminhtml> <args> <modules> <siteblocks after="Mage_Adminhtml">IGN_Siteblocks_Adminhtml</siteblocks> </modules> </args> </adminhtml> </routers> </admin> <default> <siteblocks> <settings> <enabled>1</enabled> <block_count>10</block_count> </settings> </siteblocks> </default> <crontab> <jobs> <siteblocks_clear_cache> <!--   --> <schedule> <cron_expr>*/10 * * * *</cron_expr> <!--  10  --> </schedule> <run> <model>siteblocks/cron::siteblocks_clear_cache</model> <!--   ,     --> </run> </siteblocks_clear_cache> </jobs> </crontab> </config> 


タスクには、個別のファむルCron.phpを䜿甚したす

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Cron.php
 <?php class IGN_Siteblocks_Model_Cron { public function siteblocks_clear_cache() { //do something here Mage::app()->cleanCache(array('siteblocks_blocks')); } } 




管理パネルでレンダラヌを䜿甚する


ビデオMagento管理領域でのレンダリングの䜿甚


レッスンで䜜成されたIGN_Siteblocks-10.zip モゞュヌルの構造

倚くの堎合、暙準の芁玠では目的の機胜を実装するには䞍十分です。したがっお、目的の芁玠のレンダラヌを䜜成するこずができ、このプロセスに倚くの時間は必芁ありたせん。

フォヌム芁玠のレンダラヌを䜜成するこずを怜蚎しおください。管理フォヌムがありたす

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Form.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('block_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form( array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save',array('block_id'=>$this->getRequest()->getParam('block_id'))), 'method' => 'post', 'enctype' => 'multipart/form-data' ) ); $form->setHtmlIdPrefix('block_'); $fieldset = $form->addFieldset('base_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('General Information'), 'class' => 'fieldset-wide') ); if ($model->getBlockId()) { $fieldset->addField('block_id', 'hidden', array( 'name' => 'block_id', )); } $fieldset->addField('title', 'text', array( 'name' => 'title', 'label' => Mage::helper('siteblocks')->__('Block Title'), 'title' => Mage::helper('siteblocks')->__('Block Title'), 'required' => true, )); #1           #       .../Block/Adminhtml/Siteblocks/Edit/Renderer/Myimage.php $fieldset->addType('myimage','IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Renderer_Myimage'); #       -,     lib/Varien/Data/Form/Element/Myimage.php $fieldset->addField('image', 'myimage', array( 'name' => 'image', 'label' => Mage::helper('siteblocks')->__('Image'), 'title' => Mage::helper('siteblocks')->__('Image'), 'required' => true, )); $fieldset->addField('block_status', 'select', array( 'label' => Mage::helper('siteblocks')->__('Status'), 'title' => Mage::helper('siteblocks')->__('Status'), 'name' => 'block_status', 'required' => true, 'options' => Mage::getModel('siteblocks/source_status')->toArray(), )); $fieldset->addField('content', 'textarea', array( 'name' => 'content', 'label' => Mage::helper('siteblocks')->__('Content'), 'title' => Mage::helper('siteblocks')->__('Content'), 'style' => 'height:36em', 'required' => true, )); $form->setValues($model->getData()); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } } 


フォヌムにはレンダラヌを䜜成するための2぀のオプションがあり、任意のオプションを䜿甚できたすが、lib / Varien / Data / Form / Element /フォルダヌにファむルを䜜成するオプションに感銘を受けたした。 なぜならこの堎合、䟋に埓っお、<frontend_type> myimage </ frontend_type>を穏やかに瀺すsystem.xmlのフィヌルドで同じレンダラヌを䜿甚できたす。

ファむルの内容

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/レンダラヌ/ Myimage.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Renderer_Myimage extends Varien_Data_Form_Element_Abstract { /** * Constructor * * @param array $data */ public function __construct($data) { parent::__construct($data); $this->setType('file'); } /** * Return element html code * * @return string */ public function getElementHtml() { $html = ''; if ((string)$this->getValue()) { $url = $this->_getUrl(); if( !preg_match("/^http\:\/\/|https\:\/\//", $url) ) { $url = Mage::getBaseUrl('media') . 'siteblocks' .DS.$url; } $html = '<a href="' . $url . '"' . ' onclick="imagePreview(\'' . $this->getHtmlId() . '_image\'); return false;">' . '<img src="' . $url . '" id="' . $this->getHtmlId() . '_image" title="' . $this->getValue() . '"' . ' alt="' . $this->getValue() . '" height="100" width="100" class="small-image-preview v-middle" />' . '</a> '; /*$additional = Mage::app()->getLayout()->createBlock('Mage_Adminhtml_Block_Template'); $additional->setTemplate('siteblocks/image.phtml') ->setImageUrl($url); $html = $additional->toHtml();*/ #       ,   html    ,      } $this->setClass('input-file'); $html .= parent::getElementHtml(); return $html; } /** * Return html code of hidden element * * @return string */ protected function _getHiddenInput() { return '<input type="hidden" name="' . parent::getName() . '[value]" value="' . $this->getValue() . '" />'; } /** * Get image preview url * * @return string */ protected function _getUrl() { return $this->getValue(); } /** * Return name * * @return string */ public function getName() { return $this->getData('name'); } } 



lib / Varien / Data / Form / Element / Myimage.php
 <?php class Varien_Data_Form_Element_Myimage extends Varien_Data_Form_Element_Abstract { /** * Constructor * * @param array $data */ public function __construct($data) { parent::__construct($data); $this->setType('file'); } /** * Return element html code * * @return string */ public function getElementHtml() { $html = ''; if ((string)$this->getValue()) { $url = $this->_getUrl(); if( !preg_match("/^http\:\/\/|https\:\/\//", $url) ) { $url = Mage::getBaseUrl('media') . 'siteblocks' .DS.$url; } $html = '<a href="' . $url . '"' . ' onclick="imagePreview(\'' . $this->getHtmlId() . '_image\'); return false;">' . '<img src="' . $url . '" id="' . $this->getHtmlId() . '_image" title="' . $this->getValue() . '"' . ' alt="' . $this->getValue() . '" height="150" width="150" class="small-image-preview v-middle" />' . '</a> '; /*$additional = Mage::app()->getLayout()->createBlock('Mage_Adminhtml_Block_Template'); $additional->setTemplate('siteblocks/image.phtml') ->setImageUrl($url); $html = $additional->toHtml();*/ #       ,   html    ,      } $this->setClass('input-file'); $html .= parent::getElementHtml(); return $html; } /** * Return html code of hidden element * * @return string */ protected function _getHiddenInput() { return '<input type="hidden" name="' . parent::getName() . '[value]" value="' . $this->getValue() . '" />'; } /** * Get image preview url * * @return string */ protected function _getUrl() { return $this->getValue(); } /** * Return name * * @return string */ public function getName() { return $this->getData('name'); } } 


これらのファむルの内容を暙準のlib / Varien / Data / Form / Element / Image.phpからコピヌし
、ニヌズに合わせおコヌドを調敎したした。

次に、Grid列のレンダラヌを䜜成したしょう。

これに加えお、モゞュヌル機胜にいく぀かの远加を行いたした。画像の読み蟌みず保存の機胜を䜜成する必芁がありたした。

アプリ/コヌド/ロヌカル/ IGN / Siteblocks / Block / Adminhtml / Siteblocks / Grid.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Grid extends Mage_Adminhtml_Block_Widget_Grid { public function __construct() { parent::__construct(); $this->setId('cmsBlockGrid'); $this->setDefaultSort('block_identifier'); $this->setDefaultDir('ASC'); } protected function _prepareCollection() { $collection = Mage::getModel('siteblocks/block')->getCollection(); /* @var $collection Mage_Cms_Model_Mysql4_Block_Collection */ $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { $this->addColumn('title', array( 'header' => Mage::helper('siteblocks')->__('Title'), 'align' => 'left', 'index' => 'title', )); $this->addColumn('image', array( 'header' => Mage::helper('siteblocks')->__('Image'), 'align' => 'left', 'index' => 'image', 'filter' => false, <!--      --> 'sortable' => false,<!--      --> 'renderer' => 'IGN_Siteblocks_Block_Adminhtml_Siteblocks_Grid_Renderer_Image', // 'renderer' => 'siteblocks/adminhtml_siteblocks_grid_renderer_image' #  )); $this->addColumn('block_status', array( 'header' => Mage::helper('cms')->__('Status'), 'align' => 'left', 'type' => 'options', 'options' => Mage::getModel('siteblocks/source_status')->toArray(), 'index' => 'block_status' )); $this->addColumn('created_at', array( 'header' => Mage::helper('siteblocks')->__('Created At'), 'index' => 'created_at', 'type' => 'date', )); return parent::_prepareColumns(); } protected function _prepareMassaction() { $this->setMassactionIdField('block_id'); $this->getMassactionBlock()->setIdFieldName('block_id'); $this->getMassactionBlock() ->addItem('delete', array( 'label' => Mage::helper('siteblocks')->__('Delete'), 'url' => $this->getUrl('*/*/massDelete'), 'confirm' => Mage::helper('siteblocks')->__('Are you sure?') ) ) ->addItem('status', array( 'label' => Mage::helper('siteblocks')->__('Update status'), 'url' => $this->getUrl('*/*/massStatus'), 'additional' => array('block_status'=> array( 'name' => 'block_status', 'type' => 'select', 'class' => 'required-entry', 'label' => Mage::helper('siteblocks')->__('Status'), 'values' => Mage::getModel('siteblocks/source_status')->toOptionArray() ) ) ) ); return $this; } /** * Row click url * * @return string */ public function getRowUrl($row) { return $this->getUrl('*/*/edit', array('block_id' => $row->getId())); } } 


アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/グリッド/レンダラヌ/ Image.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Grid_Renderer_Image extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract { public function render(Varien_Object $row) #       { if( ! $row->getImage()) { return ''; } $url = Mage::getBaseUrl('media') . 'siteblocks' .DS .$row->getImage(); $html = "<img src='$url' width='100' height='auto'>"; return $html; } } 


レンダラヌで、$ src URLを生成し、画像のhtmlコヌドを衚瀺したす。これで、衚に写真が衚瀺されたす。

画像をモゞュヌルにロヌドするには、いく぀かの远加が必芁です。

1. config.xmlのバヌゞョンを1.0.1
にアップグレヌドしたす2. upgrade-1.0.0-1.0.1.phpファむルを䜜成したす

app / code / local / IGN / Siteblocks / sql / siteblocks_setup / upgrade-1.0.0-1.0.1.php
 <?php /** @var Mage_Core_Model_Resource_Setup $installer */ $installer = $this; $installer->startSetup(); $installer->run(" ALTER TABLE `{$this->getTable('siteblocks/block')}` ADD `image` TEXT NOT NULL; "); $installer->endSetup(); 


3.コントロヌラヌで、適切なコヌドを远加したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = $this->getRequest()->getParam('block_id'); Mage::register('siteblocks_block',Mage::getModel('siteblocks/block')->load($id)); $blockObject = (array)Mage::getSingleton('adminhtml/session')->getBlockObject(true); if(count($blockObject)) { Mage::registry('siteblocks_block')->setData($blockObject); } $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit')); $this->renderLayout(); } //    protected function _uploadFile($fieldName,$model) { if( ! isset($_FILES[$fieldName])) { return false; } $file = $_FILES[$fieldName]; if(isset($file['name']) && (file_exists($file['tmp_name']))){ if($model->getId()){ unlink(Mage::getBaseDir('media').DS.$model->getData($fieldName)); } try { $path = Mage::getBaseDir('media') . DS . 'siteblocks' . DS; $uploader = new Varien_File_Uploader($file); $uploader->setAllowedExtensions(array('jpg','png','gif','jpeg')); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(false); $uploader->save($path, $file['name']); $model->setData($fieldName,$uploader->getUploadedFileName()); return true; } catch(Exception $e) { return false; } } } public function saveAction() { try { $id = $this->getRequest()->getParam('block_id'); $block = Mage::getModel('siteblocks/block')->load($id); /*$block ->setTitle($this->getRequest()->getParam('title')) ->setContent($this->getRequest()->getParam('content')) ->setBlockStatus($this->getRequest()->getParam('block_status')) ->save();*/ $block ->setData($this->getRequest()->getParams()); $this->_uploadFile('image',$block); //    $block ->setCreatedAt(Mage::app()->getLocale()->date()) ->save(); if(!$block->getId()) { Mage::getSingleton('adminhtml/session')->addError('Cannot save the block'); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setBlockObject($block->getData()); return $this->_redirect('*/*/edit',array('block_id'=>$this->getRequest()->getParam('block_id'))); } Mage::getSingleton('adminhtml/session')->addSuccess('Block was saved successfully!'); $this->_redirect('*/*/'.$this->getRequest()->getParam('back','index'),array('block_id'=>$block->getId())); } public function deleteAction() { $block = Mage::getModel('siteblocks/block') ->setId($this->getRequest()->getParam('block_id')) ->delete(); if($block->getId()) { Mage::getSingleton('adminhtml/session')->addSuccess('Block was deleted successfully!'); } $this->_redirect('*/*/'); } public function massStatusAction() { $statuses = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$statuses['massaction'])); foreach($blocks as $block) { $block->setBlockStatus($statuses['block_status'])->save(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were updated!'); return $this->_redirect('*/*/'); } public function massDeleteAction() { $blocks = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$blocks['massaction'])); foreach($blocks as $block) { $block->delete(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were deleted!'); return $this->_redirect('*/*/'); } } 


4.メディア/サむトブロック/フォルダヌを䜜成し、適切な曞き蟌み暩限を割り圓おるこずを忘れないでください。

フロント゚ンドでの画像の衚瀺を忘れないでください。


テンプレヌトを線集したす。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/サむトブロック/ list.phtml
 <?php foreach($this->getBlocks() as $block):?> <div class="siteblock"> <div class="block-title"><?php echo $block->getTitle()?></div> <div class="block-image"> <?php if($block->getImage()):?> <img src="<?php echo $block->getImageSrc()?>" height="150" width="auto" alt="<?php $block->getTitle()?>" title="<?php $block->getTitle()?>"> <?php endif;?> </div> <div class="block-content"><?php echo $block->getContent() ?></div> </div> <?php endforeach;?> 


モデルに新しいgetImageSrcメ゜ッドを远加したした。そのリストを次に瀺したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Block.php
 <?php /** * Class IGN_Siteblocks_Model_Block * @method getBlockStatus() * @method getContent() * @method getImage() */ class IGN_Siteblocks_Model_Block extends Mage_Core_Model_Abstract { protected $_eventPrefix = 'siteblocks_block'; public function _construct() { parent::_construct(); $this->_init('siteblocks/block'); } public function getImageSrc() { return Mage::getBaseUrl('media') . 'siteblocks' . DS . $this->getImage(); } } 


アップロヌドされたフルサむズの画像を衚瀺するこずはお勧めできたせんが、珟圚の䞻なタスクはレンダラヌを蚘述するこずです。


WYSIWYG゚ディタヌの䜿甚


ビデオMagento管理パネルでWYSIWYG゚ディタヌを䜿甚する


レッスンで䜜成されたモゞュヌルIGN_Siteblocks-11.zip

WYSIWYG の構造は、衚瀺されるものが取埗するものです衚瀺されるものは取埗するものです。これは、コンテンツを䜜成するための䟿利な゚ディタヌです。そしお、私たちのモゞュヌルにはアプリケヌションがありたす。ただし、その組み蟌みは予想ほど単玔ではありたせん。私たちは、管理パネルのレむアりトを䜜成する必芁があるこずに気付きたした。

app / design / adminhtml / default / default / layout / siteblocks.xml
 <?xml version="1.0"?> <layout version="1.0.0"> <adminhtml_siteblocks_edit> <!--       --> <update handle="editor"/> <!--     handle      js  css   ,      cms.xml --> </adminhtml_siteblocks_edit> <adminhtml_system_config_edit> <update handle="editor"/> </adminhtml_system_config_edit> </layout> 


次に、線集フォヌムを曎新する必芁がありたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Form.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('block_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form( array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save',array('block_id'=>$this->getRequest()->getParam('block_id'))), 'method' => 'post', 'enctype' => 'multipart/form-data' ) ); $form->setHtmlIdPrefix('block_'); $fieldset = $form->addFieldset('base_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('General Information'), 'class' => 'fieldset-wide') ); if ($model->getBlockId()) { $fieldset->addField('block_id', 'hidden', array( 'name' => 'block_id', )); } $fieldset->addField('title', 'text', array( 'name' => 'title', 'label' => Mage::helper('siteblocks')->__('Block Title'), 'title' => Mage::helper('siteblocks')->__('Block Title'), 'required' => true, )); //$fieldset->addType('myimage','IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Renderer_Myimage'); $fieldset->addField('image', 'myimage', array( 'name' => 'image', 'label' => Mage::helper('siteblocks')->__('Image'), 'title' => Mage::helper('siteblocks')->__('Image'), 'required' => true, )); $fieldset->addField('block_status', 'select', array( 'label' => Mage::helper('siteblocks')->__('Status'), 'title' => Mage::helper('siteblocks')->__('Status'), 'name' => 'block_status', 'required' => true, 'options' => Mage::getModel('siteblocks/source_status')->toArray(), )); #   $fieldset->addField('content', 'editor', array( 'name' => 'content', 'label' => Mage::helper('siteblocks')->__('Content'), 'title' => Mage::helper('siteblocks')->__('Content'), 'style' => 'height:36em', 'required' => true, 'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig() )); $form->setValues($model->getData()); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } //  ,       head,      protected function _prepareLayout() { parent::_prepareLayout(); if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { $this->getLayout()->getBlock('head')->setCanLoadTinyMce(true); } } } 


これらのアクションの埌、退屈なテキスト゚リアの代わりに、䟿利な゚ディタヌフィヌルドが埗られたす。構成ペヌゞのフィヌルドに察しお同じこずを行いたい堎合は、基本的に暙準の゚ディタヌ芁玠のコピヌアンドペヌストである新しいレンダラヌを䜜成する必芁がありたす。

lib / Varien / Data / Form / Element / Myeditor.php
 <?php class Varien_Data_Form_Element_Myeditor extends Varien_Data_Form_Element_Editor { public function __construct($attributes=array()) { parent::__construct($attributes); #      if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { Mage::app()->getLayout()->getBlock('head')->setCanLoadTinyMce(true); $this->setData('config',Mage::getSingleton('cms/wysiwyg_config')->getConfig()); } if($this->isEnabled()) { $this->setType('wysiwyg'); $this->setExtType('wysiwyg'); } else { $this->setType('textarea'); $this->setExtType('textarea'); } } } 


system.xmlは次のようになりたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ etc / system.xml
 <?xml version="1.0"?> <config> <tabs> <ign translate="label" module="siteblocks"> <label>IGN</label> <sort_order>2</sort_order> </ign> </tabs> <sections> <siteblocks module="siteblocks" translate="label"> <label>Siteblocks</label> <tab>ign</tab> <frontend>text</frontend> <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> <groups> <settings module="siteblocks" translate="label"> <label>Settings</label> <expanded>1</expanded> <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> <enabled translate="label comment" module="siteblocks"> <label>Enabled</label> <frontend_type>select</frontend_type> <source_model>siteblocks/source_status</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> <comment>Is module enabled</comment> </enabled> <blocks_count> <label>Blocks on page</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>1</show_in_store> <depends><enabled>1</enabled></depends> </blocks_count> <raw_text> <label>Raw text</label> <frontend_type>myeditor</frontend_type> <!--    frontend_type --> <sort_order>3</sort_order> <show_in_default>1</show_in_default> <show_in_Website>1</show_in_Website> <show_in_store>1</show_in_store> <depends><enabled>1</enabled></depends> </raw_text> <myimage> <label>Image</label> <frontend_type>myimage</frontend_type> <sort_order>3</sort_order> <show_in_default>1</show_in_default> <show_in_Website>1</show_in_Website> <show_in_store>1</show_in_store> <depends><enabled>1</enabled></depends> </myimage> </fields> </settings> </groups> </siteblocks> </sections> </config> 


このモゞュヌルでは、これは必須フィヌルドではなく、䟋ずしお䜜成されおいたす。しかし、この方法でコンテンツをフロント゚ンドに衚瀺したす。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/サむトブロック/ list.phtml
 <?php foreach($this->getBlocks() as $block):?> <div class="siteblock"> <div class="block-title"><?php echo $block->getTitle()?></div> <div class="block-image"> <?php if($block->getImage()):?> <img src="<?php echo $block->getImageSrc()?>" height="150" width="auto" alt="<?php $block->getTitle()?>" title="<?php $block->getTitle()?>"> <?php endif;?> </div> <div class="block-content"><?php echo $this->getBlockContent($block)?></div> </div> <?php endforeach;?> 


ブロックでは、このために新しいgetBlockContentメ゜ッドが䜜成されたした。

app / local / IGN / Siteblocks / Block / List.php
 <?php class IGN_Siteblocks_Block_List extends Mage_Core_Block_Template { public function getBlocks() { //return Mage::getResourceModel('siteblocks/block_collection'); $items = Mage::getModel('siteblocks/block')->getCollection() ->addFieldToFilter('block_status',array('eq'=>IGN_Siteblocks_Model_Source_Status::ENABLED)); return $items; } public function getBlockContent($block) { $processor = Mage::helper('cms')->getBlockTemplateProcessor(); $html = $processor->filter($block->getContent()); return $html; } } 




ルヌル条件を䜿甚する


ビデオMagentoでルヌル条件を䜿甚する


レッスンで䜜成したIGN_Siteblocks-12.zip モゞュヌルの構造

次のステップは、モゞュヌルに条件を远加するこずです。同じこずがMagentoプロモヌションルヌルでも䜿甚されおいたす。そしお、ここでは2皮類の条件が甚意されおいたす。最初は、2番目のバスケットで補品属性が䜿甚されたす。以䞋のレシピでは最初のケヌスに぀いお説明したすが、違いはいく぀かの行の眮換のみです。

なぜ条件が必芁なのですかブロックを衚瀺する堎所を遞択するために、条件を䜿甚したす。たずえば、䟡栌が100ドル未満の補品ペヌゞ、たたは16 GBのメモリず2015幎の補造日がある特定のカテゎリのすべおの電話。ここではナヌザヌケヌスに぀いおは説明したせん。

䜜成順序

1.モゞュヌルバヌゞョンを曎新し、テヌブルに新しい列が远加されるようにアップグレヌドスクリプトを远加したす。conditions_serializedなどTEXT。

app / code / local / IGN / Siteblocks / sql / siteblocks_setup / upgrade-1.0.1-1.0.2.php
 <?php /** @var Mage_Core_Model_Resource_Setup $installer */ $installer = $this; $installer->startSetup(); $installer->run(" ALTER TABLE `{$this->getTable('siteblocks/block')}` ADD `conditions_serialized` TEXT NOT NULL; "); $installer->endSetup(); 


2.モデルはMage_Rule_Model_Abstractを継承する必芁がありたす。そしお、2぀のメ゜ッドを宣蚀する必芁がありたすgetConditionsInstanceずgetActionInstance

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Observer.php
 <?php /** * Class IGN_Siteblocks_Model_Block * @method getBlockStatus() * @method getContent() * @method getImage() */ class IGN_Siteblocks_Model_Block extends Mage_Rule_Model_Abstract { protected $_eventPrefix = 'siteblocks_block'; # ,      ,     public function getActionsInstance() { return Mage::getModel('catalogrule/rule_action_collection'); } public function getConditionsInstance() { return Mage::getModel('catalogrule/rule_condition_combine'); } public function _construct() { parent::_construct(); $this->_init('siteblocks/block'); } public function getImageSrc() { return Mage::getBaseUrl('media') . 'siteblocks' . DS . $this->getImage(); } } 


getConditionsInstanceメ゜ッドぞのすべおの泚意。ここで、Catalog Price Rulesのような条件を䜿甚したす。補品のプロパティず属性のみ。ショッピングカヌト䟡栌ルヌルのような条件が必芁な堎合は、Mage :: getModel 'salesrule / rule_condition_combine';を䜿甚する必芁がありたす。

バスケット内のデヌタに基づいおブロックをい぀衚瀺するかを決定する堎合は、salesruleを䜿甚したす。たた、独自のモデルを䜜成し、その䞭に任意の条件を実装できたす。

3. コントロヌラヌでsaveActionを曎新する必芁がありたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = $this->getRequest()->getParam('block_id'); Mage::register('siteblocks_block',Mage::getModel('siteblocks/block')->load($id)); $blockObject = (array)Mage::getSingleton('adminhtml/session')->getBlockObject(true); if(count($blockObject)) { Mage::registry('siteblocks_block')->setData($blockObject); } $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit')); $this->renderLayout(); } protected function _uploadFile($fieldName,$model) { if( ! isset($_FILES[$fieldName])) { return false; } $file = $_FILES[$fieldName]; if(isset($file['name']) && (file_exists($file['tmp_name']))){ if($model->getId()){ unlink(Mage::getBaseDir('media').DS.$model->getData($fieldName)); } try { $path = Mage::getBaseDir('media') . DS . 'siteblocks' . DS; $uploader = new Varien_File_Uploader($file); $uploader->setAllowedExtensions(array('jpg','png','gif','jpeg')); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(false); $uploader->save($path, $file['name']); $model->setData($fieldName,$uploader->getUploadedFileName()); return true; } catch(Exception $e) { return false; } } } public function saveAction() { try { $id = $this->getRequest()->getParam('block_id'); /** @var IGN_Siteblocks_Model_Block $block */ $block = Mage::getModel('siteblocks/block')->load($id); /*$block ->setTitle($this->getRequest()->getParam('title')) ->setContent($this->getRequest()->getParam('content')) ->setBlockStatus($this->getRequest()->getParam('block_status')) ->save();*/ #      $data = $this->getRequest()->getParams(); if (isset($data['rule']['conditions'])) { $data['conditions'] = $data['rule']['conditions']; } unset($data['rule']); # setData  loadPost $block ->loadPost($data); $this->_uploadFile('image',$block); $block ->setCreatedAt(Mage::app()->getLocale()->date()) ->save(); if(!$block->getId()) { Mage::getSingleton('adminhtml/session')->addError('Cannot save the block'); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setBlockObject($block->getData()); return $this->_redirect('*/*/edit',array('block_id'=>$this->getRequest()->getParam('block_id'))); } Mage::getSingleton('adminhtml/session')->addSuccess('Block was saved successfully!'); $this->_redirect('*/*/'.$this->getRequest()->getParam('back','index'),array('block_id'=>$block->getId())); } public function deleteAction() { $block = Mage::getModel('siteblocks/block') ->setId($this->getRequest()->getParam('block_id')) ->delete(); if($block->getId()) { Mage::getSingleton('adminhtml/session')->addSuccess('Block was deleted successfully!'); } $this->_redirect('*/*/'); } public function massStatusAction() { $statuses = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$statuses['massaction'])); foreach($blocks as $block) { $block->setBlockStatus($statuses['block_status'])->save(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were updated!'); return $this->_redirect('*/*/'); } public function massDeleteAction() { $blocks = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$blocks['massaction'])); foreach($blocks as $block) { $block->delete(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were deleted!'); return $this->_redirect('*/*/'); } } 


4.管理者レむアりトを曎新したす。

アプリ/コヌド/デザむン/ adminhtml /デフォルト/デフォルト/レむアりト/ siteblocks.xml
 <?xml version="1.0"?> <layout version="1.0.0"> <adminhtml_siteblocks_edit> <update handle="editor"/> <!--     js  --> <reference name="head"> <action method="setCanLoadExtJs"><flag>1</flag></action> <action method="setCanLoadRulesJs"><flag>1</flag></action> </reference> </adminhtml_siteblocks_edit> <adminhtml_system_config_edit> <update handle="editor"/> </adminhtml_system_config_edit> </layout> 


5.フォヌムの管理ファむルを線集したす。ここで、条件デザむナヌを远加したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Form.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('block_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form( array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save',array('block_id'=>$this->getRequest()->getParam('block_id'))), 'method' => 'post', 'enctype' => 'multipart/form-data' ) ); $form->setHtmlIdPrefix('block_'); $fieldset = $form->addFieldset('base_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('General Information'), 'class' => 'fieldset-wide') ); if ($model->getBlockId()) { $fieldset->addField('block_id', 'hidden', array( 'name' => 'block_id', )); } $fieldset->addField('title', 'text', array( 'name' => 'title', 'label' => Mage::helper('siteblocks')->__('Block Title'), 'title' => Mage::helper('siteblocks')->__('Block Title'), 'required' => true, )); //$fieldset->addType('myimage','IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Renderer_Myimage'); $fieldset->addField('image', 'myimage', array( 'name' => 'image', 'label' => Mage::helper('siteblocks')->__('Image'), 'title' => Mage::helper('siteblocks')->__('Image'), 'required' => true, )); $fieldset->addField('block_status', 'select', array( 'label' => Mage::helper('siteblocks')->__('Status'), 'title' => Mage::helper('siteblocks')->__('Status'), 'name' => 'block_status', 'required' => true, 'options' => Mage::getModel('siteblocks/source_status')->toArray(), )); $fieldset->addField('content', 'editor', array( 'name' => 'content', 'label' => Mage::helper('siteblocks')->__('Content'), 'title' => Mage::helper('siteblocks')->__('Content'), 'style' => 'height:36em', 'required' => true, 'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig() )); #    $model->getConditions()->setJsFormObject('block_conditions_fieldset'); $renderer = Mage::getBlockSingleton('adminhtml/widget_form_renderer_fieldset') ->setTemplate('promo/fieldset.phtml') ->setNewChildUrl($this->getUrl('*/promo_catalog/newConditionHtml/form/block_conditions_fieldset')); $conditionsFieldset = $form->addFieldset('conditions_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('Conditions'), 'class' => 'fieldset-wide') )->setRenderer($renderer); $conditionsFieldset->addField('conditions', 'text', array( 'name' => 'conditions', 'label' => Mage::helper('siteblocks')->__('Conditions'), 'title' => Mage::helper('siteblocks')->__('Conditions'), 'required' => true, ))->setRule($model)->setRenderer(Mage::getBlockSingleton('rule/conditions')); $form->setValues($model->getData()); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } protected function _prepareLayout() { parent::_prepareLayout(); if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { #    ,    2   $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); $this->getLayout()->getBlock('head')->setCanLoadRulesJs(true); $this->getLayout()->getBlock('head')->setCanLoadTinyMce(true); } } } 


次の行に泚意しおください。

 $this->getUrl('*/promo_catalog/newConditionHtml/form/block_conditions_fieldset') 

ショッピングカヌト䟡栌ルヌルを䜿甚する堎合

 $this->getUrl('*/promo_quote/newConditionHtml/form/block_conditions_fieldset') 

別の重芁なポむントを探したす。

block_conditions_fieldset -どこblock_䞀臎しおいる必芁がありたす$ form-> setHtmlIdPrefix 'block_' ;

そしお、それは管理者偎のすべおです。ここで、フロント゚ンドの条件の怜蚌を远加したす。このために、List.phpブロックを線集したす

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/List.php
 <?php class IGN_Siteblocks_Block_List extends Mage_Core_Block_Template { public function getBlocks() { //return Mage::getResourceModel('siteblocks/block_collection'); $items = Mage::getModel('siteblocks/block')->getCollection() ->addFieldToFilter('block_status',array('eq'=>IGN_Siteblocks_Model_Source_Status::ENABLED)); $filteredItems = $items; #      . if(Mage::registry('current_product') instanceof Mage_Catalog_Model_Product) { $filteredItems = array(); /** @var IGN_Siteblocks_Model_Block $item */ foreach ($items as $item) { #  validate    ,     if($item->validate(Mage::registry('current_product'))) { $filteredItems[] = $item; } } } return $filteredItems; } public function getBlockContent($block) { $processor = Mage::helper('cms')->getBlockTemplateProcessor(); $html = $processor->filter($block->getContent()); return $html; } } 


バリデヌタの䜿甚は非垞に簡単です。このケヌスでは、ブロックの出力がクリヌチャヌペヌゞで発生せず、この堎合に怜蚌するものがない堎合、条件を無芖したす。


線集ペヌゞでタブを䜿甚する


ビデオMagentoの線集ペヌゞでタブを䜿甚する


レッスンで䜜成されたIGN_Siteblocks-13.zipモゞュヌルの構造。

倚くのフィヌルドがある堎合、タブは䟿利で䟿利です。フィヌルドをグルヌプに分割し、各グルヌプが独自のタブを䜜成したす。タブを远加するにはいく぀かのオプションがありたす。たず、タブクラスを䜜成し、その出力を線集ペヌゞに远加する必芁がありたす。クラス自䜓は次のようになりたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Tabs.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { public function __construct() { parent::__construct(); $this->setId('block_tabs'); $this->setDestElementId('edit_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } #      .       protected function _prepareLayout() { $this->addTab('main_tab',array( 'label' => $this->__('Main'), 'title' => $this->__('Main'), 'content' => $this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tab_main')->toHtml() )); /*$this->addTab('conditions_tab',array( 'label' => $this->__('Conditions'), 'title' => $this->__('Conditions'), 'content' => $this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tab_conditions')->toHtml() ));*/ $this->addTab('conditions_tab','siteblocks/adminhtml_siteblocks_edit_tab_conditions'); return parent::_prepareLayout(); } } 


addTabメ゜ッドの実装を芋おください。配列、オブゞェクト、文字列をフィヌドできるこずがわかりたす。そしお、いく぀かの違いがありたす。ここでは、ビデオを芋お、それを明確に瀺すこずをお勧めしたす。しかし、ここで䞀蚀蚀いたす。

メ゜ッドに文字列を枡す堎合、タブクラスはMage_Adminhtml_Block_Widget_Tab_Interfaceむンタヌフェむスを実装する必芁がありたす。

そうしないず、゚ラヌが発生したす。たた、むンタヌフェヌスには4぀のメ゜ッドの実装が必芁です。したがっお、この䟋では、デモ甚に2぀のオプションを䜿甚したす。実際には、同じ方法でタブを远加するこずをお勧めしたす。

゜ヌスファむルForm.phpからコピヌしたタブの内容を芋おみたしょう

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/タブ/ Main.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tab_Main extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('main_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form(); $form->setHtmlIdPrefix('main_'); $fieldset = $form->addFieldset('base_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('General Information'), 'class' => 'fieldset-wide') ); if ($model->getBlockId()) { $fieldset->addField('block_id', 'hidden', array( 'name' => 'block_id', )); } $fieldset->addField('title', 'text', array( 'name' => 'title', 'label' => Mage::helper('siteblocks')->__('Block Title'), 'title' => Mage::helper('siteblocks')->__('Block Title'), 'required' => true, )); //$fieldset->addType('myimage','IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Renderer_Myimage'); $fieldset->addField('image', 'myimage', array( 'name' => 'image', 'label' => Mage::helper('siteblocks')->__('Image'), 'title' => Mage::helper('siteblocks')->__('Image'), 'required' => true, )); $fieldset->addField('block_status', 'select', array( 'label' => Mage::helper('siteblocks')->__('Status'), 'title' => Mage::helper('siteblocks')->__('Status'), 'name' => 'block_status', 'required' => true, 'options' => Mage::getModel('siteblocks/source_status')->toArray(), )); $fieldset->addField('content', 'editor', array( 'name' => 'content', 'label' => Mage::helper('siteblocks')->__('Content'), 'title' => Mage::helper('siteblocks')->__('Content'), 'style' => 'height:36em', 'required' => true, 'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig() )); $form->setValues($model->getData()); $this->setForm($form); return parent::_prepareForm(); } protected function _prepareLayout() { parent::_prepareLayout(); if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { $this->getLayout()->getBlock('head')->setCanLoadTinyMce(true); } } } 


アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/タブ/ Conditions.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tab_Conditions extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface { #,    public function getTabTitle() { return $this->__('Conditions'); } public function getTabLabel() { return $this->__('Conditions'); } public function canShowTab() { return true; } public function isHidden() { return false; } /** * Init form */ public function __construct() { parent::__construct(); $this->setId('conditions_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Conditions')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form(); $form->setHtmlIdPrefix('block_'); $model->getConditions()->setJsFormObject('block_conditions_fieldset'); $renderer = Mage::getBlockSingleton('adminhtml/widget_form_renderer_fieldset') ->setTemplate('promo/fieldset.phtml') ->setNewChildUrl($this->getUrl('*/promo_catalog/newConditionHtml/form/block_conditions_fieldset')); $conditionsFieldset = $form->addFieldset('conditions_fieldset', array( 'legend'=>Mage::helper('siteblocks')->__('Conditions'), 'class' => 'fieldset-wide') )->setRenderer($renderer); $conditionsFieldset->addField('conditions', 'text', array( 'name' => 'conditions', 'label' => Mage::helper('siteblocks')->__('Conditions'), 'title' => Mage::helper('siteblocks')->__('Conditions'), 'required' => true, ))->setRule($model)->setRenderer(Mage::getBlockSingleton('rule/conditions')); $form->setValues($model->getData()); $this->setForm($form); return parent::_prepareForm(); } protected function _prepareLayout() { parent::_prepareLayout(); if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { $this->getLayout()->getBlock('head')->setCanLoadTinyMce(true); } } } 


元のForm.phpファむルをコピヌしたした。分離されたフォヌム芁玠。フラグを削陀するこずを忘れないでください$ form-> setUseContainertrue; 。 したがっお、フォヌムの゜ヌスファむルからフィヌルドを削陀できたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Form.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { /** * Init form */ public function __construct() { parent::__construct(); $this->setId('block_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareForm() { $model = Mage::registry('siteblocks_block'); $form = new Varien_Data_Form( array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save',array('block_id'=>$this->getRequest()->getParam('block_id'))), 'method' => 'post', 'enctype' => 'multipart/form-data' ) ); $form->setHtmlIdPrefix('block_'); $form->setValues($model->getData()); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } protected function _prepareLayout() { parent::_prepareLayout(); if (Mage::getSingleton('cms/wysiwyg_config')->isEnabled()) { $this->getLayout()->getBlock('head')->setCanLoadTinyMce(true); } } } 


タブブロックの出力を描画する方法。

コントロヌラヌのメ゜ッド番号1

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = $this->getRequest()->getParam('block_id'); Mage::register('siteblocks_block',Mage::getModel('siteblocks/block')->load($id)); $blockObject = (array)Mage::getSingleton('adminhtml/session')->getBlockObject(true); if(count($blockObject)) { Mage::registry('siteblocks_block')->setData($blockObject); } $this->loadLayout(); #     $this->_addLeft($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tabs')); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit')); $this->renderLayout(); } protected function _uploadFile($fieldName,$model) { if( ! isset($_FILES[$fieldName])) { return false; } $file = $_FILES[$fieldName]; if(isset($file['name']) && (file_exists($file['tmp_name']))){ if($model->getId()){ unlink(Mage::getBaseDir('media').DS.$model->getData($fieldName)); } try { $path = Mage::getBaseDir('media') . DS . 'siteblocks' . DS; $uploader = new Varien_File_Uploader($file); $uploader->setAllowedExtensions(array('jpg','png','gif','jpeg')); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(false); $uploader->save($path, $file['name']); $model->setData($fieldName,$uploader->getUploadedFileName()); return true; } catch(Exception $e) { return false; } } } public function saveAction() { try { $id = $this->getRequest()->getParam('block_id'); /** @var IGN_Siteblocks_Model_Block $block */ $block = Mage::getModel('siteblocks/block')->load($id); /*$block ->setTitle($this->getRequest()->getParam('title')) ->setContent($this->getRequest()->getParam('content')) ->setBlockStatus($this->getRequest()->getParam('block_status')) ->save();*/ $data = $this->getRequest()->getParams(); if (isset($data['rule']['conditions'])) { $data['conditions'] = $data['rule']['conditions']; } unset($data['rule']); $block ->loadPost($data); $this->_uploadFile('image',$block); $block ->setCreatedAt(Mage::app()->getLocale()->date()) ->save(); if(!$block->getId()) { Mage::getSingleton('adminhtml/session')->addError('Cannot save the block'); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setBlockObject($block->getData()); return $this->_redirect('*/*/edit',array('block_id'=>$this->getRequest()->getParam('block_id'))); } Mage::getSingleton('adminhtml/session')->addSuccess('Block was saved successfully!'); $this->_redirect('*/*/'.$this->getRequest()->getParam('back','index'),array('block_id'=>$block->getId())); } public function deleteAction() { $block = Mage::getModel('siteblocks/block') ->setId($this->getRequest()->getParam('block_id')) ->delete(); if($block->getId()) { Mage::getSingleton('adminhtml/session')->addSuccess('Block was deleted successfully!'); } $this->_redirect('*/*/'); } public function massStatusAction() { $statuses = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$statuses['massaction'])); foreach($blocks as $block) { $block->setBlockStatus($statuses['block_status'])->save(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were updated!'); return $this->_redirect('*/*/'); } public function massDeleteAction() { $blocks = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$blocks['massaction'])); foreach($blocks as $block) { $block->delete(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were deleted!'); return $this->_redirect('*/*/'); } } 


しかし、このベンチャヌを攟棄し、レむアりトでメ゜ッド番号2を䜿甚したす。

app / design / adminhtml / default / default / layout / siteblocks.xml
 <?xml version="1.0"?> <layout version="1.0.0"> <adminhtml_siteblocks_edit> <update handle="editor"/> <reference name="head"> <action method="setCanLoadExtJs"><flag>1</flag></action> <action method="setCanLoadRulesJs"><flag>1</flag></action> </reference> <!--       --> <reference name="left"> <block type="siteblocks/adminhtml_siteblocks_edit_tabs" name="siteblocks_tabs"> <!-- 2 c     --> <block name="conditions_tab" type="siteblocks/adminhtml_siteblocks_edit_tab_conditions"/> <action method="addTab"><name>my_conditions</name><block>conditions_tab</block></action> <action method="addTab"><name>my_conditions</name><block>siteblocks/adminhtml_siteblocks_edit_tab_conditions</block></action> </block> </reference> </adminhtml_siteblocks_edit> <adminhtml_system_config_edit> <update handle="editor"/> </adminhtml_system_config_edit> </layout> 


最埌に、アドバむスの1぀ずしお、すぐに2か所にタブを远加しないでください。1぀はレむアりトに、もう1぀はブロックにありたす。レむアりト内の1぀の堎所、すべお、たたはブロック内のすべおを远加したす。


線集ペヌゞおよびフロント゚ンドでの商品の出力テヌブルグリッド。


ビデオMagentoの線集ペヌゞでタブを䜿甚する


レッスンで䜜成されたIGN_Siteblocks-14.zip モゞュヌルの構造ここで、モゞュヌルに

最終機胜を远加したす-ブロックずずもにフロント゚ンドに衚瀺される補品をマヌクする機胜。

代替の関連補品の䞀皮。ブロックに適した条件を備えた商品のペヌゞに、テキストず商品を含むブロックを出力する非垞に有甚な有甚な事䟋が頭の䞭に圢成されおいたす。

新しいタブを远加したす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/ Tabs.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { public function __construct() { parent::__construct(); $this->setId('block_tabs'); $this->setDestElementId('edit_form'); $this->setTitle(Mage::helper('siteblocks')->__('Block Information')); } protected function _prepareLayout() { $this->addTab('main_tab',array( 'label' => $this->__('Main'), 'title' => $this->__('Main'), 'content' => $this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tab_main')->toHtml() )); $this->addTab('conditions_tab',array( 'label' => $this->__('Conditions'), 'title' => $this->__('Conditions'), 'content' => $this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tab_conditions')->toHtml() )); //     AJAX,         $this->addTab('products_tab','siteblocks/adminhtml_siteblocks_edit_tab_products'); return parent::_prepareLayout(); } } 


タブはAJAXを䜿甚したす。これはコヌドで芋るこずができたす。リク゚スト甚のURLもありたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/タブ/ Products.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tab_Products extends Mage_Adminhtml_Block_Widget_Form implements Mage_Adminhtml_Block_Widget_Tab_Interface { public function getTabTitle() { return $this->__('Products'); } public function getTabLabel() { return $this->__('Products'); } public function canShowTab() { return true; } public function isHidden() { return false; } public function getClass() { return 'ajax'; } public function getTabClass() { return 'ajax'; } #URL  , ('_current'=>true)     ,     block_id    public function getTabUrl() { return $this->getUrl('*/*/products',array('_current'=>true)); } } 


なぜならタブはAJAXを䜿甚しおいるため、コントロヌラヌにアクションを远加する必芁がありたす。そしお、先を芋るず、saveActionにどのロゞックが远加されたかがわかり、マヌクされた補品が保存されたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/コントロヌラヌ/ Adminhtml / SiteblocksController.php
 <?php class IGN_Siteblocks_Adminhtml_SiteblocksController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = $this->getRequest()->getParam('block_id'); Mage::register('siteblocks_block',Mage::getModel('siteblocks/block')->load($id)); $blockObject = (array)Mage::getSingleton('adminhtml/session')->getBlockObject(true); if(count($blockObject)) { Mage::registry('siteblocks_block')->setData($blockObject); } $this->loadLayout(); //$this->_addLeft($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit_tabs')); $this->_addContent($this->getLayout()->createBlock('siteblocks/adminhtml_siteblocks_edit')); $this->renderLayout(); } protected function _uploadFile($fieldName,$model) { if( ! isset($_FILES[$fieldName])) { return false; } $file = $_FILES[$fieldName]; if(isset($file['name']) && (file_exists($file['tmp_name']))){ if($model->getId()){ unlink(Mage::getBaseDir('media').DS.$model->getData($fieldName)); } try { $path = Mage::getBaseDir('media') . DS . 'siteblocks' . DS; $uploader = new Varien_File_Uploader($file); $uploader->setAllowedExtensions(array('jpg','png','gif','jpeg')); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(false); $uploader->save($path, $file['name']); $model->setData($fieldName,$uploader->getUploadedFileName()); return true; } catch(Exception $e) { return false; } } } public function saveAction() { try { $id = $this->getRequest()->getParam('block_id'); /** @var IGN_Siteblocks_Model_Block $block */ $block = Mage::getModel('siteblocks/block')->load($id); /*$block ->setTitle($this->getRequest()->getParam('title')) ->setContent($this->getRequest()->getParam('content')) ->setBlockStatus($this->getRequest()->getParam('block_status')) ->save();*/ $data = $this->getRequest()->getParams(); #         $links = $this->getRequest()->getPost('links', array()); if (array_key_exists('products', $links)) { $selectedProducts = Mage::helper('adminhtml/js')->decodeGridSerializedInput($links['products']); $products = array(); foreach($selectedProducts as $product => $position) { $products[$product] = isset($position['position']) ? $position['position'] : $product; } $data['products'] = $products; } if (isset($data['rule']['conditions'])) { $data['conditions'] = $data['rule']['conditions']; } unset($data['rule']); $block ->loadPost($data); $this->_uploadFile('image',$block); $block ->setCreatedAt(Mage::app()->getLocale()->date()) ->save(); if(!$block->getId()) { Mage::getSingleton('adminhtml/session')->addError('Cannot save the block'); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setBlockObject($block->getData()); return $this->_redirect('*/*/edit',array('block_id'=>$this->getRequest()->getParam('block_id'))); } Mage::getSingleton('adminhtml/session')->addSuccess('Block was saved successfully!'); $this->_redirect('*/*/'.$this->getRequest()->getParam('back','index'),array('block_id'=>$block->getId())); } public function deleteAction() { $block = Mage::getModel('siteblocks/block') ->setId($this->getRequest()->getParam('block_id')) ->delete(); if($block->getId()) { Mage::getSingleton('adminhtml/session')->addSuccess('Block was deleted successfully!'); } $this->_redirect('*/*/'); } public function massStatusAction() { $statuses = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$statuses['massaction'])); foreach($blocks as $block) { $block->setBlockStatus($statuses['block_status'])->save(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were updated!'); return $this->_redirect('*/*/'); } public function massDeleteAction() { $blocks = $this->getRequest()->getParams(); try { $blocks= Mage::getModel('siteblocks/block') ->getCollection() ->addFieldToFilter('block_id',array('in'=>$blocks['massaction'])); foreach($blocks as $block) { $block->delete(); } } catch(Exception $e) { Mage::logException($e); Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); return $this->_redirect('*/*/'); } Mage::getSingleton('adminhtml/session')->addSuccess('Blocks were deleted!'); return $this->_redirect('*/*/'); } #2     AJAX  public function productsAction() { $this->loadLayout() ->renderLayout(); } public function productsgridAction() { $this->loadLayout() ->renderLayout(); } } 


コントロヌラヌのコヌドから、レむアりトを曎新する必芁があるこずは明らかです。

app / design / adminhtml / default / default / layout / adminhtml.xml
 <?xml version="1.0"?> <layout version="1.0.0"> <adminhtml_siteblocks_edit> <update handle="editor"/> <reference name="head"> <action method="setCanLoadExtJs"><flag>1</flag></action> <action method="setCanLoadRulesJs"><flag>1</flag></action> </reference> <reference name="left"> <block type="siteblocks/adminhtml_siteblocks_edit_tabs" name="siteblocks_tabs"> <!-- <block name="conditions_tab" type="siteblocks/adminhtml_siteblocks_edit_tab_conditions"/> <action method="addTab"><name>my_conditions</name><block>conditions_tab</block></action>--> <!--<action method="addTab"><name>my_conditions</name><block>siteblocks/adminhtml_siteblocks_edit_tab_conditions</block></action>--> </block> </reference> </adminhtml_siteblocks_edit> <adminhtml_system_config_edit> <update handle="editor"/> </adminhtml_system_config_edit> <!--    ,     ,        --> <adminhtml_siteblocks_products> <block type="core/text_list" name="root" output="toHtml"> <block type="siteblocks/adminhtml_siteblocks_edit_tab_products_grid" name="siteblocks_products"/> <block type="adminhtml/widget_grid_serializer" name="siteblocks_products_serializer"> <reference name="siteblocks_products_serializer"> <action method="initSerializerBlock"> <grid_block_name>siteblocks_products</grid_block_name> <data_callback>getSelectedBlockProducts</data_callback> <hidden_input_name>links[products]</hidden_input_name> <reload_param_name>siteblocks_products</reload_param_name> </action> <action method="addColumnInputName"> <input_name>position</input_name> </action> </reference> </block> </block> </adminhtml_siteblocks_products> <!--       --> <adminhtml_siteblocks_productsgrid> <block type="core/text_list" name="root" output="toHtml"> <block type="siteblocks/adminhtml_siteblocks_edit_tab_products_grid" name="block_products"/> </block> </adminhtml_siteblocks_productsgrid> </layout> 


適切なブロックの呜名に泚意しおください。プロゞェクトの名前を倉曎したす。すべおの堎所で同期的に名前を倉曎したす。

管理むンタヌフェむスの最埌の芁玠は、テヌブルクラスになりたす。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/ Adminhtml /サむトブロック/線集/タブ/補品/ Grid.php
 <?php class IGN_Siteblocks_Block_Adminhtml_Siteblocks_Edit_Tab_Products_Grid extends Mage_Adminhtml_Block_Widget_Grid { protected $_block; /** * Set grid params * */ public function __construct() { parent::__construct(); $this->setId('siteblocks_product_grid'); $this->setDefaultSort('entity_id'); $this->setUseAjax(true); if ($this->_getBlock()->getId()) { $this->setDefaultFilter(array('in_products'=>1)); } if ($this->isReadonly()) { $this->setFilterVisibility(false); } } protected function _getBlock() { if(!$this->_block) { $this->_block = Mage::getModel('siteblocks/block')->load($this->getRequest()->getParam('block_id')); } return $this->_block; } protected function _addColumnFilterToCollection($column) { // Set custom filter for in product flag if ($column->getId() == 'in_products') { $productIds = $this->_getSelectedProducts(); if (empty($productIds)) { $productIds = 0; } if ($column->getFilter()->getValue()) { $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$productIds)); } else { if($productIds) { $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds)); } } } else { parent::_addColumnFilterToCollection($column); } return $this; } /** * Checks when this block is readonly * * @return boolean */ public function isReadonly() { return $this->_getBlock()->getUpsellReadonly(); } protected function _prepareCollection() { #        $collection = Mage::getResourceModel('catalog/product_collection') ->addAttributeToSelect('*'); if ($this->isReadonly()) { $productIds = $this->_getSelectedProducts(); if (empty($productIds)) { $productIds = array(0); } $collection->addFieldToFilter('entity_id', array('in'=>$productIds)); } $this->setCollection($collection); return parent::_prepareCollection(); } /** * Add columns to grid * * @return Mage_Adminhtml_Block_Widget_Grid */ protected function _prepareColumns() { #       if (!$this->_getBlock()->getUpsellReadonly()) { $this->addColumn('in_products', array( 'header_css_class' => 'a-center', 'type' => 'checkbox', 'name' => 'in_products', 'values' => $this->_getSelectedProducts(), 'align' => 'center', 'index' => 'entity_id' )); } $this->addColumn('entity_id', array( 'header' => Mage::helper('catalog')->__('ID'), 'sortable' => true, 'width' => 60, 'index' => 'entity_id' )); $this->addColumn('name', array( 'header' => Mage::helper('catalog')->__('Name'), 'index' => 'name' )); $this->addColumn('type', array( 'header' => Mage::helper('catalog')->__('Type'), 'width' => 100, 'index' => 'type_id', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_type')->getOptionArray(), )); $sets = Mage::getResourceModel('eav/entity_attribute_set_collection') ->setEntityTypeFilter(Mage::getModel('catalog/product')->getResource()->getTypeId()) ->load() ->toOptionHash(); $this->addColumn('set_name', array( 'header' => Mage::helper('catalog')->__('Attrib. Set Name'), 'width' => 130, 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, )); $this->addColumn('status', array( 'header' => Mage::helper('catalog')->__('Status'), 'width' => 90, 'index' => 'status', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_status')->getOptionArray(), )); $this->addColumn('visibility', array( 'header' => Mage::helper('catalog')->__('Visibility'), 'width' => 90, 'index' => 'visibility', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_visibility')->getOptionArray(), )); $this->addColumn('sku', array( 'header' => Mage::helper('catalog')->__('SKU'), 'width' => 80, 'index' => 'sku' )); $this->addColumn('price', array( 'header' => Mage::helper('catalog')->__('Price'), 'type' => 'currency', 'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE), 'index' => 'price' )); $this->addColumn('position', array( 'header' => Mage::helper('catalog')->__('Position'), 'name' => 'position', 'type' => 'number', 'width' => 60, 'validate_class' => 'validate-number', 'index' => 'position', 'editable' => true )); return parent::_prepareColumns(); } # URL       public function getGridUrl() { return $this->_getData('grid_url') ? $this->_getData('grid_url') : $this->getUrl('*/*/productsgrid', array('_current'=>true)); } protected function _getSelectedProducts() { return array_keys($this->getSelectedBlockProducts()); } public function getSelectedBlockProducts() { $selected = $this->getRequest()->getParam('siteblocks_products'); $products = array(); foreach ($this->_getBlock()->getProducts() as $product => $position) { $products[$product] = array('position' => $position); } foreach ($selected as $product) { if(!isset($products[$product])) { $products[$product] = array('position'=>$product); } } return $products; } } 


補品を正垞に保存するには、バヌゞョンを曎新し、新しいアップグレヌドスクリプトを䜜成しお、新しい列を远加する必芁がありたす。

app / code / local / IGN / Siteblocks / sql / siteblocks_setup / upgrade-1.0.2-1.0.3.php
 <?php /** @var Mage_Core_Model_Resource_Setup $installer */ $installer = $this; $installer->startSetup(); $installer->run(" ALTER TABLE `{$this->getTable('siteblocks/block')}` ADD `products` TEXT NOT NULL; "); $installer->endSetup(); 


モデルの小さな倉換。

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/モデル/ Block.php
 <?php /** * Class IGN_Siteblocks_Model_Block * @method getBlockStatus() * @method getContent() * @method getImage() */ class IGN_Siteblocks_Model_Block extends Mage_Rule_Model_Abstract { protected $_eventPrefix = 'siteblocks_block'; public function getActionsInstance() { return Mage::getModel('catalogrule/rule_action_collection'); } public function getConditionsInstance() { return Mage::getModel('catalogrule/rule_condition_combine'); } public function _construct() { parent::_construct(); $this->_init('siteblocks/block'); } public function getImageSrc() { return Mage::getBaseUrl('media') . 'siteblocks' . DS . $this->getImage(); } #      protected function _beforeSave() { parent::_beforeSave(); if(is_array($this->getData('products'))) { $this->setData('products',json_encode($this->getData('products'))); } } #      protected function _afterLoad() { parent::_beforeSave(); if(!empty($this->getData('products'))) { $this->setData('products',(array)json_decode($this->getData('products'))); } } # ,      public function getProducts() { if(!is_array($this->getData('products'))) { $this->setData('products',(array)json_decode($this->getData('products'))); } return $this->getData('products'); } } 


商品を割り圓おるこずができたす。ここで、それらをフロント゚ンドで正しく衚瀺する必芁がありたす。これらの目的のために、アップセルからコピヌし、ニヌズに合わせお線集した新しいテンプレヌトを䜜成したした。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/サむトブロック/補品/ list.php
 <?php if(count($this->getLoadedProductCollection()->getItems())): ?> <div class="box-collateral box-up-sell"> <h2><?php echo $this->__('You may also like') ?></h2> <ul class="products-grid products-grid--max-4-col" id="upsell-product-table"> <?php foreach ($this->getLoadedProductCollection()->getItems() as $_link): ?> <li> <a href="<?php echo $_link->getProductUrl() ?>" title="<?php echo $this->escapeHtml($_link->getName()) ?>" class="product-image"> <img src="<?php echo $this->helper('catalog/image')->init($_link, 'small_image')->resize(280) ?>" alt="<?php echo $this->escapeHtml($_link->getName()) ?>" /> </a> <h3 class="product-name"><a href="<?php echo $_link->getProductUrl() ?>" title="<?php echo $this->escapeHtml($_link->getName()) ?>"><?php echo $this->escapeHtml($_link->getName()) ?></a></h3> <?php echo $this->getPriceHtml($_link, true, '-upsell') ?> </li> <?php endforeach; ?> </ul> </div> <?php endif ?> 


list.phtmlブロック出力テンプレヌトも曎新したす。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/サむトブロック/ list.php
 <?php foreach($this->getBlocks() as $block):?> <div class="siteblock"> <div class="block-title"><?php echo $block->getTitle()?></div> <div class="block-image"> <?php if($block->getImage()):?> <img src="<?php echo $block->getImageSrc()?>" height="150" width="auto" alt="<?php $block->getTitle()?>" title="<?php $block->getTitle()?>"> <?php endif;?> </div> <div class="block-content"><?php echo $this->getBlockContent($block)?></div> <div class="block-product-list"> <?php echo $this->getProductsList($block)?> </div> </div> <?php endforeach;?> 


そしお、List.phpブロックに必芁な倉曎

アプリ/コヌド/ロヌカル/ IGN /サむトブロック/ブロック/List.php
 <?php class IGN_Siteblocks_Block_List extends Mage_Core_Block_Template { public function getBlocks() { //return Mage::getResourceModel('siteblocks/block_collection'); $items = Mage::getModel('siteblocks/block')->getCollection() ->addFieldToFilter('block_status',array('eq'=>IGN_Siteblocks_Model_Source_Status::ENABLED)); $filteredItems = $items; if(Mage::registry('current_product') instanceof Mage_Catalog_Model_Product) { $filteredItems = array(); /** @var IGN_Siteblocks_Model_Block $item */ foreach ($items as $item) { if($item->validate(Mage::registry('current_product'))) { $filteredItems[] = $item; } } } return $filteredItems; } public function getBlockContent($block) { $processor = Mage::helper('cms')->getBlockTemplateProcessor(); $html = $processor->filter($block->getContent()); return $html; } //      public function getProductsList($block) { $products = $block->getProducts(); asort($products); $collection = Mage::getResourceModel('catalog/product_collection') ->addFieldToFilter('entity_id',array('in'=>array_keys($products))) ->addAttributeToSelect('*'); /** @var Mage_Catalog_Block_Product_List $list */ $list = $this->getLayout()->createBlock('catalog/product_list'); $list->setCollection($collection); $list->setTemplate('siteblocks/product/list.phtml'); return $list->toHtml(); } } 


商品甚に独自のブロックを䜜成するこずもできたすが、タスクには暙準のブロックを䜿甚できたす。

したがっお、サむトのいく぀かの堎所でブロックを衚瀺できるモゞュヌルを取埗したした。補品ペヌゞのブロックの出力は、条件のチェックルヌル条件で実行されたす。䟿利なWYSIWYG゚ディタヌを䜿甚しおコンテンツを入力したす。

たた、ブロックずずもに、いく぀かの補品を衚瀺できたす。いく぀かの倉曎を加えれば、実際の䜿甚を簡単に芋぀けるこずができるモゞュヌル。䜜成されたモゞュヌルを含む公開リポゞトリ。そしお、このガむドは、独自の支払い方法ず配送方法を䜜成するプロセスを考慮しなければ完党ではありたせん。



支払方法モゞュヌルの䜜成


ビデオMagentoの支払い方法モゞュヌルの開発


パブリックリポゞトリbitbucket.org/dvman8bit/ign_payment

これは、秘密コヌドを入力しお泚文の支払いを行うこずができる支払い方法になりたす。これが泚文に察しお支払ういく぀かの詳现の入力であるず想像しおみたしょう。テヌマを開発し、本栌的なフォヌムにするこずができたす。私たちの仕事は、最小限の行動を理解しお、将来の本栌的な支払い方法の基瀎を䜜るこずです。

支払い方法には、2぀のブロック、2぀のテンプレヌト、2぀のxmlファむル、1぀のモデルのファむルが含たれたす。
system.xmlから始めたしょう。既存の[支払い方法]タブに新しいセクションを远加したす。

アプリ/コヌド/コミュニティ/ IGN /支払い/ etc / system.xml
 <?xml version="1.0"?> <config> <sections> <payment> <groups> <ignpayment translate="label"> <label>IGN Payment</label> <frontend_type>text</frontend_type> <sort_order>30</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> <fields> <active translate="label"> <label>Enabled</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_model> <sort_order>1</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </active> <order_status translate="label"> <label>New Order Status</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_order_status_newprocessing</source_model> <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> </order_status> <payment_action translate="label"> <label>Automatically Invoice All Items</label> <frontend_type>select</frontend_type> <source_model>payment/source_invoice</source_model> <sort_order>3</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> <depends> <order_status separator=",">processing,processed_ogone</order_status> </depends> </payment_action> <sort_order translate="label"> <label>Sort Order</label> <frontend_type>text</frontend_type> <sort_order>100</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> <frontend_class>validate-number</frontend_class> </sort_order> <title translate="label"> <label>Title</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> </title> <allowspecific translate="label"> <label>Payment from Applicable Countries</label> <frontend_type>allowspecific</frontend_type> <sort_order>50</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> <specificcountry translate="label"> <label>Payment from Specific Countries</label> <frontend_type>multiselect</frontend_type> <sort_order>51</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> <can_be_empty>1</can_be_empty> </specificcountry> <min_order_total translate="label"> <label>Minimum Order Total</label> <frontend_type>text</frontend_type> <sort_order>98</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </min_order_total> <max_order_total translate="label"> <label>Maximum Order Total</label> <frontend_type>text</frontend_type> <sort_order>99</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </max_order_total> <secret_code translate="label"> <label>Secret Code</label> <frontend_type>text</frontend_type> <sort_order>99</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </secret_code> </fields> </ignpayment> </groups> </payment> </sections> </config> 


system.xmlでは、ほずんどすべおのフィヌルドが暙準です。シヌクレットコヌドを入力する新しいフィヌルドを1぀だけ远加したした。

アプリ/コヌド/コミュニティ/ IGN /支払い/ etc / config.xml
 <?xml version="1.0"?> <config> <modules> <IGN_Payment> <version>1.0.0</version> </IGN_Payment> </modules> <global> <models> <ignpayment> <class>IGN_Payment_Model</class> </ignpayment> </models> <resources> <payment_setup> <setup> <module>IGN_Payment</module> </setup> </payment_setup> </resources> <blocks> <ignpayment> <class>IGN_Payment_Block</class> </ignpayment> </blocks> <helpers> <ignpayment> <class>IGN_Payment_Helper</class> </ignpayment> </helpers> </global> <frontend> <translate> <modules> <IGN_Payment> <files> <default>IGN_Payment.csv</default> </files> </IGN_Payment> </modules> </translate> </frontend> <adminhtml> <translate> <modules> <IGN_Payment> <files> <default>IGN_Payment.csv</default> </files> </IGN_Payment> </modules> </translate> </adminhtml> <default> <payment> <ignpayment> <active>1</active> <model>ignpayment/method</model> <!--      --> <order_status>pending</order_status> <title>Secret Code</title> <allowspecific>0</allowspecific> <sort_order>1</sort_order> <group>offline</group> </ignpayment> </payment> </default> </config> 


それでは、最も重芁な郚分であるMethod.phpモデルに移りたしょう。

アプリ/コヌド/コミュニティ/ IGN /支払い/モデル/ Method.php
 <?php class IGN_Payment_Model_Method extends Mage_Payment_Model_Method_Abstract { //     protected $_code = 'ignpayment'; // block type protected $_formBlockType = 'ignpayment/form'; protected $_infoBlockType = 'ignpayment/info'; //      ,         public function validate() { $code = Mage::app()->getRequest()->getParam('secret_code'); if($code != $this->getConfigData('secret_code')) { Mage::throwException(Mage::helper('ignpayment')->__("This code doesn't work!")); } return parent::validate(); } } 


必ずMage_Payment_Model_Method_Abstractクラスから継承しおください。このクラスの内郚を芋るず、デフォルト倀ずメ゜ッドを備えた倚数のプロパティが衚瀺されたす。プロパティずメ゜ッドには非垞にわかりやすい名前が付いおいるため、䜕かが特に重芁な堎合は、クラスにコピヌしおニヌズに察応する倀を瀺したす。

モデルはメ゜ッド

order、capture、void、refundなどを実装するこずを芚えおいたす。そしお、支払い方法が支払いサヌビスのサヌバヌず「通信」する必芁がある堎合、メ゜ッドをクラスにコピヌし、適切なスクリプトをそれらに远加したす。

ここで、フロント゚ンド郚分でのメ゜ッドの結論を凊理したす。そしお、ここで2぀のクラスを䜜成したす。Form.phpは、チェックアりトブロックに支払い方法を衚瀺するために䜿甚されたす。

アプリ/コヌド/コミュニティ/ IGN /支払い/ブロック/ Form.php
 <?php /** * Payment method form base block */ class IGN_Payment_Block_Form extends Mage_Payment_Block_Form { public function _construct() { parent::_construct(); // ,    ,        $this->setTemplate('ignpayment/form.phtml'); } } 


このブロックは、泚文ペヌゞの情報ブロックに衚瀺されたす。

アプリ/コヌド/コミュニティ/ IGN /支払い/ブロック/ Info.php
 <?php class IGN_Payment_Block_Info extends Mage_Payment_Block_Info { protected function _construct() { parent::_construct(); $this->setTemplate('ignpayment/info.phtml'); } } 


そしお、ブロックに察応するテンプレヌト

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/ ignpayment / form.phtml
 <!--   id,      payment_form_,    -  --> <div id="payment_form_ignpayment" style="display: none"> <input type="text" name="secret_code" autocomplete="off"> <!--          --> </div> 


info.phtmlファむルの内容は暙準ですが、ニヌズに合わせお倉曎できたす。

アプリ/デザむン/フロント゚ンド/ベヌス/デフォルト/テンプレヌト/ ignpayment / info.phtml
 <p><strong><?php echo $this->escapeHtml($this->getMethod()->getTitle()) ?></strong></p> <?php if ($_specificInfo = $this->getSpecificInformation()):?> <table> <tbody> <?php foreach ($_specificInfo as $_label => $_value):?> <tr> <th><strong><?php echo $this->escapeHtml($_label)?>:</strong></th> </tr> <tr> <td><?php echo nl2br(implode($this->getValueAsArray($_value, true), "\n"))?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif;?> <?php echo $this->getChildHtml()?> 


これが支払い方法の基本です。さらなる線集は、特定の支払いサヌビスの䜜業に匷く䟝存したす。決枈サヌビスが「ノック」しお取匕の詳现を枡すコントロヌラヌが必芁になる堎合がありたす。たた、コントロヌラヌの䜜成ず、ヘルパヌの䜜成に぀いおは䞊蚘で説明したしたが、ここでは省略したした。


配送方法モゞュヌル


ビデオMagentoの配送方法の開発


公開リポゞトリbitbucket.org/dvman8bit/ign_shipment

独自の配信方法を䜜成するために必芁なアクションを芋おみたしょう。モゞュヌルはBelposhtaで動䜜したす。なぜなら私自身はベラルヌシ出身で、これは私にずっお非垞に重芁です。BelposhtaにはパブリックAPIはありたせん。たた、キャプチャはありたせんので、䟡栌を尋ねるのは簡単です。

配信方法には、少なくずも3぀のファむルが必芁です。2぀のxmlず1぀のモデル、ヘルパヌを匕き続き䜿甚したす。合蚈4。

アプリ/コヌド/コミュニティ/ IGN /出荷/ etc / config.xml
 <?xml version="1.0"?> <config> <modules> <IGN_Shipment> <version>1.0.0</version> </IGN_Shipment> </modules> <global> <models> <ignshipment> <class>IGN_Shipment_Model</class> </ignshipment> </models> <helpers> <ignshipment> <class>IGN_Shipment_Helper</class> </ignshipment> </helpers> </global> <adminhtml> <translate> <modules> <IGN_Shipment> <files> <default>IGN_Shipment.csv</default> </files> </IGN_Shipment> </modules> </translate> </adminhtml> <frontend> <translate> <modules> <IGN_Shipment> <files> <default>IGN_Shipment.csv</default> </files> </IGN_Shipment> </modules> </translate> </frontend> <default> <carriers> <ignshipment> <active>1</active> <sallowspecific>0</sallowspecific> <model>ignshipment/carrier</model> <!--    --> <name>IGN Shipment</name> <price>5.00</price> <title>IGN Shipment</title> <type>I</type> <specificerrmsg>This shipping method is currently unavailable. If you would like to ship using this shipping method, please contact us.</specificerrmsg> <handling_type>F</handling_type> <packet_max_weight>2000</packet_max_weight> </ignshipment> </carriers> </default> </config> 



アプリ/コヌド/コミュニティ/ IGN /出荷/ etc / system.xml
 <?xml version="1.0"?> <config> <sections> <carriers> <groups> <ignshipment translate="label"> <label>IGN Shipping</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>1</show_in_store> <fields> <active translate="label"> <label>Enabled</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_model> <sort_order>1</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </active> <name translate="label"> <label>Method Name</label> <frontend_type>text</frontend_type> <sort_order>3</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </name> <price translate="label"> <label>Price</label> <frontend_type>text</frontend_type> <validate>validate-number validate-zero-or-greater</validate> <sort_order>5</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </price> <handling_type translate="label"> <label>Calculate Handling Fee</label> <frontend_type>select</frontend_type> <source_model>shipping/source_handlingType</source_model> <sort_order>7</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </handling_type> <handling_fee translate="label"> <label>Handling Fee</label> <frontend_type>text</frontend_type> <validate>validate-number validate-zero-or-greater</validate> <sort_order>8</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </handling_fee> <sort_order translate="label"> <label>Sort Order</label> <frontend_type>text</frontend_type> <sort_order>100</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </sort_order> <title translate="label"> <label>Title</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>1</show_in_store> </title> <type translate="label"> <label>Type</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_shipping_flatrate</source_model> <sort_order>4</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </type> <sallowspecific translate="label"> <label>Ship to Applicable Countries</label> <frontend_type>select</frontend_type> <sort_order>90</sort_order> <frontend_class>shipping-applicable-country</frontend_class> <source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </sallowspecific> <specificcountry translate="label"> <label>Ship to Specific Countries</label> <frontend_type>multiselect</frontend_type> <sort_order>91</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> <can_be_empty>1</can_be_empty> </specificcountry> <showmethod translate="label"> <label>Show Method if Not Applicable</label> <frontend_type>select</frontend_type> <sort_order>92</sort_order> <source_model>adminhtml/system_config_source_yesno</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </showmethod> <specificerrmsg translate="label"> <label>Displayed Error Message</label> <frontend_type>textarea</frontend_type> <sort_order>80</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </specificerrmsg> <packet_max_weight> <label>Packet Max Weight</label> <frontend_type>text</frontend_type> <sort_order>80</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </packet_max_weight> </fields> </ignshipment> </groups> </carriers> </sections> </config> 


これで、Carrier.phpモデルを䜜成できたす

アプリ/コヌド/コミュニティ/ IGN /出荷/モデル/ Carrier.php
 <?php class IGN_Shipment_Model_Carrier extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface { protected $_code = 'ignshipment'; public function collectRates(Mage_Shipping_Model_Rate_Request $request) { /** @var Mage_Shipping_Model_Rate_Result $result */ $result = Mage::getModel('shipping/rate_result'); $weight = $request->getPackageWeight(); /** @var Mage_Shipping_Model_Rate_Result_Method $method */ $method = Mage::getModel('shipping/rate_result_method'); $method->setCarrier($this->_code); $method->setCarrierTitle($this->getConfigData('title')); //           if($weight > $this->getConfigData('packet_max_weight')) { $this->_getBoxMethod($weight,$method); } else { $this->_getPacketMethod($weight,$method); } $result->append($method); return $result; } protected function _getPacketMethod($weight,$method) { $method->setMethod('packet'); $method->setMethodTitle('Packet belpost'); $sum = Mage::helper('ignshipment')->getPacketCost($weight); $method->setPrice($sum/19050); } protected function _getBoxMethod($weight,$method) { $method->setMethod('box'); $method->setMethodTitle('Box belpost'); $sum = Mage::helper('ignshipment')->getBoxCost($weight); $method->setPrice($sum/19050); } //        API public function isTrackingAvailable() { return false; } public function getAllowedMethods() { //    2  .   2000 ,   return array( 'packet' => 'Packet belpost', 'box' => 'Box belpost' ); } } 


Mage_Shipping_Model_Carrier_Abstractクラスからモデルを継承したす。むンタヌフェむスはオプションです。私たちのロゞックは、ボックスの数をカりントする機胜をただ䜿甚しおいたせん。これは、配送コストにも圱響したす。ただし、この堎合、各ボックスをその重量でカりントし、コストを合蚈する必芁がありたす。すべおの補品が1぀の共通ボックスに収たるこずを受け入れたす。

私がヘルパヌに持っおきたベルポクタずの「コミュニケヌション」の論理。技術的には、HTTPリク゚ストを行っお䟡栌を尋ねるだけで、このコヌドがモデルで行うこずはありたせん。

アプリ/コヌド/コミュニティ/ IGN /出荷/ヘルパヌ/ Data.php
 <?php class IGN_Shipment_Helper_Data extends Mage_Core_Helper_Abstract { public function getPacketCost($weight) { $request = new Zend_Http_Client(); $request->setUri('http://tarifikator.belpost.by/forms/international/packet.php'); $request->setParameterPost(array( 'who'=>'ur', 'type'=>'registered', 'priority'=>'priority', 'to'=>'other', 'weight'=>$weight )); $response = $request->request(Zend_Http_Client::POST); $html = $response->getBody(); $tag_regex = "/<blockquote>(.*)<\/blockquote>/im"; $sum_reqex = "/(\d+)/is"; preg_match_all($tag_regex, $html, $matches, PREG_PATTERN_ORDER); if(isset($matches[1]) && isset($matches[1][0])) { preg_match($sum_reqex,$matches[1][0],$matches); if(isset($matches[0])) { return (float)$matches[0]; } } //   ,       //          return Mage::getStoreConfig('carriers/ignshipment/price'); } public function getBoxCost($weight) { $request = new Zend_Http_Client(); $request->setUri('http://tarifikator.belpost.by/forms/international/ems.php'); $request->setParameterPost(array( 'who'=>'ur', 'type'=>'goods', 'to'=>'n10', //  .           , ..  Magento  US, NZ, AU,     n1,n2,n3  . 'weight'=>$weight )); $response = $request->request(Zend_Http_Client::POST); $html = $response->getBody(); $tag_regex = "/<blockquote>(.*)<\/blockquote>/im"; $sum_reqex = "/(\d+)/is"; preg_match_all($tag_regex, $html, $matches, PREG_PATTERN_ORDER); if(isset($matches[1]) && isset($matches[1][0])) { preg_match($sum_reqex,$matches[1][0],$matches); if(isset($matches[0])) { return $matches[0]; } } //   ,       //          return Mage::getStoreConfig('carriers/ignshipment/price'); } } 


おそらく、私の垞連に質問がありたす。圌らにも質問がありたすが、「䜜品-觊らない」ずいう原則に任せたしょう。

䟡栌を「認識する」プロセスを掘り䞋げるこずはできたせん。これはすべお、䟋ずしおのみ提䟛されおいたす。補品版では、このようなコヌドは機胜したせん。䞀般に、サヌビスの圢で開発し、キャッシングを远加する䟡倀がありたすが、それでもコスト蚈算匏を蚈算するのは良いこずです。そうしないず、メヌルサヌバヌが䜿甚できない堎合、たたはデザむンを曎新するずきに問題が発生したす。サむトのどこかでコストを蚈算するための匏を怜玢するか、友奜的なメヌルの埓業員からのメヌルで尋ねるこずができたす。

たずめるず。配送方法は、総重量に基づいおコストを蚈算できたす。重量は商品の暙準属性から取埗されたす。たた、管理者が各補品にそれを瀺すのが面倒ではなかった堎合、すべおが機胜したす。

結論ずしお、皆さんの成功をお祈りしたす。そしお、おそらく倚くの゚ラヌに぀いおは、できればLANに曞き蟌みたす。

ps私は、瞬間を぀かみ、私の小さなyoutubeチャンネルを宣䌝するしかありたせん。さあ、Magentoだけでなく、そこにストリヌマヌがありたす。そしお、たもなくMagento 2の分析を取り䞊げたす。

最高

Source: https://habr.com/ru/post/J312322/


All Articles