T4-データベースを使う

ブロックタイプのプラグインは、Maharaデータベース中に独自のテーブルを持つことができる。例えば、今回の SimpleClock に、「あなたが最後にこのページを訪れたのは YYYY年MM月DD日です」などという表示をしたいと考えよう。そのためには、このブロックが表示されるたびに

  1. 閲覧しているユーザを取得
  2. 現在時刻を取得
  3. ユーザIDと現在時刻を記録する

という処理をして記録しておく必要がある。表示する際には、この記録処理の前に前回の記録を読み込んできてやればよい。

テーブルの作成

この目的のために,Maharaデータベースに以下のようなフィールドを持つテーブルを作成する。

Table "blocktype_simpleclock_visit"

ColumnType
blockinstancebigint
userbigint
lastvisittimestamp
countvistint

blockinstanceは、ページに配置されたブロックモジュールを表す識別番号で、block_instance.id (テーブル block_instance の、フィールド id) を外部キーとして参照する。userは閲覧者を表す識別番号で、usr.idを外部キーとして参照する。このテーブルの主キーは(blockinstance,user)となる。

lastvisitとcountvisitがわれわれのブロックプラグインの独自データで、それぞれ直近のアクセス日時、累計のアクセス回数を示す。

このようなテーブルをどうやって作るのだろうか。データベースに直接アクセスして手動で作る、という必要はない。管理者がブロック型プラグインを「表示」するタイミングで、特定のファイル(db/install.xml)の内容に従ってMaharaが作成してくれる。install.xml の内容はXMLDBに従って作成する。

db/install.xml

<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20060926" COMMENT="XMLDB file for core Mahara tables"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
    <TABLES>
        <TABLE NAME="blocktype_simpleclock_visit">
            <FIELDS>
                <FIELD NAME="blockinstance" TYPE="int" LENGTH="8" NOTNULL="true" />
                <FIELD NAME="usr"           TYPE="int" LENGTH="8" NOTNULL="true" />
                <FIELD NAME="lastvisit"     TYPE="datetime" NOTNULL="true" />
                <FIELD NAME="countvisit"    TYPE="int" LENGTH="4" NOTNULL="true" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="blockinstance,usr" />
                <KEY NAME="instancefk" TYPE="foreign" FIELDS="blockinstance" REFTABLE="block_instance" REFFIELDS="id" />
                <KEY NAME="usrfk" TYPE="foreign" FIELDS="usr" REFTABLE="usr" REFFIELDS="id" />
            </KEYS>
        </TABLE>
    </TABLES>
</XMLDB>

現在、われわれのブロックプラグインのファイル構成は下記のようになっている。

simpleclock/
 +-- thumb.png
 +-- version.php
 +-- lib.php
 +-- lang/
 |    +-- en.utf8/
 |    |     +-- blocktype.simpleclock.php
 |    +-- ja.utf8/
 |          +-- blocktype.simpleclock.php
 +-- db/
      +-- install.xml

もう一度管理者でインストールすると、以下のようなデータベースができているはずだ。

(postgresql の psql での表示)
maharadb=> \d blocktype_simpleclock_visit 
       Table "public.blocktype_simpleclock_visit"
    Column     |            Type             | Modifiers 
---------------+-----------------------------+-----------
 blockinstance | integer                     | not null
 usr           | integer                     | not null
 lastvisit     | timestamp without time zone | not null
 countvisit    | smallint                    | not null
Indexes:
    "blocsimpvisi_blousr_pk" PRIMARY KEY, btree (blockinstance, usr)
    "blocsimpvisi_blo_ix" btree (blockinstance)
    "blocsimpvisi_usr_ix" btree (usr)
Foreign-key constraints:
    "blocsimpvisi_blo_fk" FOREIGN KEY (blockinstance) REFERENCES block_instance(id)
    "blocsimpvisi_usr_fk" FOREIGN KEY (usr) REFERENCES usr(id)

ページ情報などの取得

データベーステーブルへのアクセスの前に、「アクセスしているのは誰なのか?」「このページはどのページなのか?」といったMahara的な情報を取得する必要がある。

BlockInstance ID

render_instance には、BlockInstance のオブジェクトが第一引数として渡されてくる。この場合、これが自分自身を表すオブジェクトとなっているはずである。そのIDは下記のようにして得られる。

$blockinstance_id = $instance->get('id');

View ID

自分自身がおかれている View(ページ)のID。

$view_id = $instance->get_view()->get('id');

Owner ID

上記Viewの所有者のID。

$owner = $instance->get_view()->get('owner');

User ID

アクセスしているユーザは、グローバル変数 $USER から取得できる。

global $USER;
$userid = (!empty($USER) ? $USER->get('id') : 0);

テーブルへのアクセス

MaharaではMoodleで開発されたXMLDB関数を使ってテーブルへアクセスする。XMLDBのドキュメントはこのへんだが、ちょっと使い方が違うようだ。Maharaのソースを見た方が確実で早いと思う。Maharaに入ってるXMLDB関数のソースは lib/dml.php で、作者表示は Martin Dougiamas となっている。dml.phpで定義されている、データベースへアクセスするために使える関数の一覧はこちら参照。

とりあえず、一行を select する get_record と、upsert する ensure_record_exists を使って、訪問日の表示と保存をするように書き換えてみた lib.php は以下のようになる。render_instance() の定義部分だけ抜き出している。

lib.php

    public static function render_instance(BlockInstance $instance, $editing=false) {
      $bid = $instance->get('id');
      global $USER;
      $uid = (!empty($USER) ? $USER->get('id') : 0);

      $now = db_format_timestamp(time());

      # Maybe equivalent to 
      # 'select * from {blocktype_sinmpleclock_visit} where blockinstance=$bid and usr=$uid
      $rec = get_record('blocktype_simpleclock_visit',
                        'blockinstance',$bid,
                        'usr',$uid);

      if ( !empty($rec) ) {
        $lastvisit = date("Y/m/d H:i:s",strtotime($rec->lastvisit));
        $count = $rec->countvisit+1;
      } else {
        $count = 1;
      }

      $whereobject = array (
                            'blockinstance' => $bid,
                            'usr' => $uid
                            );

      $dataobject = array (
                            'blockinstance' => $bid,
                            'usr' => $uid,
                            'lastvisit' => $now,
                            'countvisit' => $count
                           );

      # UPDATE record with $dataobject if $whereobject exists, otherwise INSERT it.
      $status = ensure_record_exists ( 'blocktype_simpleclock_visit',
                                       $whereobject, $dataobject );

      $result = get_string('clockstring','blocktype.simpleclock',date("Y/m/d H:i:s"));

      if ( $count == 1 ) {
        $result .= '<br>'.get_string('firstvisit','blocktype.simpleclock');
      } else {
        $result .= '<br>'.get_string('notfirstvisit','blocktype.simpleclock',$lastvisit);
      }

      return $result;
    }

新しくメッセージを追加したので、LANGファイルも書き換えが必要。

lang/en.utf8/blocktype.simpleclock.php

$string['title'] = 'SimpleClock';
$string['description'] = 'Show current date/time on your view.';

$string['clockstring'] = 'It is %s now.';
$string['firstvisit'] = 'Welcome! It\'s your first visit.';
$string['notfirstvisit'] = 'Your last visit: %s';
?>

lang/ja.utf8/blocktype.simpleclock.php

$string['title'] = 'SimpleClock';
$string['description'] = '現在の日付と時刻を表示します。';

$string['clockstring'] = 'ただいまの時刻は %s です。';
$string['firstvisit'] = 'ようこそ!はじめての訪問ですね ^^';
$string['notfirstvisit'] = 'あなたの最後の訪問: %s';
?>

こうなる。

maharapg-t4-1-20121212-024610.png

ここまでのファイル: filesimpleclock-t4.zip


添付ファイル: filesimpleclock-t4.zip 210件 [詳細]

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-01-19 (土) 06:43:58 (1619d)