アソシエーション「hasOne」

2007/04/25 | cakePHP

少し時間ができたので、cakePHPのリレーション関連のまとめ。
ちなみにデータベースで言うところのリレーション(って言わないのかな?)はcakePHPではアソシエーションという。まず一つ目「hasOne」。
関連付けるモデルはあらかじめそれぞれ作っておく(「主」側のモデルをmodelA、「従」側のモデルをmodelBとする)。ここで「主」側、すなわちmodelAに設定するのがhasOneだ(「従」側つまりmodelBではbelongsToを設定することになる)。
実際の記述方法は以下のようになる。

var $hasOne = array(‘(1) 関連先のモデル名’=>
 array(
  ‘className’=>'(2) 関連先のモデルで使用されているクラス名’,
  ‘conditions’=>'(3) 関連を定義するSQL条件の一部’,
  ‘order’=>'(4) 関連先のデータの並び順’,
  ‘dependent’=>'(5) 関連先データの同時削除’,
  ‘foreignKey’=>'(6) 関連先テーブル側の外部キー’
 )
);

(1)はここでいうmodelBの名前のこと。
(2)は(1)内で定義されているクラス名。
(3)は条件を与えてデータを限定する際に使用する。
(4)は・・・いるのかな?。
(5)は「外部キー」という考え方にふさわしく、「主」側のデータが削除された場合に、それに関連付けられた「従」側のデータも削除するかどうかの設定(trueかfalse)。
(6)はmodelB内でmodelAの主キーをなんという名前のカラムで設定しているかを記述。cakePHPの記法にそって書いていれば省略できる。

逆転の発想(データの取り出し方)

2007/04/18 | cakePHP

「hasAndBelongsToMany」。諸問題はあったがなんとか動くことが確認できた。しかし必要なデータを取り出す手法がわからなかった。
ブログの記事とタグの関係を例に出すとする。記事はたくさんあるし、タグもたくさんあり、両者の関係は「多」対「多」で表すことができる。モデルとしては「article(記事)」と「tag(タグ)」の二つを作るとする。
この条件で、特定のタグを持つ記事を抽出しようと試みた。記事を抽出したいのだから、articleモデル内でhasAndBelongsToManyの設定を記述し、articleコントローラでデータを取り出そうと試みた。しかしどのように記述しても記事は全部抽出されてしまう。それぞれの記事には関連するタグが割り付けられているので、特定のタグのあるなしで、どの記事が必要なのか、ということはわかるが、記事が全て抽出されてしまっているため、なんとも不細工な処理だ。
酒を飲みつつ、ふと思いついた。逆の発想、タグからたどればいいじゃない!。タグと記事は多対多で同等の関係にあるわけだから、逆から見ても同様にデータを取得できる。つまり特定のタグに紐付けられた記事を全て抽出できるわけだ。あとはfindメソッドで、特定のタグのみ抽出すれば、これで全て事足りる。目からうろこの処理だった。
お酒もたまにはいいことあるね。

hasAndBelongsToManyは少し厄介

2007/04/17 | cakePHP

リレーションのための「hasAndBelongsToMany」。これは少々厄介だ。かなりトラぶったのでメモしておく。
まずこのリレーションを使おうとすると、使用する環境に注意が必要だ。環境とはすなわち、MySQLのバージョンとcakePHPのバージョンだ。cakePHPのデフォルトの記述方法だとMySQL3.23.58ではエラーが発生する(要はMySQL4で記述せよ、ということ)。
まず状況の説明。最初はMySQL3.23.58とcakePHP1.1.13.4450な環境で動作させようと試みた。しかしどうやってもリレーション先のテーブルのデータを取ってこれない。そこでMySQL5な環境で試してみたが、それでもやっぱり動かない。
ここではたと気づいた、バグがあるのでは・・・。調べてみたら賢者はいました。すばらしい。
http://cl.pocari.org/2007-04-06-2.html

ちなみにうちではcakePHP1.1.13.4450ではエラーは出なかった。それにMySQL5でもうまくいかなかった(これはテスト不足なだけかもしれない)。そこでまずcakePHP1.1.14.4797(執筆時点の最新バージョン)にアップデート(cakePHPのアップデートは簡単で、cakeディレクトリ内のファイルをごっそり入れ替えるだけ)。そうすると出ました、エラーメッセージ。ここで上記サイトに記載があるように、以下のように修正。

cake/libs/model/datasources/dbo_source.phpの1050行目

「’alias’ => $joinAssoc,」の記述があるのでその下に以下の一行を追加。
「’type’ => ‘INNER’,」

これで見事に解決した。3時間近く悩んだだけに感慨もひとしお。しかし上記ページの作者曰く「上記の修正はあくまで,hasAndBelongsToMany を使いたい場合で,そのほかの項目はあまりテストしていませんのでご注意を.」とのこと。まぁ問題が出たらその都度対応することにしよう。
貴重な情報に感謝。

テーブルのリレーション

2007/04/16 | cakePHP

久しぶりにcakePHPに戻る。近頃は一からシステムを組むなんてことに対して完全に億劫になっている。CMSツールとしてブログを使えば大抵のことができるから。記事管理ツールをわざわざ作らなくても、カスタマイズだけでできちゃうからね。
しかし、それでもだめな場合がやはりある。そういう場合でも極力楽をしたいから、そんなときにはcakePHPというわけだ。
しかし如何せん、まだ慣れてない。現状は簡単な仕組みを組むのもマニュアル片手にやっている状況だ(それでもすこぶる使い勝手がいい)。業務ではmojaviとcakePHPのフレームワーク二本立てだけれど、徐々にcakePHPに移行中、というわけだ。
さて本題。cakePHPでテーブルのリレーションを定義する方法。cakePHPでは極力定められたルールに則ってスクリプトを書くことで、定義ファイルも書かなくていいし、SQLも書かなくていい。直にSQLを書く必要がないから、その代わりにテーブルのリレーションをスクリプト側で定義したやらなければならない(ちょっとだけ面倒)。定義の仕方は4種類。ちなみにリレーションの定義の前に、関係するテーブルのモデルは別途個別に作成しておく必要がある。

■hasOneとbelongsTo
基本的に「主」と「従」のテーブル中のレコードが一対一で結ばれる場合、「主」から見て「従」へのリレーションを作成する場合にhasOne、「従」から見て「主」へのリレーションを作成する場合にbelongsToと使う(厳密には違うような気がするけど大体これでいいと思う)。例えばユーザIDのテーブルと、そのユーザのプロパティを格納したテーブルであれば、ユーザIDのテーブルを「主」、プロパティのテーブルを「従」とみなすことができる。

■hasMany
こちらは「親」と「子」と表現するほうがよさそう。「親」テーブルのレコード1つに対して「子」テーブルの複数のレコードが該当するような感じ。1対多の関係になっているタイプ。

■hasAndBelongsToMany
これはちょっと複雑。例えば「人間」と「検索エンジン」というテーブルの組み合わせを考える。Aという人間はgoogleとyahooを使う。Bという人間はyahooとaskを使う。こういう具合に多対多のリレーションを考えるとき、間にもう一つテーブルを入れればわかりやすい。つまり関係を表すデータのみをもつテーブルだ。hasAndBelongsToManyはこういうテーブルをあらわすことに使う。

ここの使い方はまた別途メモする(かもしれない)。

複数のテーブルを使う

2007/04/02 | cakePHP

cakePHPで、あるコントローラーから、互いに関連しない(associationがない)複数のテーブルを使用する方法(トップページとか、いろんな情報を見出し的に表示するような場合)。

使用するテーブルについてはモデルをあらかじめ作成しておく。
コントローラー内で、使用したいモデルを以下のように列挙する(未検証)。

$uses=array(‘model1′,’model2’…….);


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net