コンテンツにスキップ

モデル - モデルクラスを追加する

モデル - モデルクラスを追加する

Section titled “モデル - モデルクラスを追加する”

これまで、Model_Base, Model_User, Model_Companyの使い方を説明致しました

次は、Model_Baseを継承したクラスの具体的な作成方法について記述します


Base\Model_Baseを継承したクラスを定義する際にすべきことは

  1. Base\Model_Baseを継承する
  2. DBのカラムをプロパティとして定義する

の2点です

文字のみの説明では伝わりにくいため、

この先の説明は、具体例とコードを挙げて補足していきます

例として、日記を書き記すために、

  • id
  • slug: (URLになるアルファベット、記号のみの文字列)
  • tags: (日記につけるタグ、カンマ区切り)
  • title: (日記タイトル)
  • content: (日記の内容、Markdownで記述)
  • created_at
  • updated_at

といったカラムを持つ、diariesテーブルをモデルクラス化するとします


マイグレーションとモデルを同時に生成できるoilコマンドを使用します

Terminal window
$ 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. マイグレーションファイルを修正

Section titled “1. マイグレーションファイルを修正”

マイグレーションファイルで修正しなければならない項目は、

  • created_at
  • updated_at

の2点ですこの2点が下記の表のような構造になるように、マイグレーションを修正します

カラム名NULL許可デフォルト追加情報
created_atTIMESTAMPしないCURRENT_TIMESTAMP
updated_atTIMESTAMPしないCURRENT_TIMESTAMPon 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');
}
}

モデルクラスのクラス定義は、以下のようになります

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を用いて動作確認を行います

Terminal window
$ 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: モデル - モデルクラスを追加するページ作成

フック - Model_Base ↩

Query Builder - クラス - FuelPHP ドキュメント ↩