Nullyのぶろぐ

仙台で働くエンジニアの日記

Moduleを利用しているアプリで、従属行の取得を試みる

さっきテスト的に自宅でやっていてはまったので覚え書きとしてポスト。

はじめに

Moduleを利用し、ユーザーテーブル、コンタクトタイプテーブルを用意し、それらを利用して外部キー制約を行うというものです。

Moduleを利用していない場合とは若干動作が異なることがあると思いますが、それぞれを置き換えていただけると大まかな内容は参考程度にはできるかと思います。

利用バージョンは09/11/01時点で最新バージョンの1.9.5を利用しています。

Moduleを作る

通常通り、DefaultModuleを作ります。

zf create project

zf create module default

モジュールを作ると、作ったModuleの直下に、Bootstrap.phpが作成されていますので、その中に「_initAutoloader」を作り、Module専用のAutoLoaderを利用できるようにします。

Bootstrap.php

class Bootstrap extends Zend_Application_Module_Bootstrap

{

protected function _initAutoloader()

{

$autoloader = new Zend_Application_Module_Autoloader(array(

";namespace" => "Default",

"basePath" => dirname(__FILE__)

));

}

}

これを記述しておけばいちいちrequire_onceなどを記述しなくてもファイルを呼び出すことが可能になります。

テーブルに見合ったMapperなどの作成

今回は、ユーザーテーブル・コンタクトタイプテーブルを利用するので、DefaultModuleのModelファイルに以下のファイルを作成します。

model

|- User.php

|- UserMapper.php

|- ContactType.php

|- ContactTypeMapper.php

` - DbTable

|- User.php

`- ContactType.php

※DbTableより上にあるファイルはそれぞれSELECTや、UPDATEするための関数が記述されていますが、今回は割愛します。

DbTable以下にあるファイルはすべて、「Zend_Db_Table_Abstract」を継承します。

リレーションの定義

ここでいったんリレーションを確認します。

リレーションとは、上の方でも説明したとおり、テーブル同士の関係性(a.idはb.idに入りますよーという感じのもの)を表します。

今回定義するリレーションは、「ユーザーテーブルの親テーブルはコンタクトタイプテーブルであり、ユーザーテーブルのコンタクトタイプIDは親テーブルであるコンタクトタイプテーブルのIDが格納される」という形になります。(言い方などが若干違いがあるかと思いますが、そのときはご指摘いただければと思います。。)

図で表すと、以下のような感じになります。

コンタクトタイプテーブル(親) ユーザーテーブル(子)
ID コンタクトタイプID

つまり、子テーブルは親テーブルを参照する形になります。

ここまで形が決まったら、PHPMyAdminのようなGUIデータベース管理アプリなどを利用してテーブルを作成するとすぐに終わります。

※テーブルのリレーションの作成は今回は割愛させていただきます。

作ったDbTable以下にあるファイルを修正していく

先ほど作ったDbTableディレクトリ以下にある、Users.php・ContactTypes.phpのファイルを修正していきます。

まずは、User.phpから。

DbTable/User.php

class Default_Model_DbTable_Users extends Zend_Db_Table_Abstract

{

protected $_name = "users";

protected $_referenceMap = array(

"ContactTypes" => array(

"columns" => array("contacttype_id"),// 対象のカラム名

"refTableClass" => "Default_Module_DbTable_ContactTypes",// 参照対象になるクラスのクラス名

"refColumn" => "id" // 親テーブルの対象カラム名

)

);

}

DbTbale/ContactTypes.php

class Default_Model_DbTabl_ContactTypes extends Zend_Db_Table_Abstract

{

protected $_name = "contacttypes";

protected $_dependentTables = array("Default_Model_DbTable_Users"); //コンタクトタイプIDを参照しているZned_Db_Table_Abstractを継承したクラス名を記述

}

ここで出てきた、「$_referenceMap」は、リレーション設定をZend Frameworkで利用できるようにするための変数です。

「ContactTypes」はZend_Db_Table_Abstract内で、ループ処理をする際に必要な名前なので、ここはわかりやすいような名前をつけます。(テーブルの名前などがいいかもしれません)

次に、有効なプロパティ群を列挙します。

  • columns:子テーブルのリレーションを利用するカラム名
  • refTableClass:利用するZend_Db_Table_Abstractを継承したクラス名
  • refColumns:参照するテーブルの対象となるカラム名
  • on(Delete|Update):親テーブルが削除・更新された際に、子テーブルにはどういった処理を行うかの設定。 これは、phpMyAdminなどでも設定が可
  • なので、phpMyAdminで指定していれば特に記述はしなくてもOKかと思います。

最後に記述してきたファイルを動かす

たとえば、「/index/contact/name/friends」のような形でアクセスしてきた場合は、「nameパラメータにfriends」という値が入ります。

この、「friends」からコンタクトタイプを取得し、取得しあコンタクトタイプのコンタクトIDをもとに、ユーザーを抽出するということができます。(ややこしくなってすみまあせん。。)

まずは、「friends」というキーワードから、コンタクトタイプ名を抽出します(自動でIDも取得できます)。

IndexController -> contactAction内

// 名前からコンタクトタイプの1行を抽出

$contact = new Default_Model_ContactTypes();

$where = $contact->getMapper()->getDbTable()->getAdapter()->quoteInto("LOWER(name) = ? ", $this->_getParam("name"));

// ここで名前を条件とした1行が取得できます(一致しなかった場合はnull)

// 取得した行結果のIDをもとに、ぶら下がっているユーザーをすべて抽出します

$row = $contact->getMapper()->getDbTable()->fetchRow($where);

// ここで親テーブルにぶら下がっているクラス名を記述します

$user = $row->findDependentRowset("Default_Model_DbTable_User");

すごく長ったらしくなってしまいましたが

これで一連の流れは完了です。

が、手元にあるソースをブログ用に直しながら書いていったので、もしかするとコピペだけでは動かないことがあるかと思います。

その時はコメントなどで教えていただけると助かります。。。

また、私も完全に把握しきれていない部分もあるので、「こういった手法がある!」や、「サンプルコードはもっとこう○○○のほうがいいのでは?」などがありましたら、こちらもコメントにてご教授していただければと思います。

Zend Frameworkで自サイトを作る練習しているのですが、なかなかうまく進まず無駄に時間を消費するばかりの毎日。。。