モデル - モデルクラスを追加する
これまで、Model_Base, Model_User, Model_Companyの使い方を説明致しました
次は、Model_Baseを継承したクラスの具体的な作成方法について記述します
Base\Model_Base
を継承したクラスを定義する際にすべきことは
Base\Model_Base
を継承する- DBのカラムをプロパティとして定義する
の2点です
文字のみの説明では伝わりにくいため、
この先の説明は、具体例とコードを挙げて補足していきます
例として、日記を書き記すために、
- id
- slug: (URLになるアルファベット、記号のみの文字列)
- tags: (日記につけるタグ、カンマ区切り)
- title: (日記タイトル)
- content: (日記の内容、Markdownで記述)
- created_at
- updated_at
といったカラムを持つ、diaries
テーブルをモデルクラス化するとします
必要なファイルを生成
マイグレーションとモデルを同時に生成できるoil
コマンドを使用します
$ php oil g model diary slug:string tags:string title:string content:text
Creating model: /Users/SYS-INOUE/work/noob/tmp/fuel/app/classes/model/diary.php
Creating migration: /Users/SYS-INOUE/work/noob/tmp/fuel/app/migrations/003_create_diaries.php
マイグレーションとクラス定義ファイルが生成されました
しかし、Model_Baseを継承する際には、このままでは使用できません
Model_Baseを継承できるように、マイグレーションファイルとクラス定義ファイルを修正していきます
1. マイグレーションファイルを修正
マイグレーションファイルで修正しなければならない項目は、
created_at
updated_at
の2点ですこの2点が下記の表のような構造になるように、マイグレーションを修正します
カラム名 | 型 | NULL許可 | デフォルト | 追加情報 |
---|---|---|---|---|
created_at | TIMESTAMP | しない | CURRENT_TIMESTAMP | |
updated_at | TIMESTAMP | しない | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
以下は、修正後のマイグレーションファイルです
<?php
namespace Fuel\Migrations;
class Create_diaries
{
public function up()
{
\DBUtil::create_table('diaries', array(
'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true, 'unsigned' => true),
'slug' => array('constraint' => 255, 'type' => 'varchar'),
'tags' => array('constraint' => 255, 'type' => 'varchar'),
'title' => array('constraint' => 255, 'type' => 'varchar'),
'content' => array('type' => 'text'),
'updated_at' => array('type' => 'timestamp', 'default' => \DB::expr('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')),
'created_at' => array('type' => 'timestamp', 'default' => \DB::expr('CURRENT_TIMESTAMP')),
), array('id'), true, 'InnoDB');
}
public function down()
{
\DBUtil::drop_table('diaries');
}
}
2. クラス定義ファイルを修正
モデルクラスのクラス定義は、以下のようになります
class Model_Diary extends \Base\Model_Base {
public $slug = null;
public $tags = null;
public $title = null;
public $content = null;
}
Model_Baseを継承し、
FuelPHPが生成したプロパティを削除し、DBに存在するカラムをプロパティとして追加しました
id
, created_at
, updated_at
はModel_Baseで既に定義されているため再定義の必要はありません
それら以外のslug
, tags
, title
, content
をプロパティに追加しました
フックを追加
フックは、Model_Baseの説明1でも1つ具体例を挙げましたが、
Model_Diaryを用いた例を説明いたします
日記につけられたタグを表すtagsプロパティは、カンマで区切られた文字列です
これをDB上はカンマ区切りの文字列、PHP上では文字列の配列として扱えるように、フックを実装した例が以下です
class Model_Diary extends \Base\Model_Base {
public $slug = null;
public $tags = null;
public $title = null;
public $content = null;
const DELIMITER = ',';
// 保存前:配列をカンマ区切りの文字列へ戻す
public function before_save() {
$this->tags = implode(self::DELIMITER, $this->tags);
}
// 保存後:カンマ区切りの文字列を配列へ分割する
public function after_save($success) {
$this->tags = explode(self::DELIMITER, $this->tags);
}
// 取得後:after_saveと同様に処理する
public static function after_find($records) {
foreach($records as &$record) {
$record->after_save(true);
}
return $records;
}
}
まず、区切り文字を表すDELIMITER
を定義しました
before_save
メソッドで、
DBに保存する前にtags
プロパティの値を文字列へ戻す処理を記述しました
after_save
, after_find
メソッドでは、
カンマ区切りの文字列となったtags
プロパティの値を、配列へ分割しています
このように、フックでプロパティを書き換える場合には、
保存時の変換と、保存後(取得後)の復元ができるように記述します
フックによる変換処理が正しく記述できているか、oil console
を用いて動作確認を行います
$ oil console
Fuel 1.7.1 - PHP 5.4.28 (cli) (Jun 19 2014 14:31:57) [Darwin]
>>> $model = new Model_Diary();
>>> $model->slug = 'this-is-a-first-diary';
>>> $model->title = 'This is a first diary!!';
>>> $model->content = 'Hoge hoge foo bar **buzz**';
>>> $model->tags = ['abc', 'def', 'ghi'];
>>> $model->created_at = DB::expr('NOW()');
>>> $model->insert();
true
>>> $model = Model_Diary::find(3);
>>> $model->tags[] = 'xxxxx';
>>> $model->update();
true
DBの中身を確認しても、正しく値の挿入、更新が行われています
メソッドを追加
次に、複雑な検索条件でのSELECTやJOINを利用するクエリなど、
Model_Baseが提供していないメソッドを実装します
メソッドを追加する際に重要なのは、_getTableName()
メソッドです
このメソッドは、メソッドを呼んだクラス名を取得し、テーブル名に変換して返します
引数はなく、メソッドを呼ぶだけで自分自身のクラス名と対応するテーブル名を入手できます
※ _getTableName()はstaticメソッドにすると期待通りに動作しないため、インスタンスメソッドにしております
class Model_Diary extends \Base\Model_Base {
public $slug = null;
public $title = null;
public $content = null;
// カラム名の配列を返す($ignoreSaveKeyに登録されたプロパティは返却されない)
public function columns() {
return array_keys($this->toArray());
}
// 検索条件を用いず、テーブルに格納されている先頭の1件だけを取得する
public static function findFirst($order_by = 'id') {
$table_name = static::_getTableName();
$query = DB::select($table_name)
->order_by($order_by)
->limit(1);
$result = $query->execute();
if(is_null($result)) {
return array();
} else {
$models = $result->as_array();
return $models[0];
}
}
}
static::_getTableName()
でテーブル名を取得することができます
Model_Baseのfindなどは実際にこれを使用し、テーブル名を取得しています
テーブル名が取得できれば、
あとは任意のクエリをFuelPHPが提供するクエリビルダ2から生成することができます
また、columnsメソッドで登場しているtoArray()メソッドは、
自分自身のインスタンスを、プロパティ => 値の連想配列へ変換するメソッドです
updateやinsertのクエリビルダに$query->set($this->toArray())
とすれば、カラムと値を一度にセットすることができます
更新履歴
- 2015/02/17: モデル - モデルクラスを追加するページ作成