qudanblog

2009.04.18

HABTMのテーブルの検索とpaginate

CakePHPでハマったのでメモ。バージョンは1.2.0.7296 RC2。
HABTMのテーブルを検索する方法と、そのときのpagenateを正しく取得する方法です。

いわゆるBlogの記事に複数のタグを付けるとして、
以下のようなテーブルがあるとします。
————————————
posts
-id
-title

posts_tags
-post_id
-tag_id

tags
-id
-name
————————————

記事のタイトルとタグの名称の両方をLIKEで検索します。

コントローラのposts_controller.phpのsearchメソッドのなかで、paginateでデータを引っ張ってきます。
paginateのjoinsの指定で、posts_tagsとtagsをINNER JOINしてあげて、conditionsでLIKE検索の条件を渡してあげます。

$joins = array(
	array(
		'table' => 'posts_tags',
		'alias' => 'PostsTag',
		'type' => 'INNER',
		'conditions' => 'PostsTag.post_id = Post.id'
	),
	array(
		'table' => 'tags',
		'alias' => 'Tag',
		'type' => 'INNER',
		'conditions' => 'Tag.id = PostsTag.tag_id'
	)
);
$conditions = array(
	'OR' => array(
		'Post.title LIKE' => '%検索ワード%' ,
		'Tag.name LIKE' => '%検索ワード%' ,
	);
);
$this->paginate = array(
	'joins' => $joins,
	'conditions' => $conditions,
	//複数のpostsが引っかかるので、idでまとめる
	'group' => array('Post.id')
);

このとき、paginateでのページ送り機能が正しく動作しません。
これを回避するためモデルのpost.phpでpaginateCountメソッドを上書きします。取得するデータの総数を返してあげています。マニュアルにもさりげなく書いてあります。

→ 4.9.4 カスタムしたクエリによるページ付け


function paginateCount($conditions, $recursive) { $where = “”; if($conditions){ $db =& ConnectionManager::getDataSource($this->useDbConfig); $where = $db->conditions($conditions); }

$result = $this->query('SELECT Post.id FROM posts AS Post INNER JOIN posts_tags AS `PostsTag` ON (`PostsTag`.`post_id` = `Post`.`id`) INNER JOIN tags AS `Tag` ON (`Tag`.`id` = `PostsTag`.`tag_id`)’ .$where. ' GROUP BY `Post`.`id`’); return count($result); }

ちなみに、CakePHPはSQL文を書かなくてもある程度は自動で組み立てくれたりしてコードを書く量は減るけど、これをやるにはどうするの?という方法を調べるのに時間がかかります。自分の中でノウハウが蓄積されていけば開発スピードは上がりそうです。


2009.03.03

CakePHPで楽に作りたい

PHP用の高速開発フレームワーク「CakePHP」を実戦投入してみました。

導入時の参考書には下記の書籍を使用。CakePHPは1.1系と1.2系での違いが多々ありますので、1.2系を始めようとしている人には、こちらがオススメ。1.1系と1.2系の違いを解説していますので、事前にその違いを頭に入れておけばネット上で情報を検索するときにどっちの情報か迷わずにたどり着けます。(ネット上の情報の数はまだまだ少ないですが。。)

以下、始めてCakePHPで開発した人のメモと雑感。

  • SSHやtelnetを使えないと「Bake」というプログラムの自動生成ができません。主に使用しているレンタルサーバでは、SSHもtelnetも使えないので、ローカルでテスト環境を構築しました。MacならMAMPを使うとに環境整います。(MAMPについても、上記の「CakePHP徹底入門」に書いてあります。)
  • MAMPの環境設定。ポート>Apacheのボートを「80」にすると、http://localhost/でアクセスできるようになる。
  • .htaccessをローカルでも見えとくようにしたいので、隠しファイルを見れる設定に変更。こちらを参照。
  • MAMPのMysqlのデフォルト設定は、「ID: root / PassWord: root」
  • Mac(MAMP)環境だと、データベース接続するホスト名を「localhost」にすると上手く接続できない。なのでhostは「127.0.0.1」、portは「8889」を設定する。
  • Bakeしたファイルを使用して、データをadd(登録)しようとしたら文字化け。どうやらvalidateが日本語対応していないためらしい。validateは自作すること。
  • CakePHPはモデル名やコントローラ名に英単語の単数系/複数形を付けます。その命名に便利なサイト。http://www.cpa-lab.com/tech2/inflects/
  • 恐れずにBakeで自動生成したファイルをガシガシいじること。むしろいじらないとやりたいことが出来ません。
  • CakePHPはMVCパターンを採用しています。BakeするとMVCのファイルが出来上がるので、それをいじっているうちにMVCのデザインパターンが身に付いた気がします。
  • MVC間のやり取りは、配列で行われているので、この配列の構造を理解しておくのがキモ。ここを理解しておけば自由にカスタマイズできる気がする。
  • Bakeで自動生成されるCSSはひどい。
  • SQL文をまったく書かなくても良いので、そこは楽チン。
  • 慣れてくれば、「高速開発」も夢じゃないかも。

Accept as true only
what is indubitable

明証的に真であると認めたもの以外、決して受け入れない事。

Divide every question
into manageable parts

考える問題を出来るだけ小さい部分にわける事。

Begin with the simplest
issues
and ascend to
the
more complex

最も単純なものから始めて複雑なものに達する事。

Review frequently
enough to retain the
whole argument at once

何も見落とさなかったか、全てを見直す事。

René Descartes 1637