FuelPHPでのhas_manyリレーションでの書き込み(hasmanyを一度にsave)について簡単にメモ

2013 年 3 月 4 日PC・IT

Pocket

FuelPHPとCakePHPのhasmanyリレーションドキュメントイメージ

フレームワークを利用するときに便利なことの一つが、DBのリレーション関係です。適切に設定を行えば、複数のテーブルを関連づけて読み込み・保存することが簡単にできるようになるのです。

CakePHPでのhas_manyなどのリレーションについては、ドキュメントが豊富で簡単に出来て、とても便利でした。CakePHPで出来ていたことがFuelPHPでも出来るようなのですが、どうやるのかについて、各種書籍やWeb上の公式ドキュメント、各種サイトを閲覧しても分からず、Coreソースを見たりなんだりして、やっと分かったことについてまとめます。

私は、職業プログラマというわけでもないので、誤りや非効率的な部分があると思います。その点コメントでご指摘頂けるとありがたいです。

今回題材にする例

本エントリーでは、セミナーの開催情報を表示するシステムを例にしてみます。

存在するテーブルは、「開催するセミナーの情報を管理するテーブル」と「そのセミナーの講師を管理するテーブル」です。
これらをそれぞれ、データベース上に「seminar」テーブルと「teacher」テーブルで管理します。

「teacher」テーブルには、「seminar_id」カラムがあり、このカラムの情報で「誰がどのセミナーの講師か」を把握します。

セミナーには複数の講師が担当する場合もありますから、テーブル同士の関係は、「一つのセミナー情報に対して、多数の講師が存在しうる」という形になります。
この関係は、CakePHPでも、FuelPHPでも、「seminar」 has many 「teacher」という形で表されます。

(同じ人が複数のセミナーの講師になることもあるので、HABTMの方がよいのではないかという指摘はもっともですが、ここでは端折ります。)

CakePHPで出来ていたこと

※前提として、私はCakePHP1.3までしかいじったことがありません
CakePHPでは、モデルで「has one」「belongs to」「has many」「HABTM」の設定が可能です(アソシエーション: モデル同士を繋ぐ — CakePHP Cookbook v2.x documentation)。

CakePHPでのモデルの設定

seminarモデルとteacherモデルにそれぞれ以下のような設定を記載します。

var $hasMany = array(
				'Teacher' => array(
					'className'  => 'Teacher',
					'foreignKey'	=> 'seminar_id',
					'conditions' => array(),
					'order'	  => '',
			);
var $belongsTo = array(
					
					'Seminar' => array(
						
						'className' => 'Seminar',
						'foreignKey' => 'id',
					)
					
			);

View上でのフォームの記載

//セミナーの名称
echo '<div class="bottom_margin">';
	echo $form->label('Seminar.subject', 'セミナー名称');
	echo $form->text('Seminar.subject');
	echo $form->error('Seminar.subject');
echo '</div>';


//セミナーの説明
echo '<div class="bottom_margin">';
	echo $form->label('Seminar.contents', 'セミナーの内容');
	echo $form->textarea('Seminar.contents');
	echo $form->error('Seminar.contents');
echo '</div>';


//講師の名前
echo '<div class="bottom_margin">';
	echo $form->label('Teacher.0.name', '講師の名前');
	echo $form->text('Teacher.0.name');
	echo $form->error('Teacher.0.name');
echo '</div>';

POSTされた後のコントローラーで処理されて、以下のような配列として格納されます。

Array
(
	[Seminar] => Array
		(
			[subject] => '入力したセミナータイトル',
			[contents] => '入力したセミナーの内容'
		)
	[Teacher] => Array
		(
			[0] => Array
				(
					[name] => '入力された講師の名前'
				)
		)
)

Controller上での書き込み方法

//POSTされたデータは、$this->dataに格納
//バリデーションなどについては割愛
$this->Seminar->saveAll();

FuelPHPで同じ事をやるには?

似たようなことをFuelPHPでやるには、以下のような形になります。

FuelPHPでのモデルの設定

seminarモデルとteacherモデルにそれぞれ以下のような設定を記載します。
CakePHPとやることに大差はありませんが、FuelPHPの方がよりわかりやすいかと思います。Ormパッケージの有効化などを忘れずに行って下さい。

protected static $_has_many = array(
							'teacher' => array(
								'key_from' => 'id',
								'model_to' => 'Model_Teacher',
								'key_to' => 'seminar_id',
								'cascade_save' => true,
								'cascade_delete' => false
							)
						);
protected static $_belongs_to = array(
								'seminar' => array(
												'key_from' => 'seminar_id',
												'model_to' => 'Model_Seminar',
												'key_to' => 'id',
												'cascade_save' => true,
												'cascade_delete' => false,
											)
							);

Controller上でのフォームの記載

Viewの書き方については、だいぶ異なります。Fieldsetクラスを用いて、Viewの内容をControllerで書いてそれをViewに渡す形になります。詳細は、各種書籍やサイトをみれば分かるかと思います。

//Formの作成
$form = Fieldset::forge('seminar');
$form->teacher= Fieldset::forge('teacher');
$form->repopulate($form);

//セミナー名称
$form->add('subject', 'セミナー名称', array('type' => 'text'));

//セミナーの内容
$form->add('contents', 'セミナーの内容', array('type' => 'textarea'));

//講師の名前
$form->add('teacher[][name]', '講師の名前', array('type' => 'text'));

 //Viewインスタンスの生成
$output = View::forge('seminar/add');

//出力変数へのデータ格納
$output->set('form', $form); //formをViewに渡しており、Viewファイルでは$formをechoしています。

講師の名前部分、第一引数については、このように記載することで、POSTした後、配列として格納されます。

Controller上での書き込み方法

上記のようなフォームでPOSTした後のデータをリレーションに基づきどう書き込むかは以下のようになります。
バリデーションなどは端折っています。

//入力されPOSTされた内容を変数に格納
$post = Input::post();

//form_save変数にリレーション済みのモデルインスタンスを格納
$form_save = Model_Seminar::forge($post);
	//以下では動作しなかった
	//$form_save = new Model_Seminar();

//リレーションモデルインスタンスを格納
$form_save->teacher[] = Model_Teacher::forge($post['teacher'][0]);
	//以下では動作しなかった
	//$form_save->teacher = new Model_Teacher();

	//以下では動作しなかった Part2
	//$form_save->teacher= Model_Teacher::forge($post['teacher'][0]);

//saveメソッドの実行
$form_save->save();

まとめ

説明としてはかなり端折り気味でつたない上に誤っている恐れがありますが、個人的なメモとしても記しておきます。とにかくforgeの引数に格納した配列を渡すことで、リレーションを適切に保ったモデルインスタンスができあがるということです。

FuelPHP関連スライド

FuelPHP関連書籍

FuelPHPを学ぶに当たって以下の2つの書籍がとても参考になりました。というか、他に書籍あるんでしょうか?

FuelPHP入門
FuelPHP入門

posted with amazlet at 13.02.07
早川 聖司
ソーテック社
売り上げランキング: 25,016

満を持して発売された紙の書籍。入門の名にふさわしくインストールから利用まで、とてもわかり易く書かれている。oilコマンドの使い方なども、書いてある通りやってみて「なるほど」と思えることがあって、FuelPHPの便利さが実感できた。CakePHPのコンソールを全然使ってなかったので、ちゃんと使ってみようと思ったりもした。

ただ、Controller_Templateの使い方が、この本やネットだとよくわからず、下の電子書籍も読んでみた。

はじめてのフレームワークとしてのFuelPHP
鈴木憲治
達人出版会
発行日: 2012-07-02
対応フォーマット: EPUB, PDF

上記紙の書籍を読んで、いろいろいじくってからこの電子書籍を読むと、するすると頭に入ってきた。Controller_Templateの所はこっちのほうが記載が豊富で、やっと理解(ちゃんと動作させることが)できた。まぁ、元ソースを読めという話でもあり、ここらへんは楽をしたい私の性分のせい。それ以外の記述も充実しており、購入者限定のメーリングリストなどもあるようなので、気になる方は上記のリンクから「達人出版会」のページへ。(決済はPaypalのみ。)

似たようなエントリ

2013 年 3 月 4 日PC・IT