質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • MySQL

    7290questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • CakePHP

    2578questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

【CakePHP,MySQL】アソシエーションしたモデルの取得件数制限

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,775

ichinohetomo

score 3

UserモデルとMessageモデルを結合してリストを取得した時に、ユーザーの最新のメッセージ1件のみに制限してViewにリストを渡したいです。

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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

大変申し訳ございませんでした。そもそも掲示したmodelがMessageモデルで一覧取得に使っているモデルで、勘違いで載せてしまいました。後から見直したところ、検索で使用しているモデルはUserモデルで下記の通り、一行'limit' => 1 を追加して解決しました。

勘違いで申し訳ございません。

>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
        )
    )));

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/27 21:13

    $this->User->unbindModel する必要が有るかもしれないですね。

    キャンセル

  • 2015/06/28 10:28

    掲示したModelが間違っておりました。大変申し訳ございませんでした。
    教示して頂いた内容は大変ためになったので、ベストアンサーとさせて頂きました。
    <(_ _)>

    キャンセル

0

こちらについてですが、そもそもテーブル構成上、UserテーブルとMessageテーブルの関係が1対Nの場合を考えると、その2テーブルを結合して取得する必要があるのでしょうか?
また、Messageテーブルで日付ソートを行っているので2テーブルを結合して取得する方法だと後々SQL実行時間が長くなるのではないかと思います。

私であれば、UserテーブルとMessageテーブルを別々で取得する方法を選択します。

また、一点気になったのですがMessageモデル内に、$belongsToで条件を設定しています。
こちらですが、モデル内ではなくコントローラ内で指定した方が汎用性があるのではないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • MySQL

    7290questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

  • CakePHP

    2578questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。