Magento2 エクステンションの作成 その7
1. 概要
前回までで、管理画面側の実装は完了したので、最後に投稿した記事をフロント側に表示する実装を行う。管理画面側の実装と同じように以下の作業を行う。
- routeの作成
- コントローラーの作成
- テンプレートの作成
2. Routeの作成
まず、Routeを作成する。フロント側のRouteはetc/frontend/routes.xmlで定義する。
etc/frontend/routes.xml
<?xml version="1.0" ?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> <router id="standard"> <!-- standard routerでは以下のようなURL形式になる。 <store-url>/<store-code>/<front-name>/<controller-name>/<action-name> idは通常frontNameと同じものを指定する。 --> <route frontName="topic" id="topic"> <module name="BitHive_Topic"/> </route> </router> </config>
これは、/topicへのRouteを定義している。
3. コントローラーの作成
次に/topicで記事を作成するためのコントローラーを作成する。routes.xmlで定義したRoute(/topic)のトップで表示するため、コントローラーはController/Index/Index.phpとなる。
Controller/Index/Index.php
<?php namespace BitHive\Topic\Controller\Index; class Index extends \Magento\Framework\App\Action\Action { protected $pageFactory; protected $postFactory; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\View\Result\PageFactory $pageFactory, \BitHive\Topic\Model\PostFactory $postFactory) { $this->pageFactory = $pageFactory; $this->postFactory = $postFactory; return parent::__construct($context); } public function execute() { return $this->pageFactory->create(); } }
このコントローラーはPageFactoryでページデータを作成して返しているだけ。このページのlayoutファイルはview/frontend/layout/topic_index_index.xmlとなる。
4. テンプレートの作成
/topicページのlayoutファイル(topic_index_index.xml)を作成する。
view/frontend/layout/topic_index_index.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <title> Topics </title> </head> <body> <referenceContainer name="content"> <block class="BitHive\Topic\Block\TopicList" template="BitHive_Topic::topic.phtml"/> </referenceContainer> </body> </page>
これはページのコンテンツ部分をtopic.phtmlテンプレートで表示する。また、topic.phtmlに対応する実装として、Block/TopicList.phpを使うように設定している。
投稿一覧を表示するtopic.phtmlテンプレートを作成する。
view/frontend/templates/topic.phtml
<ul> <?php foreach ($this->getPostCollection() as $item) { $dateString = $item['date'] ? ' at ' . $item->getConvertedDate('Y-m-d H:i:s (e)') : ''; echo '<li>' . $item->getMessage() . $dateString . '</li>'; } ?> </ul>
getPostCollection()によりPostモデルのリストを取得し、それを表示しているだけ。getPostCollection()はBlock/TopicList.phpで実装する。dateは例によってUTCなので、Webサイト設定に合わせたタイムゾーンに変換して出力している。
最後にBlockの実装部分(TopicList.php)を作成する。
Block/TopicList.php
<?php namespace BitHive\Topic\Block; class TopicList extends \Magento\Framework\View\Element\Template implements \Magento\Framework\DataObject\IdentityInterface { protected $postFactory; protected $timezone; protected $timezoneHelper; /** * Post Collection * * @var AbstractCollection */ protected $postCollection; public function __construct( \Magento\Framework\View\Element\Template\Context $context, \BitHive\Topic\Model\PostFactory $postFactory, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone, \BitHive\Topic\Helper\Timezone $timezoneHelper ) { $this->postFactory = $postFactory; $this->timezone = $timezone; $this->timezoneHelper = $timezoneHelper; parent::__construct($context); } public function getPostCollection() { $collection = $this->postFactory->create()->getCollection() ->setPageSize(5) ->setOrder('date', 'DESC'); return $collection; } private function _getPostCollection() { if ($this->postCollection === null) { $collection = $this->postFactory->create()->getCollection() ->setPageSize(5) ->setOrder('date', 'DESC'); $this->postCollection = $collection; } return $this->postCollection; } // トピック更新時に自動でキャッシュをクリアさせるために実装。 // // ブロック内に表示するPostモデルのIdentitiesの一覧を返すことで、 // 関連Postモデル更新時に本ブロックを含むページのfull page cacheが // クリアされる。 // キャッシュの更新が不要ならIdentityInterfaceは実装しなくてよい。 // // 参考: app/code/Magento/Catalog/Block/Product/ListProduct.php public function getIdentities() { $identities = []; foreach ($this->_getPostCollection() as $item) { $identities = array_merge($identities, $item->getIdentities()); } return $identities; } }
テンプレートから呼び出すgetPostCollection()を実装している。
getIdentities()では、このブロック内に表示する投稿のIDを全て含めて返す。これにより、このブロック内に表示されている投稿が編集された場合、本ブロックのキャッシュが正常に更新されるようになる。getIdentities()の詳細はMagento2 エクステンションの作成 その3参照のこと。
5. 表示の確認
ここまでで、全ての修正が完了したので/topicにアクセスすれば投稿の一覧が表示されるはず。
図1 投稿一覧の表示
これで、今回のTopicエクステンションの作成は全て完了となります。今回のサンプルエクステンションは以下からもダウンロードできます。
https://github.com/kztomita/magento-module-topic
以上。