【CakePHP,MySQL】アソシエーションしたモデルの取得件数制限
- 評価
- クリップ 1
- VIEW 2,386
Modelは他のViewで一覧取得しているため、Modelのconditionで取得メッセージの制限はしたくありません。
そのためコントローラの処理で件数を制限して取得したいです。
UsersController.php
public function find_user(){
$message = null;
$result = false;
if($this->request->is('post')) {
if(!empty($this->request->data['User']['word'])){
$findListName = null;
$this->set('findWord',$this->request->data['User']['word']);
$findWord = '%'.$this->request->data['User']['word'].'%';
$findListName = $this->User->find('list',array(
'conditions' => array('OR' => array(
'User.username LIKE' => $findWord,
'User.name LIKE' => $findWord)),
'fields' => array('User.id')
));
$this->set('resultList',$this->User->find('all',array(
'conditions' => array('AND' => array(
'User.id' => $findListName)),
'Message' => array('limit' => 1)
)));
$message = '検索結果を表示します。' ;
return $this->render('find_user_result');
//return(処理をここで終わらせる)render(処理を元の処理ではなく、値のURLに飛ばす。
} else {
$message = '検索ワードを入力してください。';
}
}
$this->Session->setFlash($message);
}
$this->set('resultList',$this->User->find('all',array(
'conditions' => array('AND' => array(
'User.id' => $findListName)),
'Message' => array('limit' => 1)
上記の処理を実行すると、viewのdebug($resultList)では全件戻ってきます。
'Message' => array('limit' => 1)を
'limit' => array('Message' => 1)と入力すると下記のようにユーザー1件分しか戻ってきません。Messageは1件でユーザーリストは全件返したいです。
array(
(int) 0 => array(
'User' => array(
'password' => '*****',
'id' => '41',
'username' => 'satoshii',
'name' => 'さとし1',
'mail' => 'satoshi@gmail.com',
'hidden_flag' => false,
'created' => '2015-06-21 23:03:00'
),
'Message' => array(
(int) 0 => array(
'id' => '24',
'u_id' => '41',
'murmur' => 'つぶやきuser41つぶやき2個',
'created' => '2015-06-18 18:12:00'
),
(int) 1 => array(
'id' => '23',
'u_id' => '41',
'murmur' => 'つぶやきuser41つぶやき1個',
'created' => '2015-06-18 12:12:00'
)
)
)
)
ここの処理で、最新のメッセージ1件のみを取得する方法がいまいちわかりません。
ちなみにMessageモデルとUserモデルを連結した時にMessage.createdでDESCしているので、順序は最新のつぶやき順になっているので、頭の1件だけ取得するような処理であれば大丈夫なはずです。
一応ですが、下記がモデルになります。
App::uses('AppModel', 'Model');
class Message extends AppModel {
public $name = 'Message';
public $primaryKey = 'id';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'u_id',
'order' => 'Message.created DESC'
));
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+2
勘違いで申し訳ございません。
>DaisukeKawabata様
bindModelというのがあるのですね。大変勉強になりました。
今回は私の質問が間違っていましたが、今回の方法に合致する方法で具体的だったのでベストアンサーとさせて頂きました。ありがとうございました。
>takayukiinaba様
ご回答ありがとうございました。
<?php
App::uses('AppModel', 'Model');
class User extends AppModel {
public $name = 'User';
public $primaryKey = 'id';
public $hasMany = array(
'Message' => array(
//
'className' => 'Message',
'foreignKey' => 'u_id',
'order' => 'Message.created DESC',
'limit' => '1'
));
//入力チェック機能
public $validate = array(
'username' => array(
array(
'rule' => 'isUnique', //重複禁止
'message' => '既に使用されている名前です。'
),
array(
'rule' => 'alphaNumeric', //半角英数字のみ
'message' => 'UserIDは半角英数字にしてください。'
),
array(
'rule' => array('between', 2, 32), //2~32文字
'message' => 'UserIDは2文字以上32文字以内にしてください。'
)
),
'password' => array(
array(
'rule' => 'alphaNumeric',
'message' => 'パスワードは半角英数字にしてください。'
),
array(
'rule' => array('between', 8, 32),
'message' => 'パスワードは8文字以上32文字以内にしてください。'
)
),
'mail' => array(
array(
'rule' => 'isUnique',
'message' => 'すでに登録されてあるメールアドレスです。'
),
array(
'rule' => 'email',
'message' => 'メールアドレスの形式で入力してください。'
)
),
'name' => array(
array(
'rule' => 'notEmpty',
'message' => '他のユーザーに表示するお名前を入力してください。'
)
)
);
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
return true;
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
Model上の(共通の)定義を変えたくないということであれば、下記のように、UserがhasManyしている関係を、Controller内でfindする直前に再定義してあげればいいのではないでしょうか?
$this->User->bindModel(array(
'hasMany' => array(
'Message' => array(
'className' => 'Message',
'foreignKey' => 'u_id',
'order' => 'Message.created DESC',
'limit' => 1
)
)));
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
また、Messageテーブルで日付ソートを行っているので2テーブルを結合して取得する方法だと後々SQL実行時間が長くなるのではないかと思います。
私であれば、UserテーブルとMessageテーブルを別々で取得する方法を選択します。
また、一点気になったのですがMessageモデル内に、$belongsToで条件を設定しています。
こちらですが、モデル内ではなくコントローラ内で指定した方が汎用性があるのではないかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.09%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる