gasormはcodeigniter用のORMですが、
今回少し使ってみたので、単純に既存のテーブル構造から、シンプルにデータを抜いてくるところまでを作ってみました。
既存のテーブルを題材にしたので、idとか user_idのように綺麗にORMに適用できなかったので、少し手こずりました。
- お客様モデル
customer.php
<?php namespace Model;
use \Gas\Core;
use \Gas\ORM;
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Customer extends ORM{
public function _init()
{
/**
* プライマリキー 単に "id"の場合は省略できます。
*/
$this->primary_key = "CUSTOMER_NO";
/**
* リレーション
* ねぎテーブル側にCUSTOMER_NOがあり、belongs_toでCustomerに属するようにする。
* ねぎは一つしか持てません。
*/
self::$relationships = array (
'green_onion' => ORM::has_one('\\Model\\Green_onion')
);
/**
* フィルード定義とバリデーションルール
*/
self::$fields = array(
'CUSTOMER_NO' => ORM::field('int[8]'),
'NAME' => ORM::field('char[128]'),
"CREATE_AT" => ORM::field("datetime"),
"UPDATE_AT" => ORM::field("datetime"),
);
}
}
- ねぎモデル
green_onion.php
<?php namespace Model;
use \Gas\Core;
use \Gas\ORM;
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Green_onion extends ORM{
/**
* プライマリキー 単に "id"の場合は省略できます。
*/
public $primary_key="GREEN_ONION_NO";
/**
* 外部キー 参照先テーブル名_id の場合は省略できます
* このモデルのテーブルに持っている、お客様を示す外部キーを指定する。
*/
public $foreign_key = array('\\Model\\Customer' => 'CUSTOMER_NO');
public function _init()
{
/**
* リレーション
*/
self::$relationships = array (
'customer' => ORM::belongs_to('\\Model\\Customer')
);
/**
* フィルード定義とバリデーションルール
* 定義しておかないと値が取れません。
*/
self::$fields= array(
"GREEN_ONION_NO" => ORM::field("int[8]"),
"CUSTOMER_NO" => ORM::field("char[8]"),
"CREATE_AT" => ORM::field("datetime"),
"UPDATE_AT" => ORM::field("datetime"),
);
}
}
- ねぎコントローラ
green_onions.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Green_onions extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function show_list() {
$green_onion = new Model\Green_onion();
$onions = $green_onion->all();
$data["onions"]=$onions;
$this->load->view("green_onions_list",$data);
}
}
- ねぎ一覧ビュー
green_onions_list.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');?>
<h1>ねぎ一覧</h1>
<table class="data_tables">
<thead>
<tr>
<th>ねぎ番号</th>
<th>ねぎを持っているお客様</th>
</tr>
</thead>
<tbody>
<?php foreach ($onions as $onion) { ?>
<tr>
<td><?php echo $onion->GREEN_ONION_NO ?></td>
<td><?php echo $onion->green_onion()->NAME ?></td>
<?php } ?>
</tbody>
</table>
使い方的にはこれでいけるはずなのですが...
しかしこれだと取ってこれませんでした。
あまり日本語の情報がないので、結局gasormのコードを読んだのですが。
orm.phpのコンストラクタで、プライマリキーが設定されていると外部キーを設定しない条件があり、そこを修正せざるをえませんでした。
正しい修正の方法なのか、いまいちよくわかりません。
間違っていたら教えてください。
third_party/gas/classes/orm.php
// We really deal with composite keys here
//@remark プライマリキーの条件を削除、設定されていようがいまいが、外部キーを処理する
/*
if (empty($this->primary_key))
{
*/
if ( ! empty($this->foreign_key))
{
// Validate foreign keys for consistency naming convention recognizer
$foreign_key = array();
foreach($this->foreign_key as $namespace => $fk)
{
$foreign_key[strtolower($namespace)] = $fk;
}
$this->foreign_key = $foreign_key;
}
else
{
// If so far we didnt have any keys yet,
// then hopefully someone is really follow Gas convention
// while he define his entity relationship (yes, YOU!)
foreach ($this->meta->get('entities') as $name => $entity)
{
if ($entity['type'] == 'belongs_to')
{
$child_name = $entity['child'];
$child_instance = new $child_name;
$child_table = $child_instance->table;
$child_key = $child_instance->primary_key;
$this->foreign_key[strtolower($child_name)] = $child_table.'_'.$child_key;
}
}
}
//}
gasormは気になるコメントがコード内のそこここに書かれています。
大丈夫なのでしょうか。
補足で、二つほど単純なhackを書いておきます。
- テーブル名を大文字にしたい場合のhack
third_party/gas/classes/orm.php
final public function validate_table()
{
// If there is no table name set, use model name based by namespace path
if (empty($this->table))
{
// Parse namespace into table spec
if (array_key_exists($this->namespace, Core::$path['model']))
{
// Namespace already in the correct position
$namespace = strtolower($this->namespace);
}
else
{
// Get the namespace from parent
foreach (Core::$path['model'] as $parent => $path)
{
if (strpos($this->namespace, $parent) !== FALSE)
{
$namespace = strtolower($parent);
break;
}
}
}
// Define table, path and set the table properties
$table = str_replace($namespace.'\\', '', $this->model());
//@remark テーブル名を大文字に変更
/*
$path = strtolower(str_replace('\\', '_', $table));
$this->table = strtolower($path);
*/
$path = strtoupper(str_replace('\\', '_', $table));
$this->table = strtoupper($path);
}
return $this;
}
- IDの値に数値ではなく文字列を使いたい場合のhack
third_party/gas/classes/core.php
public static function generate_clause($domain, $key, $identifier, $ids = '')
{
//...(中略)
// Do we need to replace the string identifier
// Either into sub-query or the real COLUMN value(s) ?
// @remark ↑うん、やってよ! と思いました。
if ( ! empty($ids))
{
//@remark idsが通常だとクオート処理されないので、文字列ならクオート処理する。
if (is_string($ids)) {
$ids="'".$ids."'";
}
$pattern = sprintf($pattern, $ids);
}
// Statement is ready
return $pattern;
}