Magento2 エクステンションの作成 その3
Rev.8を表示中。最新版はこちら。
1. 概要
ここではModel関連の以下のクラスを作成する。
- Model
- ResourceModel
- ResourceModel Collection
2. Modelの作成
いわゆるMVCのModelクラスを作成する。今回のエクステンションでは、投稿をbithive_topic_postテーブルで管理するのでPostクラスを作成する。ファイルはModel/Post.phpとして作成する。
Model/Post.php
<?php namespace BitHive\Topic\Model; use Magento\Framework\Model\Context; use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime\TimezoneInterface; class Post extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\DataObject\IdentityInterface { const CACHE_TAG = 'bithive_topic_post'; protected $_cacheTag = 'bithive_topic_post'; protected $_eventPrefix = 'bithive_topic_post'; /** * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface */ protected $timezone; public function __construct( Context $context, Registry $registry, TimezoneInterface $timezone ) { $this->timezone = $timezone; parent::__construct($context, $registry); } protected function _construct() { // ResouceModelのクラス名 $this->_init(\BitHive\Topic\Model\ResourceModel\Post::class); } // IdentityInterfaceのメソッド public function getIdentities() { return [self::CACHE_TAG . '_' . $this->getId()]; } public function beforeSave() { // 更新時のmodifiedを自動設定させるため $this->setData('modified', null); return parent::beforeSave(); } // $this->getData('date') で取得される時刻はUTCなので、 // タイムゾーンを指定して時刻を取得するメソッド // nullの場合はconfigに従う。 public function getConvertedDate($format = 'Y-m-d H:i:s', $tz = null) { $defaultTz = $this->timezone->getDefaultTimezone(); // 'UTC' $configTz = $this->timezone->getConfigTimezone(); // 'Asia/Tokyo' Websiteの設定が参照される $tz = $tz ?: $configTz; $date = $this->getData('date'); // default timezone(UTC)での時刻 $datetime = new \DateTime($date, new \DateTimeZone($defaultTz)); $datetime->setTimezone(new \DateTimeZone($tz)); return $datetime->format($format); } }
Modelは\Magento\Framework\Model\AbstractModelの継承と\Magento\Framework\DataObject\IdentityInterfaceインターフェースの実装が必要になる。以下に実装内容を解説する。
コンストラクタでは対応するResourceModelのクラス名を指定する。ResourceModelとは実際にDBへのアクセスを行うクラスのこと。Magento2ではDBへのアクセス処理はModelから分離されており、ResourceModelを介してDBにアクセスする。例えば、Modelのsave(),load()メソッドを呼び出すと対応するResourceModelのメソッドに転送されて、DBへのRead/Writeが行われる。
protected function _construct()
{
// ResouceModelのクラス名
$this->_init(\BitHive\Topic\Model\ResourceModel\Post::class);
}
次にIdentityInterfaceインターフェースの実装を行う。これはgetIdentities()メソッドを実装するだけでよい。getIdentities()はModel識別用のIDを含んだ配列を返す。通常、IDはModelごとに決めたPrefix文字列(cache_tag。ここでは'bithive_topic_post')とPRIMARY KEY(レコードのID)を組み合わせた文字列を使う。
// IdentityInterfaceのメソッド
public function getIdentities()
{
return [self::CACHE_TAG . '_' . $this->getId()];
}
getIdentities()が返すIDリストはコンテンツのキャッシュ管理に利用される。Magento2ではページ/ブロックを生成する際、そのページ/ブロック内に表示するModelのIdentitiesの一覧を作成し、それをページ/ブロックのIdentitiesとするような実装にする(図1)。Magento2では(FullPageCache機能をOnにしていれば)、ページのキャッシュを作成するが、記事の更新があった際、その記事のIdentitiesを含むキャッシュを探しクリアすることで、必要なキャッシュのみクリアするようになっている(図1)。
図1 Identitiesとキャッシュ
このため、getIdentities()は配列を返すようになっているが、Modelの場合は、一つだけIDを返すようにしておけばよい。
最後に時刻とタイムゾーン関連の説明。
Magento2では越境ECを構築できるため、時刻のカラムは基本的にTIMESTAMP型で持つ。Magento2自体はUTCの設定で動作しているため、DBから取得した時刻をそのまま表示すると、UTCで表示されてしまう。そのため、WebsiteなりStoreなりのタイムゾーン設定を取得/変換する処理が必要になる。getConvertedDate()ではdateカラムの時刻をWebsiteのタイムゾーンに変換し返す。
// $this->getData('date') で取得される時刻はUTCなので、 // タイムゾーンを指定して時刻を取得するメソッド // nullの場合はconfigに従う。 public function getConvertedDate($format = 'Y-m-d H:i:s', $tz = null) { $defaultTz = $this->timezone->getDefaultTimezone(); // 'UTC' $configTz = $this->timezone->getConfigTimezone(); // 'Asia/Tokyo' Websiteの設定が参照される $tz = $tz ?: $configTz; $date = $this->getData('date'); // default timezone(UTC)での時刻 $datetime = new \DateTime($date, new \DateTimeZone($defaultTz)); $datetime->setTimezone(new \DateTimeZone($tz)); return $datetime->format($format); }
3. ResourceModelの作成
Postモデルに対応するResourceModelを作成する。ResourceModelはModelのDBへのアクセス処理部分を担う。ファイルはModel/ResourceModel/Post.phpに作成する。
Model/ResourceModel/Post.php
<?php
namespace BitHive\Topic\Model\ResourceModel;
class Post extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context
)
{
parent::__construct($context);
}
protected function _construct()
{
$this->_init('bithive_topic_post', 'post_id');
}
}
ここでは、最低限の実装で、コンストラクタでテーブル名とIDカラム名を指定するだけでよい。
4. ResourceModel Collectionの作成
CollectionはテーブルからModelのリストを読み込んだり、フィルターしたりするクラス。リポジトリパターンのRepository的な存在。ファイルはModel/ResourceModel/Post/Collection.phpとして作成する。
Model/ResourceModel/Post/Collection.php
<?php
namespace BitHive\Topic\Model\ResourceModel\Post;
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
protected $_idFieldName = 'post_id';
protected $_eventPrefix = 'bithive_topic_post_collection';
protected $_eventObject = 'post_collection';
/**
* Define resource model
*
* @return void
*/
protected function _construct()
{
$this->_init(\BitHive\Topic\Model\Post::class, \BitHive\Topic\Model\ResourceModel\Post::class);
}
}
コンストラクタでModelクラスの名前とResourceModelクラスの名前を指定すればよい。
現時点でTopic配下は以下のようになっている。
./registration.php ./Model/ResourceModel/Post/Collection.php ./Model/ResourceModel/Post.php ./Model/Post.php ./view/adminhtml/templates/posts.phtml ./view/adminhtml/layout/topic_posts_index.xml ./Setup/InstallSchema.php ./Controller/Adminhtml/Posts/Index.php ./etc/module.xml ./etc/adminhtml/menu.xml ./etc/adminhtml/routes.xml
今回はここまで。