Linuxなどのメモ書き

Magento2 エクステンションの作成 その7


1. 概要

Magento2 エクステンションの作成 その6の続き。

前回までで、管理画面側の実装は完了したので、最後に投稿した記事をフロント側に表示する実装を行う。管理画面側の実装と同じように以下の作業を行う。

  • 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

以上。


最終更新 2018/12/11 15:19:40 - kztomita
(2018/12/11 14:52:41 作成)
添付ファイル
topics.jpg - kztomita