SlideShare a Scribd company logo
http://www.flickr.com/photos/totoro_zine/8463662488/




What’s Temporal model
    #FuelPHPTokyo 03
Agenda

Who am i ?
What’s temporal model ???
Let’s try temporal model !!!
$ whoami

   名前: 山口 貴之
   twitter: @takyam
   ブログ: http://new.takyam.com/
   会社: GaiaX
   仕事: WEB Engineer
   FuelPHP歴:1年くらい
packages
2つパッケージを公開してます

fuel-coffeeless
https://github.com/takyam-git/fuel-coffeeless

fuel-gearman
https://bitbucket.org/takyam/fuel-gearman

メンテしてないので恥ずかちぃのですがよろしければどぞ!
Model_Temporal

FuelPHP 1.6/develop から、Temporal ModelとよばれるORM
の拡張が導入されました。

1.5に導入された Model_Soft に続く2つ目の拡張です。

Revision Model といった方がイメージしやすいでしょうか。
Revision for your Apps.


超簡潔にいうと、バージョン管理をORMがやってくれます。

Wiki ページの変更履歴の管理のように!!
Old technique...
テーブル分割して子テーブルのレコード=リビジョン

このロジックはアプリ側で頑張る
New technique !

     Temporal Model を使う!

     ID+Datetime+Datetime の複合キー

     このテーブルを1個用意
Let’s try !!


それでは早速やってみましょう!

・・・とその前に、
Caution!!!

まだ develop バージョンです

ちょっと前までバグバグしてました

機能はまだ不足してるようです
1st. Generate Model
まずは、テーブルを作成します。

  $ oil g model wiki_page title:string body:text temporal_start:datetime
                        temporal_end:datetime

ジェネレートしたままの状態だとTemporal Model用ではないの
で、マイグレーションファイルを修正しましょう。
2nd. Fix Migration
DBUtil::create_table('wiki_pages', array(
	   'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true, 'unsigned' => true),
	   'title' => array('constraint' => 255, 'type' => 'varchar'),
	   'body' => array('type' => 'text'),
	   'temporal_start' => array('type' => 'datetime'),
	   'temporal_end' => array('type' => 'datetime'),
	   'created_at' => array('constraint' => 11, 'type' => 'int', 'null' => true),
	   'updated_at' => array('constraint' => 11, 'type' => 'int', 'null' => true),
), array('id', 'temporal_start', 'temporal_end'));




    プライマリーキーを、id, temporal_start, temporal_endの3つ
    のフィールドの複合キーに変更します。
3rd. Oil refine migrate
   それではmigrateを実行してテーブルを生成します
                                 $ oil r migrate
+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| title          | varchar(255)     | NO   |     | NULL    |                |
| body           | text             | NO   |     | NULL    |                |
| temporal_start | datetime         | NO   | PRI | NULL    |                |
| temporal_end   | datetime         | NO   | PRI | NULL    |                |
| created_at     | int(11)          | YES |      | NULL    |                |
| updated_at     | int(11)          | YES |      | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+
4th. Extends Temporal
    最後に生成されたモデルの継承元を変更して準備完了です

class Model_Wiki_Page extends OrmModel_Temporal ←Model_Temporal に変更
{
	 protected static $_properties = array(/* 略 */);
	   protected static $_primary_key = array(    ←Primary key を複合キーで設定
       'id', 'temporal_start', 'temporal_end');
	   protected static $_temporal = array(       ←Temporal Model 用のプロパティを追加
       'start_column'    => 'temporal_start',
       'end_column'      => 'temporal_end',
       'mysql_timestamp' => true,
	   );
	   protected static $_observers = array(/* 略 */);
}
5th. Save new model
   準備はできたのでモデルを保存してみましょう
$wiki_page = Model_Wiki_Page::forge();
$wiki_page->title = 'version 1';
$wiki_page->body = 'VERSION 1';
$wiki_page->save();

+----+-----------+-----------+---------------------+---------------------+
| id | title     | body      | temporal_start      | temporal_end        |
+----+-----------+-----------+---------------------+---------------------+
| 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2038-01-18 22:14:08 |
+----+-----------+-----------+---------------------+---------------------+
6th. Update model
   次にID:1のモデルをアップデートしてみます
$wiki_page = Model_Wiki_Page::find(1);
$wiki_page->title = 'version 2';
$wiki_page->body = 'VERSION 2';
$wiki_page->save();

   レコードの更新ではなく、新しく追加されました!
+----+-----------+-----------+---------------------+---------------------+
| id | title     | body      | temporal_start      | temporal_end        |
+----+-----------+-----------+---------------------+---------------------+
| 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2013-03-17 10:17:27 |
| 1 | version 2 | VERSION 2 | 2013-03-17 10:17:27 | 2038-01-18 22:14:08 |
+----+-----------+-----------+---------------------+---------------------+
7th. Get revisions
   何回か更新した後にリビジョンを取得してみます。
$revisions = Model_Wiki_Page::find_revisions_between(1);
foreach($revisions as $rev){
	 echo $rev->title . ' : '. $rev->temporal_start . ' - '
	 . $rev->temporal_end . PHP_EOL;
}

   ID:1に複数のバージョンが保持されてる事がわかります
version   1   :   2013-03-17   10:15:14   -   2013-03-17   10:17:27
version   2   :   2013-03-17   10:17:27   -   2013-03-17   10:21:57
version   3   :   2013-03-17   10:21:57   -   2013-03-17   10:23:20
version   4   :   2013-03-17   10:23:20   -   2013-03-17   10:23:28
version   5   :   2013-03-17   10:23:28   -   2038-01-18   22:14:08
8th. Overwrite
   バージョンを作らずに更新する事もできます

$wiki_page = Model_Wiki_Page::find(1);
$wiki_page->title = 'updated';
$wiki_page->overwrite();

+----+-----------+-----------+           +----+-----------+-----------+
| id | title     | body      |           | id | title     | body      |
+----+-----------+-----------+           +----+-----------+-----------+
| 1 | version 1 | VERSION 1 |            | 1 | version 1 | VERSION 1 |
| 1 | version 2 | VERSION 2 |            | 1 | version 2 | VERSION 2 |
| 1 | version 3 | VERSION 3 |            | 1 | version 3 | VERSION 3 |
| 1 | version 4 | VERSION 4 |            | 1 | version 4 | VERSION 4 |
| 1 | version 5 | VERSION 5 |            | 1 | updated    | VERSION 5 |
+----+-----------+-----------+           +----+-----------+-----------+
9th. Delete model
    削除してみましょう!
$wiki_page = Model_Wiki_Page::find(1);
$wiki_page->delete();
+----+---------+-----------+---------------------+---------------------+
| id | title   | body      | temporal_start      | temporal_end        |
+----+---------+-----------+---------------------+---------------------+
---( 略 )---
+----+---------+-----------+---------------------+---------------------+
| 1 | updated | VERSION 5 | 2013-03-17 10:23:28 | 2038-01-18 22:14:08 |
+----+---------+-----------+---------------------+---------------------+


+----+---------+-----------+---------------------+---------------------+
| id | title   | body      | temporal_start      | temporal_end        |
+----+---------+-----------+---------------------+---------------------+
---( 略 )---
+----+---------+-----------+---------------------+---------------------+
| 1 | updated | VERSION 5 | 2013-03-17 10:23:28 | 2013-03-17 10:35:17 |
+----+---------+-----------+---------------------+---------------------+
10th. Deleted model
   削除したモデルはfindしても返ってきません!
$wiki_page = Model_Wiki_Page::find(1);
var_dump($wiki_page); // NULL
11th. Restore
   削除したモデルはRestoreすることができます!
$revisions = Model_Wiki_Page::find_revisions_between(1);
$last_revision = end($revisions);
$last_revision->restore();


+----+-----------+-----------+---------------------+---------------------+
| id | title     | body      | temporal_start      | temporal_end        |
+----+-----------+-----------+---------------------+---------------------+
| 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2013-03-17 10:17:27 |
| 1 | version 2 | VERSION 2 | 2013-03-17 10:17:27 | 2013-03-17 10:21:57 |
| 1 | version 3 | VERSION 3 | 2013-03-17 10:21:57 | 2013-03-17 10:23:20 |
| 1 | version 4 | VERSION 4 | 2013-03-17 10:23:20 | 2013-03-17 10:23:28 |
| 1 | updated    | VERSION 5 | 2013-03-17 10:23:28 | 2013-03-17 10:35:17 |
| 1 | updated    | VERSION 5 | 2013-03-17 10:46:57 | 2038-01-18 22:14:08 |
+----+-----------+-----------+---------------------+---------------------+
12th. Purge ALL!!
   綺麗にすべてを消す事もできます!

$revisions = Model_Wiki_Page::find(1);
$revisions->purge();



mysql> select id, title, body, temporal_start, temporal_end from wiki_pages;
Empty set (0.00 sec)
おわり

駆け足でしたが、ドキュメントに書いてある内容をひと通り試し
てみました。詳しくはdev-docsをご覧ください。

http://fuelphp.com/dev-docs/packages/orm/model/
temporal.html
ご清聴ありがとうございました



 m(_ _)m

More Related Content

What's Temporal model FuelPHP東京勉強会03

  • 2. Agenda Who am i ? What’s temporal model ??? Let’s try temporal model !!!
  • 3. $ whoami 名前: 山口 貴之 twitter: @takyam ブログ: http://new.takyam.com/ 会社: GaiaX 仕事: WEB Engineer FuelPHP歴:1年くらい
  • 5. Model_Temporal FuelPHP 1.6/develop から、Temporal ModelとよばれるORM の拡張が導入されました。 1.5に導入された Model_Soft に続く2つ目の拡張です。 Revision Model といった方がイメージしやすいでしょうか。
  • 6. Revision for your Apps. 超簡潔にいうと、バージョン管理をORMがやってくれます。 Wiki ページの変更履歴の管理のように!!
  • 8. New technique ! Temporal Model を使う! ID+Datetime+Datetime の複合キー このテーブルを1個用意
  • 11. 1st. Generate Model まずは、テーブルを作成します。 $ oil g model wiki_page title:string body:text temporal_start:datetime temporal_end:datetime ジェネレートしたままの状態だとTemporal Model用ではないの で、マイグレーションファイルを修正しましょう。
  • 12. 2nd. Fix Migration DBUtil::create_table('wiki_pages', array( 'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true, 'unsigned' => true), 'title' => array('constraint' => 255, 'type' => 'varchar'), 'body' => array('type' => 'text'), 'temporal_start' => array('type' => 'datetime'), 'temporal_end' => array('type' => 'datetime'), 'created_at' => array('constraint' => 11, 'type' => 'int', 'null' => true), 'updated_at' => array('constraint' => 11, 'type' => 'int', 'null' => true), ), array('id', 'temporal_start', 'temporal_end')); プライマリーキーを、id, temporal_start, temporal_endの3つ のフィールドの複合キーに変更します。
  • 13. 3rd. Oil refine migrate それではmigrateを実行してテーブルを生成します $ oil r migrate +----------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+------------------+------+-----+---------+----------------+ | id | int(11) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | body | text | NO | | NULL | | | temporal_start | datetime | NO | PRI | NULL | | | temporal_end | datetime | NO | PRI | NULL | | | created_at | int(11) | YES | | NULL | | | updated_at | int(11) | YES | | NULL | | +----------------+------------------+------+-----+---------+----------------+
  • 14. 4th. Extends Temporal 最後に生成されたモデルの継承元を変更して準備完了です class Model_Wiki_Page extends OrmModel_Temporal ←Model_Temporal に変更 { protected static $_properties = array(/* 略 */); protected static $_primary_key = array( ←Primary key を複合キーで設定 'id', 'temporal_start', 'temporal_end'); protected static $_temporal = array( ←Temporal Model 用のプロパティを追加 'start_column' => 'temporal_start', 'end_column' => 'temporal_end', 'mysql_timestamp' => true, ); protected static $_observers = array(/* 略 */); }
  • 15. 5th. Save new model 準備はできたのでモデルを保存してみましょう $wiki_page = Model_Wiki_Page::forge(); $wiki_page->title = 'version 1'; $wiki_page->body = 'VERSION 1'; $wiki_page->save(); +----+-----------+-----------+---------------------+---------------------+ | id | title | body | temporal_start | temporal_end | +----+-----------+-----------+---------------------+---------------------+ | 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2038-01-18 22:14:08 | +----+-----------+-----------+---------------------+---------------------+
  • 16. 6th. Update model 次にID:1のモデルをアップデートしてみます $wiki_page = Model_Wiki_Page::find(1); $wiki_page->title = 'version 2'; $wiki_page->body = 'VERSION 2'; $wiki_page->save(); レコードの更新ではなく、新しく追加されました! +----+-----------+-----------+---------------------+---------------------+ | id | title | body | temporal_start | temporal_end | +----+-----------+-----------+---------------------+---------------------+ | 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2013-03-17 10:17:27 | | 1 | version 2 | VERSION 2 | 2013-03-17 10:17:27 | 2038-01-18 22:14:08 | +----+-----------+-----------+---------------------+---------------------+
  • 17. 7th. Get revisions 何回か更新した後にリビジョンを取得してみます。 $revisions = Model_Wiki_Page::find_revisions_between(1); foreach($revisions as $rev){ echo $rev->title . ' : '. $rev->temporal_start . ' - ' . $rev->temporal_end . PHP_EOL; } ID:1に複数のバージョンが保持されてる事がわかります version 1 : 2013-03-17 10:15:14 - 2013-03-17 10:17:27 version 2 : 2013-03-17 10:17:27 - 2013-03-17 10:21:57 version 3 : 2013-03-17 10:21:57 - 2013-03-17 10:23:20 version 4 : 2013-03-17 10:23:20 - 2013-03-17 10:23:28 version 5 : 2013-03-17 10:23:28 - 2038-01-18 22:14:08
  • 18. 8th. Overwrite バージョンを作らずに更新する事もできます $wiki_page = Model_Wiki_Page::find(1); $wiki_page->title = 'updated'; $wiki_page->overwrite(); +----+-----------+-----------+ +----+-----------+-----------+ | id | title | body | | id | title | body | +----+-----------+-----------+ +----+-----------+-----------+ | 1 | version 1 | VERSION 1 | | 1 | version 1 | VERSION 1 | | 1 | version 2 | VERSION 2 | | 1 | version 2 | VERSION 2 | | 1 | version 3 | VERSION 3 | | 1 | version 3 | VERSION 3 | | 1 | version 4 | VERSION 4 | | 1 | version 4 | VERSION 4 | | 1 | version 5 | VERSION 5 | | 1 | updated | VERSION 5 | +----+-----------+-----------+ +----+-----------+-----------+
  • 19. 9th. Delete model 削除してみましょう! $wiki_page = Model_Wiki_Page::find(1); $wiki_page->delete(); +----+---------+-----------+---------------------+---------------------+ | id | title | body | temporal_start | temporal_end | +----+---------+-----------+---------------------+---------------------+ ---( 略 )--- +----+---------+-----------+---------------------+---------------------+ | 1 | updated | VERSION 5 | 2013-03-17 10:23:28 | 2038-01-18 22:14:08 | +----+---------+-----------+---------------------+---------------------+ +----+---------+-----------+---------------------+---------------------+ | id | title | body | temporal_start | temporal_end | +----+---------+-----------+---------------------+---------------------+ ---( 略 )--- +----+---------+-----------+---------------------+---------------------+ | 1 | updated | VERSION 5 | 2013-03-17 10:23:28 | 2013-03-17 10:35:17 | +----+---------+-----------+---------------------+---------------------+
  • 20. 10th. Deleted model 削除したモデルはfindしても返ってきません! $wiki_page = Model_Wiki_Page::find(1); var_dump($wiki_page); // NULL
  • 21. 11th. Restore 削除したモデルはRestoreすることができます! $revisions = Model_Wiki_Page::find_revisions_between(1); $last_revision = end($revisions); $last_revision->restore(); +----+-----------+-----------+---------------------+---------------------+ | id | title | body | temporal_start | temporal_end | +----+-----------+-----------+---------------------+---------------------+ | 1 | version 1 | VERSION 1 | 2013-03-17 10:15:14 | 2013-03-17 10:17:27 | | 1 | version 2 | VERSION 2 | 2013-03-17 10:17:27 | 2013-03-17 10:21:57 | | 1 | version 3 | VERSION 3 | 2013-03-17 10:21:57 | 2013-03-17 10:23:20 | | 1 | version 4 | VERSION 4 | 2013-03-17 10:23:20 | 2013-03-17 10:23:28 | | 1 | updated | VERSION 5 | 2013-03-17 10:23:28 | 2013-03-17 10:35:17 | | 1 | updated | VERSION 5 | 2013-03-17 10:46:57 | 2038-01-18 22:14:08 | +----+-----------+-----------+---------------------+---------------------+
  • 22. 12th. Purge ALL!! 綺麗にすべてを消す事もできます! $revisions = Model_Wiki_Page::find(1); $revisions->purge(); mysql> select id, title, body, temporal_start, temporal_end from wiki_pages; Empty set (0.00 sec)