Movable Typeに追加した独自オブジェクトをダイナミックパブリッシングで出力する方法

Movable Typeに追加した独自オブジェクトをダイナミックパブリッシングで出力する方法

Posted at October 28,2013 1:23 AM
Tag:[Developer, MovableType, Plugin]

Movable Typeに追加した独自オブジェクトをダイナミックパブリッシングで出力する方法を紹介します。

このエントリーは「Movable Typeに独自オブジェクトを追加する方法」の続きで、「Event」プラグインで「mt_event」というテーブルを定義し、定義したテーブルのデータに対してMTEventsタグとMTEventTitleタグを定義し、ダイナミックパブリッシングで次のテンプレートグの内容を出力できるようにします。

<mt:Events>
    <$mt:EventTitle$>
</mt:Events>

1.プラグインの構成

ダイナミックパブリッシング用のプラグインを作成するには、元記事の1項に示したディレクトリ構成に「php」ディレクトリを追加し、その配下に赤色で示した3つのファイルを追加します。

plugins
 └ Event
   ├ config.yaml
   ├ lib
   │ └ MT
   │   └ Event.pm
   └ php
     ├ class.mt_event.php
     ├ block.mtevents.php
     └ function.mteventtitle.php

追加した3つのファイルの意味は次の通りです。

  • class.mt_event.php:mt_eventテーブルの定義
  • block.mtevents.php:ブロックタグMTEventsの実装
  • function.mteventtitle.php:ファンクションタグMTEventTitleの実装

ファンクションタグは定義しているフィールドに応じて適宜追加してください。

また、スタティックパブリッシング用として、config.yamlにテンプレートタグの定義が必要です。詳細は6項を参照してください。

2.class.mt_event.php

class.mt_event.phpでダイナミックパブリッシング用に動作するようテーブルを定義します。

<?php
require_once("class.baseobject.php");
 
class Event extends BaseObject
{
    public $_table = 'mt_event';
    protected $_prefix = "event_";
    protected $_has_meta = true;
}
ADODB_Active_Record::ClassHasMany(
    'Event', 'mt_event_meta',
    'event_meta_event_id');	
?>

新しく追加したEventクラスはBaseObject(class.baseobject.php)を必ず継承してください。

class Event extends BaseObject
{
}

$_tableにテーブル名を定義します。

    public $_table = 'mt_event';

$_prefixにテーブルのプレフィックスを定義します。

    protected $_prefix = "event_";

$_has_metaにメタテーブルの有無を定義します。

    protected $_has_meta = true;

最後にメタデータを利用する場合の設定を行います。

ADODB_Active_Record::ClassHasMany(
    'Event', 'mt_event_meta',
    'event_meta_event_id');	

3.block.mtevents.php

block.mtevents.phpに次の内容を設定します。

<?php
function smarty_block_mtevents($args, $content, &$ctx, &$repeat) {
    $localvars = array('event', '_events', '_events_counter', 'blog_id');
    if (!isset($content)) {
        $ctx->localize($localvars);
        $args['blog_id'] = $ctx->stash('blog_id');
        if (isset($args['blog_id'])) {
            $blog_filter = 'and event_blog_id = ' . intval($args['blog_id']);
        }
        $where = "1 = 1
                  $blog_filter
                  order by event_title";
        require_once('class.mt_event.php');
        $event = new Event;
        $events = $event->Find($where);
        $ctx->stash('_events', $events);
        $counter = 0;
    } else {
        $events = $ctx->stash('_events');
        $counter = $ctx->stash('_events_counter');
    }
    if ($counter < count($events)) {
        $event = $events[$counter];
        $ctx->stash('event', $event);
        $ctx->stash('_events_counter', $counter + 1);
        $repeat = true;
    } else {
        $ctx->restore($localvars);
        $repeat = false;
    }
    return $content;
}
?>

ダイナミックパブリッシングのブロックタグの基本的な構造は上記と同じですが、今回は独自オブジェクトなので、MTに実装されているfetch系のAPIの代わりに、追加したクラス定義をそのまま利用します(以下の部分)。

        $args['blog_id'] = $ctx->stash('blog_id');
        if (isset($args['blog_id'])) {
            $blog_filter = 'and event_blog_id = ' . intval($args['blog_id']);
        }
        $where = "1 = 1
                  $blog_filter
                  order by event_title";
        require_once('class.mt_event.php');
        $event = new Event;
        $events = $event->Find($where);

下から3行目で定義したクラスclass.mt_event.phpを読み込みます。

        require_once('class.mt_event.php');

Eventオブジェクトを作成します。

        $event = new Event;

Eventオブジェクトに対してFind()を実行します。Findはclass.mt_event.php継承したBaseObjectに定義されたAPIで、このAPIでデータベースのデータを取得します。

        $events = $event->Find($where);

Findのパラメータには、SQLとなる変数$whereを設定します(1~7行目)。

        $args['blog_id'] = $ctx->stash('blog_id');
        if (isset($args['blog_id'])) {
            $blog_filter = 'and event_blog_id = ' . intval($args['blog_id']);
        }
        $where = "1 = 1
                  $blog_filter
                  order by event_title";

ここではblog_idとevent_titleでソートするように設定しています。この部分は必要に応じて適宜変更してください。

4.function.mteventtitle.php

function.mteventtitle.phpに次の内容を設定します。

<?php
function smarty_function_mteventtitle($args, &$ctx) {
    $event = $ctx->stash('event');
    return $event->event_title;
}
?>

コンテキストからstashに保存されたeventを取得します。

    $event = $ctx-&gt;stash('event');

取得した$eventには1レコード分のデータが入っているので、あとはフィールドを指定して返却すればOKです。

    return $event-&gt;event_title;

他のフィールド用のファンクションタグを作る場合は、ファイル名と関数名を変更し、以下の赤色部分を該当するフィールド名にしてください。

    return $event->event_title;

5.メタデータについて

元記事で追加したテーブルにはメタデータを使う定義をしていないので、メタデータを使っていない場合は、ADODB_Active_Record::ClassHasManyの3行の設定は不要です。

ADODB_Active_Record::ClassHasMany(
    'Event', 'mt_event_meta',
    'event_meta_event_id');	

また、$_has_metaもfalseを設定しておくといいでしょう。

    protected $_has_meta = false;

なお独自テーブルでメタデータを利用する設定を行うには、lib/MT/Event.pmに次の1行を追加してください。

    …前略…
    datasource => 'event',
    primary_key => 'id',
    meta => 1,
    …後略…

メタデータを定義していないのにADODB_Active_Record::ClassHasManyの定義を行って、ダイナミックパブリッシングでアクセスすると次のようなエラーが出力されるので注意してください(mt-config.cgiにDebugMode 1を設定)。

ページが見つかりません。
 
    <p><b>Error:</b> pdo error: [-1: Invalid table name: mt_event_meta] in ADODB_Active_Record::UpdateActiveTable(0, 0) <br></p><pre>#0 /home/user/htdocs/mt/php/extlib/adodb5/adodb-active-record.inc.php(496): adodb_throw() #1 /home/user/htdocs/mt/php/extlib/adodb5/adodb-active-record.inc.php(390): ADODB_Active_Record->Error('pdo', 'ADODB_Active_Re...', -1, 'Invalid table n...', 0, 0, Object(ADODB_pdo)) #2 /home/user/htdocs/mt/php/extlib/adodb5/adodb-active-record.inc.php(136): ADODB_Active_Record->UpdateActiveTable('Invalid table n...', 'UpdateActiveTab...') #3 /home/user/htdocs/mt/php/extlib/adodb5/adodb-active-record.inc.php(200): ADODB_Active_Record->__construct(false) #4 /home/user/htdocs/mt/php/extlib/adodb5/adodb-active-record.inc.php(230): ADODB_Active_Record->hasMany('mt_event_meta') #5 /home/user/htdocs/mt/plugins/Event/php/class.mt_event.php(14): ADODB_Active_Record::ClassHasMany('mt_event_meta', 'event_meta_even...', 'ADODB_Active_Re...') #6 /home/user/htdocs/mt/plugins/Event/php/block.mtevents.php(18): require_once('/home/user/htdocs...') #7 /home/user/htdocs/mt/website/blog/templates_c/%%B2^B21^B21484EB%%mt%3A247.php(12): smarty_block_mtevents('Event', 'mt_event_meta', 'event_meta_even...') #8 /home/user/htdocs/mt/php/extlib/smarty/libs/Smarty.class.php(1265): include('/home/user/htdocs...') #9 /home/user/htdocs/mt/php/mt.php(650): Smarty->fetch(Array, NULL, Object(MTViewer), true) #10 /home/user/htdocs/mt/website/blog/mtview.php(5): MT->view('mt:247', '4;/mt/fi...') #11 {main}</pre>

6.スタティックパブリッシングの対応

5項までの設定ではテンプレートにMTEventsタグを設定した時点で「タグがみつかりません」というエラーになります。

これはconfig.yamlにテンプレートタグの定義を行っていないためです。

よってconfig.yamlにテンプレートタグの定義を行います。たとえば、lib/Event/Tag.pmに実装するのであれば次のように記述し、lib/Event/Tag.pmにhdlr_eventsとhdlr_event_titleを実装する必要があります。

id: Event
name: Event
description: This is event object.
version: 1.00
schema_version: 1.0
object_types:
    event: MT::Event
tags:
    block:
        Events: $Event::Event::Tags::hdlr_events
    function:
        EventTitle: $Event::Event::Tags::hdlr_event_title

ただし、スタティックパブリッシング用の拡張テンプレートタグの実装が必要ないのであれば、以下の赤色部分のように記述しておくとよいでしょう。

id: Event
name: Event
description: This is event object.
version: 1.00
schema_version: 1.3
object_types:
    event: MT::Event
tags:
    block:
        Events: sub {}
    function:
        EventTitle: sub {}

7.参考サイト

この記事は以下のスライドを参考にさせて頂きました。ありがとうございました。

Phpで作るmovable typeプラグイン from Yuji Takayama

関連記事
zenback
人気エントリー
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)