HOME>WEBプログラム覚書>[CakePHP2.X] hasAndBelongsToMany(HABTM)関係にあるモデルのconditions
[CakePHP2.X] hasAndBelongsToMany(HABTM)関係にあるモデルのconditions
つい最近わかった。
ブログを例にして投稿(Post)とタグ(Tag)がhasAndBelongsToManyの関係にあるとします。
でもってタグ「iPad」のページに「iPad」のタグが付いた投稿を表示させることは簡単ですよね。
Controller/TagsController.php
<?php
class TagsController extends AppController {
public function view()
{
if (isset($this->request->params['slug'])) {
$tag = $this->Tag->find(
'first',
array(
'conditions' => array(
'Tag.slug' => $this->request->params['slug'],
),
)
);
$this->set('posts', $tag['Post']);
}
}
}
?>
こんな感じでアクションを作成して /tags/view/ipad にアクセスすると iPad のタグがついた投稿を表示することができます。
では「iPad」のタグが付いていて、投稿のステータスが「公開」になっている
投稿を表示させるにはどうすればよいでしょう?
Controller/TagsController.php
<?php
class TagsController extends AppController {
public function view()
{
if (isset($this->request->params['slug'])) {
$tag = $this->Tag->find(
'first',
array(
'conditions' => array(
'Tag.slug' => $this->request->params['slug'],
'Post.publish' => 1,
),
)
);
$this->set('posts', $tag['Post']);
}
}
}
?>
こんな感じに書きたくなりますが、これはエラーになります。なので、
Controller/TagsController.php
<?php
class TagsController extends AppController {
public function view()
{
if (isset($this->request->params['slug'])) {
$tag = $this->Tag->find(
'first',
array(
'conditions' => array(
'Tag.slug' => $this->request->params['slug'],
),
)
);
// 公開の投稿のみ取得する
$posts = array();
foreach ($tag['Post'] as $post) {
if ($post['publish'] == 1) {
$posts[] = $post;
}
}
$this->set(compact('tag', 'posts'));
}
}
}
?>
のようにコントローラーでforeachするとか
最悪なことにビューでif文とかやっちゃってましたw
でも実は下記のようにモデルの hasAndBelongsToMany プロパティに条件を追加することで
hasAndBelongsToMany相手の検索条件を設定できるようです。
Controller/TagsController.php
<?php
class TagsController extends AppController {
public function view()
{
if (isset($this->request->params['slug'])) {
// Postの条件追加
$this->Tag->hasAndBelongsToMany['Post']['conditions'] = array('Post.publish' => 1);
$tag = $this->Tag->find(
'first',
array(
'conditions' => array(
'Tag.slug' => $this->request->params['slug'],
),
)
);
// foreach 不要
$this->set('posts', $tag['Post']);
}
}
}
?>
注意点としてはパフォーマンスは調べてないのでわかりませんが、変なクエリ発行して遅くなるかもしれませんw
また再度findする場合、Model::$hasAndBelongsToMany に設定した検索条件は残るので不要であれば初期化しましょう。
実行Verは2.3.8です。
以下は上記の例での各モデルのサンプルです。特に何もしてません。
Model
Model/Post.php
<?php
class Post extends AppModel {
public $hasAndBelongsToMany = array(
'Tag' => array(
'className' => 'Tag',
'joinTable' => 'posts_tags',
'foreignKey' => 'post_id',
'associationForeignKey' => 'tag_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
?>
Model/Tag.php
<?php
class Tag extends AppModel {
public $hasAndBelongsToMany = array(
'Post' => array(
'className' => 'Post',
'joinTable' => 'posts_tags',
'foreignKey' => 'tag_id',
'associationForeignKey' => 'post_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
?>
Model/PostsTag.php
<?php
class PostsTag extends AppModel {
/**
* belongsTo associations
*
* @var array
*/
public $belongsTo = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'post_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Tag' => array(
'className' => 'Tag',
'foreignKey' => 'tag_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
?>
投稿日 |
2013年11月14日 00:39 |
カテゴリ |
PHP |
タグ |
CakePHP |
トラックバック URL |
http://www.kantenna.com/cgi-bin/mt504/mt-tb.cgi/1333 |
フィードバック
2016年3月 3日 12:53 | 返信
参考になりました。ありがとうございます。