アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

Piece_ORM 1.0.0の新機能を試してみた

こんにちは。小川です。

4月末にPiece FrameworkO/RマッピングフレームワークであるPiece_ORMの1.0.0(stable)がリリースしました。今回はこのPiece_ORMの新機能をいくつか試してみたいと思います。

今回試してみた機能は
・自動タイムスタンプ
・楽観的ロック
・配列サポート
の3つです。それでは早速使ってみましょう。

尚、基本的な設定などはここでは省かせていただきます。Piece_ORM短期集中コースPHPプロ!のTIPSを参考にしてください。今回使用したソースコードは最後に配布いたしますのでそちらも参考までに。

以下は今回使用したテーブルのスキーマです。



CREATE TABLE framework (
  id serial,
  name varchar(255) NOT NULL,
  uri varchar(255),
  lock_version integer NOT NULL DEFAULT 0,
  created_at timestamp with time zone,
  updated_at timestamp with time zone,
  PRIMARY KEY(id)
);



□自動タイムスタンプ
テーブルにcreated_at/updated_atというカラムを作成しておくと、INSERT/UPDATE時にそれぞれにタイムスタンプを登録してくれる機能です。テーブルにカラムをつけるだけで自動的に更新されるようになります。

以下はサンプルスクリプトです。configure.phpというスクリプトを読み込んでいますが、Piece_ORMの設定をまとめたファイルです。たいしたものじゃないので書きませんので、中身を見たい場合はソースをダウンロードしてください。

timestamps.php


<?php

require_once 'configure.php';
require_once 'Piece/ORM.php';

$mapper = Piece_ORM::getMapper('Framework');

$data = array(
  'Piece Framework' => 'http://piece-framework.com/',
  'symfony'         => 'http://www.symfony-project.org/',
  'CakePHP'         => 'http://www.cakephp.org/',
);

// INSERT
foreach ($data as $name => $uri) {
  $framework = $mapper->createObject();
  $framework->name = $name;
  $framework->uri = $uri;
  $mapper->insert($framework);
}
$frameworks = $mapper->findAll();
disp_timestamps($frameworks);

echo "\n";

// UPDATE
foreach ($frameworks as $framework) {
  $mapper->update($framework);
}
$frameworks = $mapper->findAll();
disp_timestamps($frameworks);

function disp_timestamps($frameworks)
{
  foreach ($frameworks as $framework) {
    echo "[{$framework->name}]\n";
    echo "  created_at: {$framework->createdAt}\n";
    echo "  updated_at: {$framework->updatedAt}\n";
  }
}

?>



$ php timestamps.php
[Piece Framework]
  created_at: 2008-06-04 13:56:11.617439+09
  updated_at:
[symfony]
  created_at: 2008-06-04 13:56:11.644954+09
  updated_at:
[CakePHP]
  created_at: 2008-06-04 13:56:11.650563+09
  updated_at:

[Piece Framework]
  created_at: 2008-06-04 13:56:11.617439+09
  updated_at: 2008-06-04 13:56:11.668114+09
[symfony]
  created_at: 2008-06-04 13:56:11.644954+09
  updated_at: 2008-06-04 13:56:11.672379+09
[CakePHP]
  created_at: 2008-06-04 13:56:11.650563+09
  updated_at: 2008-06-04 13:56:11.673652+09


たとえばsymfonyだと、INSERTの場合はcreated_atとupdated_atの両カラムが更新されるのですが、今回の例ではINSERTの場合はcreated_atカラムのみの更新となってますね。またタイムスタンプはDB側でCURRENT_TIMESTAMPで入れてるようです。


□楽観的ロック
テーブルにlock_versionカラムがある場合に楽観的ロックをサポートする機能です。既にスキーマの方に組み込んであるように、INTEGER型でNULL以外に設定してください。

lock.php


<?php

require_once 'configure.php';
require_once 'Piece/ORM.php';

$mapper = Piece_ORM::getMapper('Framework');

$framework = $mapper->findByName('Piece Framework');
$dummy = $mapper->findByName('Piece Framework');

var_dump($framework->uri, $framework->lockVersion);

$framework->uri = "http://example.org/";

$mapper->update($dummy);
$mapper->update($framework);

$framework = $mapper->findByName('Piece Framework');
var_dump($framework->uri, $framework->lockVersion);

?>



$ php lock.php
string(27) "http://piece-framework.com/"
string(1) "0"
string(27) "http://piece-framework.com/"
string(1) "1"


上記のスクリプトでは$frameworkと$dummyという2つのオブジェクトを取得しています。どちらも同じデータで、lock_versionはどちらも0です。先に$dummyというカラムに対してUPDATEをかけますが、この時点でDB上のlock_versionは自動でインクリメントされて1になります。
この状態でlock_versionが0の$frameworkをUPDATEしようとすると、lock_versionの違いによりUPDATEされません。正確にはUPDATEクエリは実行されるのですが、同一のlock_versionのレコードのみが更新されるという仕組みです。
lock_versionが違う場合はUPDATEされないだけでExceptionが出たりはしません。$mapper->update()の戻り値は更新したカラムの数ですので、更新されたかを判断するにはそれを使いましょう。

□配列サポート
以前のバージョンではIN句を用いたクエリを設定していても複数の値を渡すことができませんでしたが、今回変更で配列が渡された場合に展開されるようになったので、IN句も使えるようになりました。

テスト用にマッパーファイルにクエリを追加します。$names配列に含まれる名前と一致する全てのレコードを返すクエリです。

Framework.yaml


- name: findAllByNames
  query: >
    SELECT * FROM Framework WHERE name IN ($names)

array.php


<?php

require_once 'configure.php';
require_once 'Piece/ORM.php';

$mapper = Piece_ORM::getMapper('Framework');

$names = array('Piece Framework', 'symfony');
$some_frameworks = $mapper->findAllByNames($names);

foreach ($some_frameworks as $framework) {
  echo "{$framework->name}\n";
}

?>



$ php array.php
symfony
Piece Framework



今回作成したスクリプトなどを以下にまとめておきます。
orm.tar.gz

これでPiece Frameworkプロダクトも一通りstableになりましたね。Tracの方には現在も色々なチケットが登録されており、今後も様々な機能追加が期待できそうです。派手な機能はないですが、シンプルで使いやすいO/Rマッパーだと思います。ドキュメントはまだ少ないですが、ぜひ使ってみてください。