Magentoのステップバむステップモゞュヌルの䜜成-初心者向けガむド

Magentoに぀いおはどれくらい曞くのではなく、ただたくさんの質問がありたす;© jeje


Magentoの電子ストアを勉匷しおいるずきに、䟋を䜿甚しおモゞュヌルの䜜成を説明する倚くの蚘事に出䌚いたしたが、ほずんどすべおの蚘事で「これを実行しお実行しおください」ずいう手順が説明されおいたす。 その結果、゚ラヌが発生した堎合、䜕が間違っおいたかを刀断するこずは非垞に難しく、ニヌズに合わせおモゞュヌルを䜜り盎すこずもより困難です。

この蚘事では、DS Newsニュヌスモゞュヌルの䟋を䜿甚しお、各倉曎の説明ずずもにモゞュヌルの䜜成を段階的に瀺したす。DSは名前空間で、Newsはモゞュヌルの名前です。 このモゞュヌル呜名スキヌムは、モゞュヌル名の名前の競合を恐れないために非垞に䟿利です。 構成ファむルで䜿甚される倀ノヌドの名前ずそれらが䜿甚される堎所の説明に特に重点を眮いお説明したす。 私自身は、新しいモゞュヌルを䜜成するずきにこのマニュアルを絶えず䜿甚しおいたす。 デヌタがどこから来たか、どのクラスを継承する必芁があるかなどを芚えおおいおください...それは単に物理的に䞍可胜です。 そしお、ここではすべおが1぀の蚘事にたずめられおいたす。

システムがすでに機胜しおいるこずを考慮しお、Magentoのむンストヌルず商品の充填に぀いおは説明したせん。 ただし、キャッシュが無効になっおいるこずを確認する必芁がありたす システム/キャッシュ管理ペヌゞの管理パネルでキャッシュを無効にできたす-これは、加えられた倉曎をすぐに確認するために必芁です。

ステップ1.システムにモゞュヌルを登録する
最初のステップでは、䜕もしたせんが、システムで考慮される管理パネルに衚瀺される最小限のモゞュヌルを䜜成したす。

  1. ディレクトリ/アプリ/コヌド/ロヌカル/ DS /ニュヌスを䜜成したす
  2. etc / config.xmlファむルを䜜成したす
    <?xml version="1.0" ?> <config> <modules> <DS_News> <version>0.0.1</version> </DS_News> </modules> </config> 

  3. ディレクトリ/ app / etc / modules /に DS_News.xmlファむルを䜜成したす
     <?xml version="1.0" ?> <config> <modules> <DS_News> <active>true</active> <codePool>local</codePool> </DS_News> </modules> </config> 



このディレクトリ構造ずファむルの䜜成の結果、DS_Newsモゞュヌルがシステムに登録されたす。 このモゞュヌルは、[ システム ]、[ 構成 ]、[ 詳现]、[詳现]、[モゞュヌル出力の無効化 ]のパスの䞋にある管理パネルのモゞュヌルのリストで確認できたす。

ステップ1では、ディレクトリ/ app / code / local / DS / Newsが䜜成され 、そこにモゞュヌルのメむンコヌドが栌玍されたすモデル、コントロヌラヌ、ヘルパヌなど。ステップ2では、ディレクトリなどが䜜成され、モゞュヌル構成ファむルが栌玍されたす。メむンの構成ファむルconfig.xmlが䜜成されたすが 、ここではモゞュヌルのバヌゞョンのみが瀺されおいたす。 パラグラフ3では、モゞュヌルはシステムに登録されおいたす。

実際、モゞュヌル登録タスクで最も重芁なのはポむント3です。モゞュヌルディレクトリがない堎合でも、モゞュヌルは管理パネルに衚瀺されたす。 / app / etc / modules /ディレクトリ内のDS_News.xmlファむル名もオプションです-システムをロヌドするずき、このディレクトリからすべおのXMLファむルを解析したす。 これは、盞互接続された耇数のモゞュヌルがむンストヌルされおいる開発䞭に䟿利です。すべおのモゞュヌルを1぀のXMLファむルで指定できたす。

xmlファむル内のDS_Newsモゞュヌルの名前は、 [名前空間ディレクトリ名] _ [モゞュヌルディレクトリ名]の2぀の郚分で構成されおいたす。 この呜名方法に関連しお、ディレクトリ名は文字のみで䜜成するこずをお勧めしたす。たた、倧文字ず小文字の違いを考慮するこずも重芁です。* nixシステムで正垞に動䜜するには、蚭定ファむルのモゞュヌル名がディレクトリ名ず正確に䞀臎する必芁がありたす。

/app/etc/modules/DS_News.xmlファむルは、 activeずcodePoolの 2぀のタグを䜿甚したす。 最初のタグはモゞュヌルの有効化/無効化を担圓し、2番目はディレクトリ/ app / code /内の堎所 コア システムコア、 コミュニティ Magentoコミュニティが開発したモゞュヌルたたはロヌカル 他の開発者が開発したモゞュヌルです。



ステップ2.デヌタベヌスの初期化
ニュヌスモゞュヌルを機胜させるには、ニュヌスを保存するテヌブルを䜜成する必芁がありたす。 Magentoでは、モゞュヌルのむンストヌル時にテヌブルを䜜成/曎新できたす。

  1. sql / dsnews_setup / install-0.0.1.phpファむルを䜜成したす
     <?php die('DS News module setup'); $installer = $this; $installer->startSetup(); $installer->run("CREATE TABLE ds_news_entities ( `news_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `content` TEXT NOT NULL, `created` DATETIME, PRIMARY KEY (`news_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); $installer->endSetup(); 

  2. etc / config.xml構成ファむルにむンストヌル甚のリ゜ヌスを含むセクションを远加したす。
     <?xml version="1.0" ?> <config> <modules> ... </modules> <global> <resources> <dsnews_setup> <setup> <module>DS_News</module> </setup> </dsnews_setup> </resources> </global> </config> 



倉曎が行われた埌、ブラりザでサむトを開くだけです。 DS Newsモゞュヌルのセットアップが衚瀺されたら、すべお問題ありたせん。 少し埌、 install-0.0.1.phpファむルのdieの行をコメントアりトし、ブラりザヌりィンドりを曎新できたす。その埌、モゞュヌルがcore_resourceテヌブルに登録され、 ds_news_entitiesテヌブルがデヌタベヌスに䜜成されたす。

碑文が衚瀺されない堎合、ほずんどの堎合、モゞュヌルはシステムに既にむンストヌルされおいたす。むンストヌルには、SQLマネヌゞャヌを䜿甚しおデヌタベヌスのcore_resourceテヌブルからdsnews_setupリ゜ヌスレコヌドを削陀し、サむトでブラりザヌりィンドりを再曎新する必芁がありたす

 DELETE FROM `core_resource` WHERE `code` = 'dsnews_setup'; 


config.xmlのdsnews_setupノヌド名は任意です。 䞻なこずは、このノヌドの名前が、むンストヌルするファむルが眮かれるディレクトリの名前ず䞀臎するこずです。 たた、このノヌドの名前は、システム内で䞀意である必芁がありたす。 この名前は、むンストヌルされおいるすべおのリ゜ヌスを栌玍するcore_resourceテヌブルのプラむマリキヌずしお䜿甚されたす。

むンストヌルディレクトリ内のファむルの名前は、特定の構造に察応しおいる必芁がありたす。 むンストヌルファむルの堎合はinstall- [version]。[Php | sql]で、曎新ファむルの堎合はupgrade- [version-from]-[version-to]。[Php | sql]です。 Mage_Core_Model_Resource_Setupクラスを調べるず、リ゜ヌスのむンストヌル、ファむルおよびディレクトリの呜名のプロセスに関する詳现を確認できたす。



ステップ3. config.xmlからテヌブル名を取埗する
このモゞュヌルでは将来、デヌタベヌスずの連携がモデルずコレクションを通じお行われるため、テヌブルの名前はむンストヌルファむルではなく、構成ファむルに保存する必芁がありたす。 これを行うには、 etc / config.xmlファむルず、 sql / dsnews_setup / install-0.0.1.phpむンストヌルファむルを倉曎する必芁がありたす。

  1. etc / config.xmlファむルにモデルノヌドconfig / global / models /を䜜成したす
     <?xml version="1.0" ?> <config> ... <global> <models> <dsnews> <resourceModel>dsnews_resource</resourceModel> </dsnews> <dsnews_resource> <entities> <table_news> <table>ds_news_entities</table> </table_news> </entities> </dsnews_resource> </models> <resources> ... </resources> </global> </config> 

  2. sql / dsnews_setup / install-0.0.1.phpファむルを線集したす
     <?php $installer = $this; $tableNews = $installer->getTable('dsnews/table_news'); die($tableNews); $installer->startSetup(); $installer->getConnection()->dropTable($tableNews); $table = $installer->getConnection() ->newTable($tableNews) ->addColumn('news_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( 'identity' => true, 'nullable' => false, 'primary' => true, )) ->addColumn('title', Varien_Db_Ddl_Table::TYPE_TEXT, '255', array( 'nullable' => false, )) ->addColumn('content', Varien_Db_Ddl_Table::TYPE_TEXT, null, array( 'nullable' => false, )) ->addColumn('created', Varien_Db_Ddl_Table::TYPE_DATETIME, null, array( 'nullable' => false, )); $installer->getConnection()->createTable($table); $installer->endSetup(); 



ブラりザにds_news_entities テヌブルの名前が衚瀺されたら、すべおが正しく行われおいたす-dieで行を削陀し、りィンドりを曎新しおモゞュヌルのむンストヌルを完了できたす。 それ以倖の堎合は、SQLマネヌゞャヌを䜿甚しおcore_resourceテヌブルからモゞュヌルリ゜ヌスレコヌドを削陀する必芁がありたす。

 DELETE FROM `core_resource` WHERE `code` = 'dsnews_setup'; 


このテヌブルが前の段階で䜜成された堎合にSQL゚ラヌが発生するのを防ぐために、既存のテヌブルを事前に削陀するためのコヌドがむンストヌルファむルに远加されたした。 たた、同じテヌブルを䜜成するためのコヌドが抜象に倉曎されたした。テヌブルは抜象接続クラスを䜿甚しお䜜成され、MySQL以倖のデヌタベヌスをさらにサポヌトできるようになりたす。

dsnewsモデルノヌドの名前、 および config / global / models /にあるdsnews_resourceモデルリ゜ヌスノヌドの名前は任意です。 唯䞀の芁件は、システムの他のモデル/リ゜ヌス間のノヌド名の䞀意性です。

段萜2のむンストヌラヌコヌド内では、関数の$ installer-> getTable 'dsnews / table_news'を䜿甚しおテヌブルの名前が芁求されたす。この関数は文字列を匕数ずしお受け取りたす
[モデルノヌドの名前] / [リ゜ヌスの゚ンティティノヌドの名前] Magentoロゞックによるず、デヌタベヌスずの䜎レベルの察話はリ゜ヌスモデルを䜿甚しお行われるため、モデルノヌド自䜓にはテヌブルの名前は保存されたせん。 このため、モデルはresourceModelタグのリ゜ヌスモデルのノヌドぞのリンクのみを保存したす。



ステップ4.フロント゚ンドを介しおモゞュヌルにアクセスする
次に、サむトに「Hello World」ずいう碑文を衚瀺したす。

  1. フロント゚ンドセクションをetc / config.xml構成ファむルに远加したす
     <?xml version="1.0" ?> <config> <modules> ... </modules> <frontend> <routers> <dsnews> <use>standard</use> <args> <module>DS_News</module> <frontName>news</frontName> </args> </dsnews> </routers> </frontend> <global> ... </global> </config> 

  2. ファむルコントロヌラヌの䜜成/ IndexController.php
     <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { echo '<h1>News</h1>'; } } 



これで、「 http://site.com/news/ 」で「News」ずいう単語が衚瀺されたす。

config / frontend / routers /セクションにあるdsnewsノヌドの名前は任意です。 唯䞀の芁件は、システムの他のルヌタヌ間での名前の䞀意性です。 より重芁なのは、 frontNameノヌドの倀です。この倀は、芁求凊理䞭に目的のモゞュヌルを決定するために䜿甚されたす。

パスは、 http// [site] / [router] / [controller] / [action]のように定矩されたす。 芁求する堎合、 [action]たたは[controller] / [action]のペアを省略できたす。その埌、欠萜しおいるパラメヌタヌの代わりに、デフォルト倀のむンデックスが䜿甚されたす。 したがっお、パスhttp://site.com/news/、http://site.com/news/index/、http://site.com/news/index/indexは同等です-DS Newsモゞュヌル、コントロヌラヌにアクセスしたすIndexControllerおよびindexActionアクション。



ステップ5.テンプレヌトを䜿甚しおデヌタを出力する
情報はコントロヌラで盎接生成できたす。たたは、特別なテンプレヌトを䜿甚しお、プログラムロゞックから衚瀺ロゞックを分離できたす。

  1. テンプレヌトファむルを䜜成する/app/design/frontend/[package†/[theme†/template/ds_news/index.phtml
     <h1>Template ds_news/index.phtml</h1> 

  2. ペヌゞレむアりト構成ファむルを䜜成する/app/design/frontend/[packageapter/[theme†/layout/ds_news.xml
     <?xml version="1.0" ?> <layout> <dsnews_index_index> <reference name="content"> <block type="core/template" template="ds_news/index.phtml" /> </reference> </dsnews_index_index> </layout> 

  3. etc / config.xml構成ファむルにレむアりトセクションを远加したす
     <?xml version="1.0" ?> <config> <modules> ... </modules> <frontend> <layout> <updates> <dsnews> <file>ds_news.xml</file> </dsnews> </updates> </layout> <routers> ... </routers> </frontend> <global> ... </global> </config> 

  4. コントロヌラヌコントロヌラヌの倉曎/ IndexController.php
     <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $this->loadLayout(); $this->renderLayout(); } } 



これで、パスhttp://site.com/news/に沿っお、すべおのブロックヘッダヌ、フッタヌ、サむドバヌでサむトペヌゞが開き、サむトのコンテンツに「テンプレヌトds_news / index.phtml」が衚瀺されたす。

すべおのテンプレヌトはテンプレヌトディレクトリに保存され、ペヌゞレむアりト蚭定は珟圚のテヌマディレクトリ/ app / design / frontend / [package] / [theme]に保存されたす。 Magentoで䜜業する堎合、Magentoのバヌゞョンを曎新するずきに基本テヌマのコンテンツが䞊曞きされる可胜性があるため、基本テヌマ/アプリ/デザむン/フロント゚ンド/ベヌス/および/アプリ/デザむン/フロント゚ンド/デフォルト/のコンテンツに觊れるこずなく、独自のテヌマを䜜成する必芁がありたす。

コントロヌラヌアクションでペヌゞレむアりト$ this-> loadLayoutを初期化するず、ペヌゞレむアりトレむアりトが順番に読み蟌たれ、互いに倉曎される可胜性がありたす。 デフォルトでは、デフォルトのハンドルが最初にロヌドされ、最埌の1぀は[router] _ [controller] _ [action]ずいう名前のハンドルです 。 [router]はconfig / frontend / routers / [router]ノヌドの名前です。

節2は、コントロヌラヌ/アクションのレむアりトハンドルを定矩したす  dsnews_index_index 、その内郚に組み蟌みのコア/テンプレヌトタむプのブロックが䜜成され、節1で䜜成されたdsnews / index.phtmlテンプレヌトが䜜成されたす。節3では、 config / frontend / layout / sectionが構成ファむルに远加されたすupdatesは、テヌマの初期化時に適甚される曎新ファむルを指定したす。

テヌマのレむアりトにそれほど倚くの倉曎がなく、モゞュヌルを他のプロゞェクトに実装する予定がない堎合、 レむアりトハンドルをファむル/app/design/frontend/[packageapter/[theme†/layout/local.xmlに配眮できたす。
すべおの曎新埌に垞にロヌドされたす-このファむルをconfig.xmlモゞュヌル構成ファむルに登録する必芁はありたせん

レむアりトハンドルの正しい名前を決定するのが困難な堎合、コントロヌラヌで䜿甚されるハンドルのリストを芋るこずができたす。
 <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $this->loadLayout(); $layoutHandles = $this->getLayout()->getUpdate()->getHandles(); echo '<pre>' . print_r($layoutHandles, true) . '</pre>'; } } 

その結果、次のような結論を確認できたす。
配列
 
     [0] =>デフォルト
     [1] => STORE_default
     [2] => THEME_frontend_ [パッケヌゞ] _ [テヌマ]
     [3] => dsnews_index_index
     [4] => customer_logged_out
 




ステップ6.デヌタベヌスからニュヌスを盎接衚瀺する
この段階で、デヌタベヌスから盎接デヌタを䜿甚しお、テンプレヌトにニュヌスを衚瀺するこずができたす。 これを行うには、最初にいく぀かのテストニュヌスをデヌタベヌスに远加する必芁がありたす。

  1. 衚瀺するテストニュヌスをデヌタベヌスに远加したす。
     INSERT INTO `ds_news_entities` VALUES (NULL, 'News 1', 'News 1 Content', '2013-10-16 17:45'), (NULL, 'News 2', 'News 2 Content', '2013-11-07 04:12'), (NULL, 'News 3', 'News 3 Content', '2014-01-12 15:55'); 

  2. テンプレヌトを倉曎したす/app/design/frontend/[package†/[theme†/template/dsnews/index.phtml
     <h1>News</h1> <?php $news = Mage::registry('news'); foreach ($news as $item) { echo '<h2>' . $item['title'] . '</h2>'; } 

  3. コントロヌラヌコントロヌラヌの倉曎/ IndexController.php
     <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $resource = Mage::getSingleton('core/resource'); $read = $resource->getConnection('core_read'); $table = $resource->getTableName('dsnews/table_news'); $select = $read->select() ->from($table, array('news_id', 'title', 'content', 'created')) ->order('created DESC'); $news = $read->fetchAll($select); Mage::register('news', $news); $this->loadLayout(); $this->renderLayout(); } } 



この䟋は、デヌタベヌスからのデヌタの盎接リク゚ストず、 Mage ::レゞストリレゞストリを䜿甚しおコントロヌラからテンプレヌトにニュヌスを転送するこずを瀺しおいたす。 レゞストリは、コヌドのどの郚分でもグロヌバルに利甚可胜であり、たれに、困難な状況で最も最適な゜リュヌションです。

レゞストリを䜿甚するこず、およびグロヌバル倉数を䜿甚するこずは、䜎品質コヌドの兆候ず芋なされたす。 デヌタベヌスぞの盎接アクセスも掚奚されたせん。これは、コヌドの互換性ず移怍性の朜圚的な問題だからです。 次のセクションで説明するモデルやコレクションなどのオブゞェクトを操䜜するために、システム自䜓が提䟛する機胜を䜿甚するこずをお勧めしたす。



ステップ7.モデルの䜜成ず䜿甚
Magentoおよび他の倚くのOOPシステムのロゞックによれば、デヌタの取埗および保存の方法を考慮せずに、オブゞェクト/モデルおよびコレクションのレベルでデヌタ凊理を実行する必芁がありたす。 デヌタの取埗ず保存の操䜜は、リ゜ヌスモデルに䞋䜍レベルずしお残されたす-その埌、デヌタの保存方法デヌタベヌス、ファむルなどを倉曎する堎合、凊理ロゞックを倉曎する必芁はありたせんが、リ゜ヌスモデルを倉曎するだけで、デヌタの受信ず保存に埓事。 モデルを䜿甚しおニュヌス出力をやり盎し、IDによるニュヌスコンテンツの出力も远加したす。

  1. 構成ファむル内のモデルノヌドにクラスノヌドを远加したす。
     <?xml version="1.0" ?> <config> <modules> ... </modules> <frontend> ... </frontend> <global> <models> <dsnews> <class>DS_News_Model</class> <resourceModel>dsnews_resource</resourceModel> </dsnews> <dsnews_resource> <class>DS_News_Model_Resource</class> <entities> <table_news> <table>ds_news_entities</table> </table_news> </entities> </dsnews_resource> </models> <resources> ... </resources> </global> </config> 

  2. ニュヌスモデルファむルモデルの䜜成/ News.php
     <?php class DS_News_Model_News extends Mage_Core_Model_Abstract { public function _construct() { parent::_construct(); $this->_init('dsnews/news'); } } 

  3. ニュヌスモデルリ゜ヌスファむルモデルの䜜成/リ゜ヌス/News.php
     <?php class DS_News_Model_Resource_News extends Mage_Core_Model_Mysql4_Abstract { public function _construct() { $this->_init('dsnews/table_news', 'news_id'); } } 

  4. コレクションリ゜ヌスファむルを䜜成するModel / Resource / News / Collection.php
     <?php class DS_News_Model_Resource_News_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract { public function _construct() { parent::_construct(); $this->_init('dsnews/news'); } } 

  5. コントロヌラヌコントロヌラヌの倉曎/ IndexController.php
     <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $news = Mage::getModel('dsnews/news')->getCollection()->setOrder('created', 'DESC'); $viewUrl = Mage::getUrl('news/index/view'); echo '<h1>News</h1>'; foreach ($news as $item) { echo '<h2><a href="' . $viewUrl . '?id=' . $item->getId() . '">' . $item->getTitle() . '</a></h2>'; } } public function viewAction() { $newsId = Mage::app()->getRequest()->getParam('id', 0); $news = Mage::getModel('dsnews/news')->load($newsId); if ($news->getId() > 0) { echo '<h1>' . $news->getTitle() . '</h1>'; echo '<div class="content">' . $news->getContent() . '</div>'; } else { $this->_forward('noRoute'); } } } 



これで、リンクhttp://site.com/newsをクリックするず、ニュヌスの内容を含むペヌゞが開くリンクをクリックするず、リンクの圢でニュヌスのリストが開きたす。

ステップ1では、 クラスノヌドが構成ファむルに远加され、 DS_News_ModelモデルずDS_News_Model_Resourceリ゜ヌスの基本的なクラスプレフィックスが登録されたす。

コントロヌラヌアむテム5のモデルを芁求するずき、 Mage :: getModel 'dsnews / news' 、 getModel関数は、モデルクラス名の圢成元である[model] / [class]型の文字列を受け入れたす。 [model]は構成ノヌドの名前です/ global / models / [model] 、 クラスノヌドの倀の取埗元-DS_News_Model 、および倀[class]がこのクラスプレフィックスに远加されたす各単語[class]の最初の文字は倧文字に倉換されたす。 たずえば、 DS_News_Model_Newsクラスはdsnews / news 行から取埗され、 DS_News_Model_News_Galleryクラスはdsnews / news_gallery 行から取埗されたす。

節2では、基本的なDS_News_Model_Newsニュヌスモデルが䜜成され 、そのコンストラクタヌでリ゜ヌス$ this-> _ init 'dsnews / news'が初期化されたすパラメヌタヌずしお、関数は文字列[model] / [class]を取りたす。 [model]はノヌドの名前ですconfig / global / models / [model] 、および[class]はクラスの名前です。 ただし、モデルずは異なり、リ゜ヌスクラスをクラスプレフィックスずしお初期化するには、 resourceModelノヌドのモデルによっお参照されるリ゜ヌスのconfig / global / models / [resourceModel] / classノヌドの倀を䜿甚したす。 その結果、リ゜ヌス$ this-> _ init 'dsnews / news'を初期化するずきに、 DS_News_Model_Resource_Newsクラスが初期化されたす。

ステップ3では、リ゜ヌスクラスDS_News_Model_Resource_Newsが䜜成されたす。 このクラスでは、テヌブル$ this-> _ init 'dsnews / table_news'、 'news_id'が初期化されたす 。最初のパラメヌタヌは目的のテヌブルの名前ぞのパスで、2番目は䞻キヌずしお䜿甚されるフィヌルドです䞻キヌテヌブル。

節4では、オブゞェクトコレクションクラスが初期化され、そのコンストラクタヌで初期モデルDS_News_Model_Newsが初期化されたす。

パラグラフ5では、デヌタベヌスからのデヌタの受信に倉曎がありたす。 今回は、モデルずコレクションが䜿甚されたす。 indexActionアクションでは、すべおのニュヌスは$ news = Mage :: getModel 'dsnews / news'-> getCollectioncollectionを取埗するこずで芁求されたす。 コレクションクラスの名前は、モデルDS_News_Model_Resource_News + _Collectionのリ゜ヌスクラスの名前から蚈算されたす。

viewActionアクションでは、リク゚ストで受信したIDによっおニュヌスがダりンロヌドされたす。 このIDのニュヌスが存圚する堎合、ニュヌスずコンテンツの名前が衚瀺されたす。 それ以倖の堎合、ペヌゞ404が生成されたす。



ステップ8.ブロックの䜜成ず䜿甚
Magentoは、デヌタを出力するために特別なブロックを䜿甚したす-これらは、コヌドの特定のセクションをレンダリングするコヌドオブゞェクトです。 ステップ5デヌタ出力甚のテンプレヌトの䜿甚では、暙準のコア/テンプレヌトブロックが䜿甚されたした。 このステップでは、ニュヌスのリストずコンテンツを衚瀺するために、ニュヌスモゞュヌル甚のブロックが䜜成されたす。

  1. ブロックノヌド構成/グロヌバル/ブロックを远加
     <?xml version="1.0" ?> <config> ... <global> <blocks> <dsnews> <class>DS_News_Block</class> </dsnews> </blocks> ... </global> </config> 

  2. ニュヌスリストブロッククラスBlock / News.phpを䜜成する
     <?php class DS_News_Block_News extends Mage_Core_Block_Template { public function getNewsCollection() { $newsCollection = Mage::getModel('dsnews/news')->getCollection(); $newsCollection->setOrder('created', 'DESC'); return $newsCollection; } } 

  3. ニュヌスコンテンツブロッククラスBlock / View.phpを䜜成する
     <?php class DS_News_Block_View extends Mage_Core_Block_Template { } 

  4. 構成ファむルの曎新/app/design/frontend/[package†/[theme†/layout/ds_news.xml
     <layout> <dsnews_index_index> <reference name="content"> <block type="dsnews/news" template="ds_news/index.phtml" /> </reference> </dsnews_index_index> <dsnews_index_view> <reference name="content"> <block type="dsnews/view" name="news.content" template="ds_news/view.phtml" /> </reference> </dsnews_index_view> </layout> 

  5. テンプレヌトファむルを線集したす/app/design/frontend/[package†/[theme†/template/ds_news/index.phtml
     <?php $news = $this->getNewsCollection(); $newsViewUrl = Mage::getUrl('news/index/view'); ?> <h1>News</h1> <?php foreach ($news as $item): ?> <h2> <a href="<?php echo $newsViewUrl; ?>?id=<?php echo $item->getId(); ?>"> <?php echo $item->getTitle(); ?> </a> </h2> <?php endforeach; ?> 

  6. テンプレヌトファむルを䜜成したす/app/design/frontend/[packageapter/[theme†/template/ds_news/view.phtml
     <h1><?php echo $newsItem->getTitle(); ?></h1> <div class="content"><?php echo $newsItem->getContent(); ?></div> 

  7. コントロヌラヌコントロヌラヌの倉曎/ IndexController.php
     <?php class DS_News_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { $this->loadLayout(); $this->renderLayout(); } public function viewAction() { $newsId = Mage::app()->getRequest()->getParam('id', 0); $news = Mage::getModel('dsnews/news')->load($newsId); if ($news->getId() > 0) { $this->loadLayout(); $this->getLayout()->getBlock('news.content')->assign(array( "newsItem" => $news, )); $this->renderLayout(); } else { $this->_forward('noRoute'); } } } 



ペヌゞhttp://site.com/news/を開くず、サむトペヌゞのコンテンツずしおニュヌスリストが衚瀺され、ニュヌスリンクをクリックするず、ニュヌスコンテンツのあるペヌゞが開きたす。

ブロックメカニズムにより、コントロヌラヌに関係なく衚瀺ロゞックを䜿甚できたす。 パラグラフ3からわかるように、 indexActionアクションはテンプレヌトのロヌドず衚瀺のみを凊理するようになりたした。 ニュヌスを受信するためのロゞックはDS_News_Block_Newsブロックにあり、衚瀺ロゞックは/app/design/frontend/[package†/[theme†/template/dsnews/index.phtmlテンプレヌトにありたす。 したがっお、たずえば、最近のニュヌスのリストを他のペヌゞのサむドバヌに衚瀺する必芁がある堎合は、コントロヌラヌを䜿甚せずに目的のブロックをペヌゞに接続するだけで十分です。

$this , / - .

1 , Magento . , (type) .xml . type [module]/[block] , [module] — config/global/blocks/[module] , class ; a [block] — . type=«dsnews/news» DS_News_Block_News .

4 <reference name=«content» . , , . layout handle dsnews_index_view , <block type=«dsnews/view» name=«news.content» template=«ds_news/view.phtml» /> . viewAction assign , . .



ステップ9.モゞュヌルの管理パネルを䜜成する
, , - . .

  1. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction() { echo '<h1>News Module: Admin section</h1>'; } } 

  2. etc/config.xml
     <?xml version="1.0" ?> <config> ... <admin> <routers> <dsnews_admin> <use>admin</use> <args> <module>DS_News</module> <frontName>dsnews_admin</frontName> </args> </dsnews_admin> </routers> </admin> ... </config> 

  3. , etc/config.xml
     <?xml version="1.0" ?> <config> ... <adminhtml> <menu> <dsnews module="dsnews"> <title>News</title> <sort_order>77</sort_order> <action>dsnews_admin/adminhtml_news</action> </dsnews> </menu> </adminhtml> ... </config> 

  4. - Helper/Data.php
     <?php class DS_News_Helper_Data extends Mage_Core_Helper_Abstract { } 

  5. etc/config.xml
     <?xml version="1.0" ?> <config> ... <global> ... <helpers> <dsnews> <class>DS_News_Helper</class> </dsnews> </helpers> ... </global> ... </config> 



, , News , «News Module: Admin section» .

1 , 2 — config/admin/routers/[router] . , http://site.com/index.php/[frontName]/[controller]/index/ , [frontName] — config/admin/routers/[router]/args/[frontName] , [controller] — , DS_News + [controller] + Controller . adminhtml_news DS_News_Adminhtml_NewsController . http://site.com/index.php/dsnews_admin/adminhtml_news/index/ .

, Magento - . , . 3 , .

4 5, , «Warning: include(Mage\DS\News\Helper\Data.php): failed to open stream: No such file or directory...» . Magento , module config/adminhtml/menu/[menu] . config/global/helpers/[helper] , . 4 5 -, .

, — frontName config/admin/routers config/frontend/routers .
( ), , HTTPS .



ステップ10.管理パネルでブロックを䜿甚する
. .

  1. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout(); $this->_setActiveMenu('dsnews'); $contentBlock = $this->getLayout()->createBlock('dsnews/adminhtml_news'); $this->_addContent($contentBlock); $this->renderLayout(); } } 

  2. Block/Adminhtml/News.php
     <?php class DS_News_Block_Adminhtml_News extends Mage_Adminhtml_Block_Abstract { public function _toHtml() { return '<h1>News Module: Admin section</h1>'; } } 



Magento , frontend ( ), backend () . .xml / ( 5: « »), , - Magento, . HTML « » . , /app/design/adminhtml/default/default/ , , .. .

1 $this->loadLayout() . $this->getLayout() : // . createBlock [module]/[block] , <block type="[module]/[block]" ; .



ステップ11.デヌタグリッドにリストする
, .

  1. Block/Adminhtml/News.php
     <?php class DS_News_Block_Adminhtml_News extends Mage_Adminhtml_Block_Widget_Grid_Container { protected function _construct() { parent::_construct(); $helper = Mage::helper('dsnews'); $this->_blockGroup = 'dsnews'; $this->_controller = 'adminhtml_news'; $this->_headerText = $helper->__('News Management'); $this->_addButtonLabel = $helper->__('Add News'); } } 

  2. Block/Adminhtml/News/Grid.php
     <?php class DS_News_Block_Adminhtml_News_Grid extends Mage_Adminhtml_Block_Widget_Grid { protected function _prepareCollection() { $collection = Mage::getModel('dsnews/news')->getCollection(); $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { $helper = Mage::helper('dsnews'); $this->addColumn('news_id', array( 'header' => $helper->__('News ID'), 'index' => 'news_id' )); $this->addColumn('title', array( 'header' => $helper->__('Title'), 'index' => 'title', 'type' => 'text', )); $this->addColumn('created', array( 'header' => $helper->__('Created'), 'index' => 'created', 'type' => 'date', )); return parent::_prepareColumns(); } } 



, 1 DS_News_Block_Adminhtml_News : [_blockGroup]/[_controller]_grid , _blockGroup — config/global/blocks/[_blockGroup] . «dsnews/adminhtml_news_grid» .

_prepareColumns , . addColumn , — , index — , type — . Mage_Adminhtml_Block_Widget_Grid_Column .



手順12.デヌタグリッドでの䞀括操䜜


  1. Block/Adminhtml/News/Grid.php _prepareMassaction
     <?php class DS_News_Block_Adminhtml_News_Grid extends Mage_Adminhtml_Block_Widget_Grid { protected function _prepareCollection(){ ... } protected function _prepareColumns(){ ... } protected function _prepareMassaction() { $this->setMassactionIdField('news_id'); $this->getMassactionBlock()->setFormFieldName('news'); $this->getMassactionBlock()->addItem('delete', array( 'label' => $this->__('Delete'), 'url' => $this->getUrl('*/*/massDelete'), )); return $this; } } 

  2. massDeleteAction controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function massDeleteAction() { $news = $this->getRequest()->getParam('news', null); if (is_array($news) && sizeof($news) > 0) { try { foreach ($news as $id) { Mage::getModel('dsnews/news')->setId($id)->delete(); } $this->_getSession()->addSuccess($this->__('Total of %d news have been deleted', sizeof($news))); } catch (Exception $e) { $this->_getSession()->addError($e->getMessage()); } } else { $this->_getSession()->addError($this->__('Please select news')); } $this->_redirect('*/*'); } } 



. , Actions Delete Submit .

1 _prepareMassaction , id- news_id , , id-. — , , . : . , . Mage_Adminhtml_Block_Catalog_Product_Grid .



ステップ13. CRUD远加、線集、削陀
,

  1. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction() { $this->loadLayout()->_setActiveMenu('dsnews'); $this->_addContent($this->getLayout()->createBlock('dsnews/adminhtml_news')); $this->renderLayout(); } public function newAction() { $this->_forward('edit'); } public function editAction() { $id = (int) $this->getRequest()->getParam('id'); Mage::register('current_news', Mage::getModel('dsnews/news')->load($id)); $this->loadLayout()->_setActiveMenu('dsnews'); $this->_addContent($this->getLayout()->createBlock('dsnews/adminhtml_news_edit')); $this->renderLayout(); } public function saveAction() { if ($data = $this->getRequest()->getPost()) { try { $model = Mage::getModel('dsnews/news'); $model->setData($data)->setId($this->getRequest()->getParam('id')); if(!$model->getCreated()){ $model->setCreated(now()); } $model->save(); Mage::getSingleton('adminhtml/session')->addSuccess($this->__('News was saved successfully')); Mage::getSingleton('adminhtml/session')->setFormData(false); $this->_redirect('*/*/'); } catch (Exception $e) { Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setFormData($data); $this->_redirect('*/*/edit', array( 'id' => $this->getRequest()->getParam('id') )); } return; } Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find item to save')); $this->_redirect('*/*/'); } public function deleteAction() { if ($id = $this->getRequest()->getParam('id')) { try { Mage::getModel('dsnews/news')->setId($id)->delete(); Mage::getSingleton('adminhtml/session')->addSuccess($this->__('News was deleted successfully')); } catch (Exception $e) { Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); $this->_redirect('*/*/edit', array('id' => $id)); } } $this->_redirect('*/*/'); } public function massDeleteAction(){ ... } } 

  2. getRowUrl Block/Adminhtml/News/Grid.php
     <?php class DS_News_Block_Adminhtml_News_Grid extends Mage_Adminhtml_Block_Widget_Grid { protected function _prepareCollection(){ ... } protected function _prepareColumns(){ ... } protected function _prepareMassaction(){ ... } public function getRowUrl($model) { return $this->getUrl('*/*/edit', array( 'id' => $model->getId(), )); } } 

  3. Block/Adminhtml/News/Edit.php
     <?php class DS_News_Block_Adminhtml_News_Edit extends Mage_Adminhtml_Block_Widget_Form_Container { protected function _construct() { $this->_blockGroup = 'dsnews'; $this->_controller = 'adminhtml_news'; } public function getHeaderText() { $helper = Mage::helper('dsnews'); $model = Mage::registry('current_news'); if ($model->getId()) { return $helper->__("Edit News item '%s'", $this->escapeHtml($model->getTitle())); } else { return $helper->__("Add News item"); } } } 

  4. Block/Adminhtml/News/Edit/Form.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { $helper = Mage::helper('dsnews'); $model = Mage::registry('current_news'); $form = new Varien_Data_Form(array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save', array( 'id' => $this->getRequest()->getParam('id') )), 'method' => 'post', 'enctype' => 'multipart/form-data' )); $this->setForm($form); $fieldset = $form->addFieldset('news_form', array('legend' => $helper->__('News Information'))); $fieldset->addField('title', 'text', array( 'label' => $helper->__('Title'), 'required' => true, 'name' => 'title', )); $fieldset->addField('content', 'editor', array( 'label' => $helper->__('Content'), 'required' => true, 'name' => 'content', )); $fieldset->addField('created', 'date', array( 'format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT), 'image' => $this->getSkinUrl('images/grid-cal.gif'), 'label' => $helper->__('Created'), 'name' => 'created' )); $form->setUseContainer(true); if($data = Mage::getSingleton('adminhtml/session')->getFormData()){ $form->setValues($data); } else { $form->setValues($model->getData()); } return parent::_prepareForm(); } } 



Data Grid , Add News — .

1 new , edit , save delete , . new edit , new edit . , ( , ), . save
$model->setData($data)->setId(...) — , .. , setData . , .

2 Data Grid — . 3 , , [_blockGroup]/[_controller]_[_mode]_form , dsnews/adminhtml_news_edit_form ( _mode edit ).

. , new Varien_Data_Form id HTML id , .. JavaScript-, . , name .



ステップ14.タブを䜿甚する
, TAB-.

  1. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function newAction(){ ... } public function editAction() { $id = (int) $this->getRequest()->getParam('id'); $model = Mage::getModel('dsnews/news'); if($data = Mage::getSingleton('adminhtml/session')->getFormData()){ $model->setData($data)->setId($id); } else { $model->load($id); } Mage::register('current_news', $model); $this->loadLayout()->_setActiveMenu('dsnews'); $this->_addLeft($this->getLayout()->createBlock('dsnews/adminhtml_news_edit_tabs')); $this->_addContent($this->getLayout()->createBlock('dsnews/adminhtml_news_edit')); $this->renderLayout(); } public function saveAction(){ ... } public function deleteAction() { ... } public function massDeleteAction(){ ... } } 

  2. Block/Adminhtml/News/Edit/Tabs.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { public function __construct() { $helper = Mage::helper('dsnews'); parent::__construct(); $this->setId('news_tabs'); $this->setDestElementId('edit_form'); $this->setTitle($helper->__('News Information')); } protected function _prepareLayout() { $helper = Mage::helper('dsnews'); $this->addTab('general_section', array( 'label' => $helper->__('General Information'), 'title' => $helper->__('General Information'), 'content' => $this->getLayout()->createBlock('dsnews/adminhtml_news_edit_tabs_general')->toHtml(), )); $this->addTab('custom_section', array( 'label' => $helper->__('Custom Fields'), 'title' => $helper->__('Custom Fields'), 'content' => $this->getLayout()->createBlock('dsnews/adminhtml_news_edit_tabs_custom')->toHtml(), )); return parent::_prepareLayout(); } } 

  3. Block/Adminhtml/News/Edit/Form.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Form extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { $form = new Varien_Data_Form(array( 'id' => 'edit_form', 'action' => $this->getUrl('*/*/save', array( 'id' => $this->getRequest()->getParam('id') )), 'method' => 'post', 'enctype' => 'multipart/form-data' )); $form->setUseContainer(true); $this->setForm($form); return parent::_prepareForm(); } } 

  4. General Block/Adminhtml/News/Edit/Tabs/General.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs_General extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { $helper = Mage::helper('dsnews'); $model = Mage::registry('current_news'); $form = new Varien_Data_Form(); $fieldset = $form->addFieldset('general_form', array( 'legend' => $helper->__('General Information') )); $fieldset->addField('title', 'text', array( 'label' => $helper->__('Title'), 'required' => true, 'name' => 'title', )); $fieldset->addField('content', 'editor', array( 'label' => $helper->__('Content'), 'required' => true, 'name' => 'content', )); $fieldset->addField('created', 'date', array( 'format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT), 'image' => $this->getSkinUrl('images/grid-cal.gif'), 'label' => $helper->__('Created'), 'name' => 'created' )); $form->setValues($model->getData()); $this->setForm($form); return parent::_prepareForm(); } } 

  5. Custom
    Block/Adminhtml/News/Edit/Tabs/Custom.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs_Custom extends Mage_Adminhtml_Block_Widget { protected function _toHtml() { return '<h2>Custom Fields</h2>'; } } 



. 2 — , — . , General, .

, , . 2 - , _prepareLayout . . , General $form = new Varien_Data_Form() , , — .



ステップ15.画像アップロヌドフィヌルドを远加する
.

  1. General Block/Adminhtml/News/Edit/Tabs/General.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs_General extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { $helper = Mage::helper('dsnews'); $model = Mage::registry('current_news'); $form = new Varien_Data_Form(); $fieldset = $form->addFieldset('general_form', array('legend' => $helper->__('General Information'))); $fieldset->addField('title', 'text', array( 'label' => $helper->__('Title'), 'required' => true, 'name' => 'title', )); $fieldset->addField('content', 'editor', array( 'label' => $helper->__('Content'), 'required' => true, 'name' => 'content', )); $fieldset->addField('image', 'image', array( 'label' => $helper->__('Image'), 'name' => 'image', )); $fieldset->addField('created', 'date', array( 'format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT), 'image' => $this->getSkinUrl('images/grid-cal.gif'), 'label' => $helper->__('Created'), 'name' => 'created' )); $formData = array_merge($model->getData(), array('image' => $model->getImageUrl())); $form->setValues($formData); $this->setForm($form); return parent::_prepareForm(); } } 

  2. Helper/Data.php
     <?php class DS_News_Helper_Data extends Mage_Core_Helper_Abstract { public function getImagePath($id = 0) { $path = Mage::getBaseDir('media') . '/ds_news'; if ($id) { return "{$path}/{$id}.jpg"; } else { return $path; } } public function getImageUrl($id = 0) { $url = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'ds_news/'; if ($id) { return $url . $id . '.jpg'; } else { return $url; } } } 

  3. Model/News.php
     <?php class DS_News_Model_News extends Mage_Core_Model_Abstract { protected function _construct() { parent::_construct(); $this->_init('dsnews/news'); } protected function _afterDelete() { $helper = Mage::helper('dsnews'); @unlink($helper->getImagePath($this->getId())); return parent::_afterDelete(); } public function getImageUrl() { $helper = Mage::helper('dsnews'); if ($this->getId() && file_exists($helper->getImagePath($this->getId()))) { return $helper->getImageUrl($this->getId()); } return null; } } 

  4. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function newAction(){ ... } public function editAction(){ ... } public function saveAction() { $id = $this->getRequest()->getParam('id'); if ($data = $this->getRequest()->getPost()) { try { $helper = Mage::helper('dsnews'); $model = Mage::getModel('dsnews/news'); $model->setData($data)->setId($id); if (!$model->getCreated()) { $model->setCreated(now()); } $model->save(); $id = $model->getId(); if (isset($_FILES['image']['name']) && $_FILES['image']['name'] != '') { $uploader = new Varien_File_Uploader('image'); $uploader->setAllowedExtensions(array('jpg', 'jpeg')); $uploader->setAllowRenameFiles(false); $uploader->setFilesDispersion(false); $uploader->save($helper->getImagePath(), $id . '.jpg'); // Upload the image } else { if (isset($data['image']['delete']) && $data['image']['delete'] == 1) { @unlink($helper->getImagePath($id)); } } Mage::getSingleton('adminhtml/session')->addSuccess($this->__('News was saved successfully')); Mage::getSingleton('adminhtml/session')->setFormData(false); $this->_redirect('*/*/'); } catch (Exception $e) { Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setFormData($data); $this->_redirect('*/*/edit', array( 'id' => $id )); } return; } Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find item to save')); $this->_redirect('*/*/'); } public function deleteAction(){ ... } public function massDeleteAction(){ ... } } 



JPG, . /media/ds_news , , . — URL , , — . , — image : $formData = array_merge($model->getData(), array('image' => $model->getImageUrl())) .



ステップ16.管理パネルでJavaScript / CSSファむルを接続する


  1. /skin/adminhtml/default/default/ds_news/adminhtml/scripts.js
     console.log('DS News admin'); 

  2. /skin/adminhtml/default/default/ds_news/adminhtml/styles.css
     #general_form label { color: #FF0000; font-weight: bold; } 

  3. controllers/Adminhtml/NewsController.php
     <?php class DS_News_Adminhtml_NewsController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function newAction(){ ... } public function editAction() { $id = (int) $this->getRequest()->getParam('id'); $model = Mage::getModel('dsnews/news'); if ($data = Mage::getSingleton('adminhtml/session')->getFormData()) { $model->setData($data)->setId($id); } else { $model->load($id); } Mage::register('current_news', $model); $this->loadLayout()->_setActiveMenu('dsnews'); $this->getLayout()->getBlock('head')->addItem('skin_js', 'ds_news/adminhtml/scripts.js'); $this->getLayout()->getBlock('head')->addItem('skin_css', 'ds_news/adminhtml/styles.css'); $this->_addLeft($this->getLayout()->createBlock('dsnews/adminhtml_news_edit_tabs')); $this->_addContent($this->getLayout()->createBlock('dsnews/adminhtml_news_edit')); $this->renderLayout(); } public function saveAction(){ ... } public function deleteAction(){ ... } public function massDeleteAction(){ ... } } 



DS News admin , .

, , , : JS, . — /skin/adminhtml/default/default/ /js/ — . , , /js/ , — .

, /js/ /js/
 $this->getLayout()->getBlock('head')->addItem('skin_js', 'ds_news/adminhtml/scripts.js'); $this->getLayout()->getBlock('head')->addItem('skin_css', 'ds_news/adminhtml/styles.css'); 

 $this->getLayout()->getBlock('head')->addJs('ds_news/adminhtml/scripts.js'); $this->getLayout()->getBlock('head')->addItem('js_css', 'ds_news/adminhtml/styles.css'); 




ステップ17.モゞュヌルの曎新ニュヌスのカテゎリヌの远加
— : . , .

  1. sql/dsnews_setup/upgrade-0.0.1-0.0.2.php
     <?php echo '<h1>Upgrade DS News to version 0.0.2</h1>'; exit; $installer = $this; $tableCategories = $installer->getTable('dsnews/table_categories'); $tableNews = $installer->getTable('dsnews/table_news'); $installer->startSetup(); $installer->getConnection()->dropTable($tableCategories); $table = $installer->getConnection() ->newTable($tableCategories) ->addColumn('category_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( 'identity' => true, 'nullable' => false, 'primary' => true, )) ->addColumn('title', Varien_Db_Ddl_Table::TYPE_TEXT, '255', array( 'nullable' => false, )); $installer->getConnection()->createTable($table); $installer->getConnection()->addColumn($tableNews, 'category_id', array( 'comment' => 'News Category', 'default' => '0', 'nullable' => false, 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER, )); $installer->endSetup(); 

  2. etc/config.xml
     <?xml version="1.0" ?> <config> <modules> <DS_News> <version>0.0.2</version> </DS_News> </modules> ... <global> ... <models> <dsnews> <class>DS_News_Model</class> <resourceModel>dsnews_resource</resourceModel> </dsnews> <dsnews_resource> <class>DS_News_Model_Resource</class> <entities> <table_categories> <table>ds_news_categories</table> </table_categories> <table_news> <table>ds_news_entities</table> </table_news> </entities> </dsnews_resource> </models> ... </global> </config> 

  3. Model/Category.php
     <?php class DS_News_Model_Category extends Mage_Core_Model_Abstract { protected function _construct() { parent::_construct(); $this->_init('dsnews/category'); } protected function _afterDelete() { $newsCollection = Mage::getModel('dsnews/news')->getCollection() ->addFieldToFilter('category_id', $this->getId()); foreach($newsCollection as $news){ $news->setCategoryId(0)->save(); } return parent::_afterDelete(); } } 

  4. Block/Adminhtml/News/Edit/Tabs/General.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs_General extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { ... $fieldset->addField('category_id', 'select', array( 'label' => $helper->__('Category'), 'name' => 'category_id', 'values' => $helper->getCategoriesOptions(), )); ... } } 

  5. Helper/Data.php ,
     <?php class DS_News_Helper_Data extends Mage_Core_Helper_Abstract { public function getImagePath($id = 0){ ... } public function getImageUrl($id = 0){ ... } public function getCategoriesList() { $categories = Mage::getModel('dsnews/category')->getCollection()->load(); $output = array(); foreach($categories as $category){ $output[$category->getId()] = $category->getTitle(); } return $output; } public function getCategoriesOptions() { $categories = Mage::getModel('dsnews/category')->getCollection()->load(); $options = array(); $options[] = array( 'label' => '', 'value' => '' ); foreach ($categories as $category) { $options[] = array( 'label' => $category->getTitle(), 'value' => $category->getId(), ); } return $options; } } 

  6. Block/News/Grid.php
     <?php class DS_News_Block_Adminhtml_News_Grid extends Mage_Adminhtml_Block_Widget_Grid { protected function _prepareCollection(){ ... } protected function _prepareColumns() { $helper = Mage::helper('dsnews'); $this->addColumn('news_id', array( 'header' => $helper->__('News ID'), 'index' => 'news_id', 'width' => '100px', )); $this->addColumn('title', array( 'header' => $helper->__('Title'), 'index' => 'title', 'type' => 'text', )); $this->addColumn('category', array( 'header' => $helper->__('Category'), 'index' => 'category_id', 'options' => $helper->getCategoriesList(), 'type' => 'options', 'width' => '150px', )); $this->addColumn('created', array( 'header' => $helper->__('Created'), 'index' => 'created', 'type' => 'date', )); return parent::_prepareColumns(); } protected function _prepareMassaction(){ ... } public function getRowUrl($model){ ... } } 

  7. etc/config.xml
     <?xml version="1.0" ?> <config> ... <adminhtml> <menu> <dsnews module="dsnews"> <title>News</title> <sort_order>77</sort_order> <children> <dsnews_news translate="title" module="dsnews"> <title>News</title> <sort_order>10</sort_order> <action>dsnews_admin/adminhtml_news</action> </dsnews_news> <dsnews_category translate="title" module="dsnews"> <title>Categories</title> <sort_order>20</sort_order> <action>dsnews_admin/adminhtml_category</action> </dsnews_category> </children> </dsnews> </menu> </adminhtml> ... </config> 



«Upgrade DS News to version 0.0.2», — . core_resource — dsnews_setup 0.0.1 . , , comment , .

, , . , . , , . / — Magento ( /var/cache ), .. Magento !



ステップ18.タブでのデヌタグリッドの衚瀺
,

  1. Model/Category.php
     <?php class DS_News_Model_Category extends Mage_Core_Model_Abstract { protected function _construct(){ ... } protected function _afterDelete() { foreach($this->getNewsCollection() as $news){ $news->setCategoryId(0)->save(); } return parent::_afterDelete(); } public function getNewsCollection() { $collection = Mage::getModel('dsnews/news')->getCollection(); $collection->addFieldToFilter('category_id', $this->getId()); return $collection; } } 

  2. Block/Adminhtml/Category/Edit/Tabs/News.php
     <?php class DS_News_Block_Adminhtml_Category_Edit_Tabs_News extends Mage_Adminhtml_Block_Widget_Grid { public function __construct() { parent::__construct(); $this->setId('categoryNewsGrid'); $this->setUseAjax(true); } protected function _prepareCollection() { $collection = Mage::registry('current_category')->getNewsCollection(); $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { $helper = Mage::helper('dsnews'); $this->addColumn('ajax_grid_news_id', array( 'header' => $helper->__('News ID'), 'index' => 'news_id', 'width' => '100px', )); $this->addColumn('ajax_grid_title', array( 'header' => $helper->__('Title'), 'index' => 'title', 'type' => 'text', )); $this->addColumn('ajax_grid_created', array( 'header' => $helper->__('Created'), 'index' => 'created', 'type' => 'date', )); return parent::_prepareColumns(); } public function getGridUrl() { return $this->getUrl('*/*/news', array('_current' => true)); } } 

  3. Block/Adminhtml/Category/Edit/Tabs.php
     <?php class DS_News_Block_Adminhtml_Category_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { public function __construct(){ ... } protected function _prepareLayout() { $helper = Mage::helper('dsnews'); $this->addTab('general_section', array( 'label' => $helper->__('General Information'), 'title' => $helper->__('General Information'), 'content' => $this->getLayout()->createBlock('dsnews/adminhtml_category_edit_tabs_general')->toHtml(), )); $this->addTab('news_section', array( 'class' => 'ajax', 'label' => $helper->__('News'), 'title' => $helper->__('News'), 'url' => $this->getUrl('*/*/news', array('_current' => true)), )); return parent::_prepareLayout(); } } 

  4. controllers/Adminhtml/CategoryController.php ,
     <?php class DS_News_Adminhtml_CategoryController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function newAction(){ ... } public function editAction(){ ... } public function saveAction(){ ... } public function deleteAction(){ ... } public function newsAction() { $id = (int) $this->getRequest()->getParam('id'); $model = Mage::getModel('dsnews/category')->load($id); Mage::register('current_category', $model); if (Mage::app()->getRequest()->isAjax()) { $this->loadLayout(); echo $this->getLayout()->createBlock('dsnews/adminhtml_category_edit_tabs_news')->toHtml(); } } } 



, «News». , . , , , 3:
 <?php class DS_News_Block_Adminhtml_Category_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { public function __construct(){ ... } protected function _prepareLayout() { $helper = Mage::helper('dsnews'); $category = Mage::registry('current_category'); $this->addTab('general_section', array( 'label' => $helper->__('General Information'), 'title' => $helper->__('General Information'), 'content' => $this->getLayout()->createBlock('dsnews/adminhtml_category_edit_tabs_general')->toHtml(), )); if($category->getId()){ $this->addTab('news_section', array( 'class' => 'ajax', 'label' => $helper->__('News'), 'title' => $helper->__('News'), 'url' => $this->getUrl('*/*/news', array('_current' => true)), )); } return parent::_prepareLayout(); } } 


, , 2 $this->setId('categoryNewsGrid') , JavaScript , , JavaScript (, ).

ajax_grid_ 2. , , .

, - , ajax ( ) /, . getGridUrl -. array('_current' => true) , , , id .



ステップ19.デヌタグリッドで遞択したレコヌドを保存する
, / . , . , -, . , - . Mage_Adminhtml_Block_Widget_Grid_Serializer .

  1. Block/Adminhtml/Category/Edit/Tabs/News.php
     <?php class DS_News_Block_Adminhtml_Category_Edit_Tabs_News extends Mage_Adminhtml_Block_Widget_Grid { public function __construct() { parent::__construct(); $this->setDefaultFilter(array('ajax_grid_in_category' => 1)); $this->setId('categoryNewsGrid'); $this->setSaveParametersInSession(false); $this->setUseAjax(true); } protected function _prepareCollection() { $collection = Mage::getModel('dsnews/news')->getCollection(); $this->setCollection($collection); return parent::_prepareCollection(); } protected function _prepareColumns() { $helper = Mage::helper('dsnews'); $this->addColumn('ajax_grid_in_category', array( 'align' => 'center', 'header_css_class' => 'a-center', 'index' => 'news_id', 'type' => 'checkbox', 'values' => $this->getSelectedNews(), )); $this->addColumn('ajax_grid_news_id', array( 'header' => $helper->__('News ID'), 'index' => 'news_id', 'width' => '100px', )); $this->addColumn('ajax_grid_title', array( 'header' => $helper->__('Title'), 'index' => 'title', 'type' => 'text', )); $this->addColumn('ajax_grid_created', array( 'header' => $helper->__('Created'), 'index' => 'created', 'type' => 'date', )); return parent::_prepareColumns(); } protected function _addColumnFilterToCollection($column) { if ($column->getId() == 'ajax_grid_in_category') { $collection = $this->getCollection(); $selectedNews = $this->getSelectedNews(); if ($column->getFilter()->getValue()) { $collection->addFieldToFilter('news_id', array('in' => $selectedNews)); } elseif (!empty($selectedNews)) { $collection->addFieldToFilter('news_id', array('nin' => $selectedNews)); } } else { parent::_addColumnFilterToCollection($column); } return $this; } public function getGridUrl() { return $this->getUrl('*/*/news', array('_current' => true, 'grid_only' => 1)); } public function getSelectedNews() { if (!isset($this->_data['selected_news'])) { $selectedNews = Mage::app()->getRequest()->getParam('selected_news', null); if(is_null($selectedNews) || !is_array($selectedNews)){ $category = Mage::registry('current_category'); $selectedNews = $category->getNewsCollection()->getAllIds(); } $this->_data['selected_news'] = $selectedNews; } return $this->_data['selected_news']; } } 

  2. controllers/Adminhtml/CategoryController.php
     <?php class DS_News_Adminhtml_CategoryController extends Mage_Adminhtml_Controller_Action { public function indexAction(){ ... } public function newAction(){ ... } public function editAction(){ ... } public function saveAction() { $categoryId = $this->getRequest()->getParam('id'); if ($data = $this->getRequest()->getPost()) { try { $helper = Mage::helper('dsnews'); $model = Mage::getModel('dsnews/category'); $model->setData($data)->setId($categoryId); $model->save(); $categoryId = $model->getId(); $categoryNews = $model->getNewsCollection()->getAllIds(); if ($selectedNews = $this->getRequest()->getParam('selected_news', null)) { $selectedNews = Mage::helper('adminhtml/js')->decodeGridSerializedInput($selectedNews); } else { $selectedNews = array(); } $setCategory = array_diff($selectedNews, $categoryNews); $unsetCategory = array_diff($categoryNews, $selectedNews); foreach($setCategory as $id){ Mage::getModel('dsnews/news')->setId($id)->setCategoryId($categoryId)->save(); } foreach($unsetCategory as $id){ Mage::getModel('dsnews/news')->setId($id)->setCategoryId(0)->save(); } Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Category was saved successfully')); Mage::getSingleton('adminhtml/session')->setFormData(false); $this->_redirect('*/*/'); } catch (Exception $e) { Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); Mage::getSingleton('adminhtml/session')->setFormData($data); $this->_redirect('*/*/edit', array( 'id' => $categoryId )); } return; } Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find item to save')); $this->_redirect('*/*/'); } public function deleteAction(){ ... } public function newsAction() { $id = (int) $this->getRequest()->getParam('id'); $model = Mage::getModel('dsnews/category')->load($id); $request = Mage::app()->getRequest(); Mage::register('current_category', $model); if ($request->isAjax()) { $this->loadLayout(); $layout = $this->getLayout(); $root = $layout->createBlock('core/text_list', 'root', array('output' => 'toHtml')); $grid = $layout->createBlock('dsnews/adminhtml_category_edit_tabs_news'); $root->append($grid); if (!$request->getParam('grid_only')) { $serializer = $layout->createBlock('adminhtml/widget_grid_serializer'); $serializer->initSerializerBlock($grid, 'getSelectedNews', 'selected_news', 'selected_news'); $root->append($serializer); } $this->renderLayout(); } } } 



1, ajax_grid_in_category , / , ( / / ). _prepareCollection , _addColumnFilterToCollection . $this->setDefaultFilter(array('ajax_grid_in_category' => 1)); ( ). getSelectedNews , . , , POST- ( ), — .

. . $root = $layout->createBlock(...) root , . , , , . .

initSerializerBlock , . 4 : , , ( ), , getSelectedNews .



ステップ20.矎しいURLを䜿甚する
— , HTML/CSS . — . , . . , , , .

  1. sql/dsnews_setup/upgrade-0.0.2-0.0.3.php
     <?php echo '<h1>Upgrade DS News to version 0.0.3</h1>'; exit; $installer = $this; $tableNews = $installer->getTable('dsnews/table_news'); $installer->startSetup(); $installer->getConnection() ->addColumn($tableNews, 'link', array( 'comment' => 'News URL link', 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, 'length' => '255', 'nullable' => true, )); $installer->getConnection() ->addKey($tableNews, 'IDX_UNIQUE_NEWS_LINK', 'link', Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE); foreach (Mage::getModel('dsnews/news')->getCollection() as $news) { try { $news->load($news->getId())->setDataChanges(true)->save(); } catch (Exception $e) { $news->setId($news->getId())->setLink($news->getId())->save(); } } $installer->endSetup(); 

  2. etc/config.xml
     <?xml version="1.0" ?> <config> <modules> <DS_News> <version>0.0.3</version> </DS_News> </modules> ... </config> 

  3. Helper/Data.php
     <?php class DS_News_Helper_Data extends Mage_Core_Helper_Abstract { public function getImagePath($id = 0){ ... } public function getImageUrl($id = 0){ ... } public function getCategoriesList(){ ... } public function getCategoriesOptions(){ ... } public function prepareUrl($url) { return trim(preg_replace('/-+/', '-', preg_replace('/[^a-z0-9]/sUi', '-', strtolower(trim($url)))), '-'); } } 

  4. Model/News.php
     <?php class DS_News_Model_News extends Mage_Core_Model_Abstract { protected function _construct(){ ... } protected function _afterDelete(){ ... } protected function _beforeSave() { $helper = Mage::helper('dsnews'); if (!$this->getData('link')) { $this->setData('link', $helper->prepareUrl($this->getTitle())); } else { $this->setData('link', $helper->prepareUrl($this->getData('link'))); } return parent::_beforeSave(); } public function getImageUrl(){ ... } } 

  5. Block/Adminhtml/News/Edit/Tabs/General.php
     <?php class DS_News_Block_Adminhtml_News_Edit_Tabs_General extends Mage_Adminhtml_Block_Widget_Form { protected function _prepareForm() { ... $fieldset->addField('link', 'text', array( 'label' => $helper->__('Link'), 'name' => 'link', )); ... } } 

  6. etc/config.xml
     <?xml version="1.0" ?> <config> ... <global> ... <events> <controller_front_init_routers> <observers> <dsnews> <class>DS_News_Controller_Router</class> <method>initControllerRouters</method> </dsnews> </observers> </controller_front_init_routers> </events> ... </global> </config> 

  7. Controller/Router.php
     <?php class DS_News_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract { public function initControllerRouters($observer) { $front = $observer->getEvent()->getFront(); $front->addRouter('dsnews', $this); } public function match(Zend_Controller_Request_Http $request) { $identifier = trim($request->getPathInfo(), '/'); $cmd = explode('/', $identifier); if ($cmd[0] == 'news') { if (count($cmd) == 1) { return $this->_fillRequest($request); } else { $model = Mage::getModel('dsnews/news')->load($cmd[1], 'link'); if ($model->getId()) { $params = array( 'id' => $model->getId() ); return $this->_fillRequest($request, $params, 'index', 'view'); } } } return false; } protected function _fillRequest($request, $cmd = array(), $controller = 'index', $action = 'index') { $request->setModuleName('news') ->setControllerName($controller) ->setActionName($action) ->setParam('is_routed', 1); if (is_array($cmd) && count($cmd)) { foreach ($cmd as $key => $value) { $request->setParam($key, $value); } } $request->setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, $request->getPathInfo()); return true; } } 



Upgrade DS News to version 0.0.3 , — , Magento ( ). 1 5 — : . 7, 6 . http://site.com/news/{news-link}

. controller_front_init_routers , $this : $front->addRouter('dsnews', $this) . Mage_Core_Controller_Varien_Router_Abstract , match . , , . match , URL. , . true , , false . _fillRequest — , .

, _fillRequest $request->setModuleName('news') frontName config.xml ( frontend/routers/[module Name]/args/frontName ), .

, , .



各ステップの゜ヌスコヌドはこちらから入手できたす。


䟋のコヌドを曎新するため、テキスト内のコヌドがアヌカむブのコヌドず䞀臎しない堎合や、コヌドが意図したずおりに機胜しない堎合がありたす。コヌドの䞍正確さや違いに気づいたら、PMで䜜者にメッセヌゞを曞いおください。

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


All Articles