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

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

ただいまの
回答率

88.91%

CakePHP3 各グループ内の最新レコードを得たい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 2,740

takingshape

score 10

前提・実現したいこと

コントローラ内でTableRegistry::getを使用して各物件マスターテーブル(Places)と,その各物件からのレポートが毎日追加されるデータテーブル(Data)を取得しております。

各物件(Placeテーブルの各レコード)に対してDataテーブルの最新のレコード一件を結合させたいのですが,粘りましたが上手く行きませんでしたので,こちらでお教えいただこうと思いました。

グループ化によりどのように最新レコードを取得できるか,お教えいただけたら助かります。

Places
ID
name
name_kana
created
modified
Data
ID
place_id
staff_amount_morning
key_check_morning
staff_amount_evening
key_check_evening
created
modified

発生している問題・エラーメッセージ

今place_idをグループ化する事でplace_idで紐づくDataテーブルのレコードを一つづつに絞るところまでは出来ました。
しかし,グループ化で抽出されたplace_idグループごとのデータが最新のものに出来ません。
(最新でないデータが選ばれてしまいます。)

該当のソースコード

↓以下は前述の通り,place_id毎に一つずつDataテーブルから取得できているソースです。

public function initialize()
     {
         parent::initialize();
         $this->places = TableRegistry::get('Places');
         $this->data = TableRegistry::get('Data');
    }

    public function occupancy()
    {
        $data = $this->data->find()
            ->contain(['Places'])
            ->group('place_id')
            ->all();

        $this->set('data', $data);
        $this->set('_serialize', ['data']);
    }


↓以下は上記のソースにhavingで条件を付け足して最大値レコードの取得を試みているものですが,結果は空になってしまいます。

public function initialize()
     {
         parent::initialize();
         $this->places = TableRegistry::get('Places');
         $this->data = TableRegistry::get('Data');
    }

    public function occupancy()
    {
        $data = $this->data->find()
            ->contain(['Places'])
            ->group('place_id')
            ->having(['max(Data.id)' => 'Data.id'])
            ->all();

        $this->set('data', $data);
        $this->set('_serialize', ['data']);
    }

試したこと

SQLですとinnerJoinを用いて最新のデータ取得等のソース情報がありましたので,CakePHPの書き方に直してみようと試行錯誤しましたが,どうも的外れの様でマニュアルを見ても上手く組むことが出来ずあきらめました。
恐縮ですが,抽出条件の書き方の基本が残念ながら分かっていないようです。

またCakePHP3のクエリビルダを用いてオプションとしてOrderを記載してIDで降順にすることもしてみましたが,配列の並び替えが変わってしまい,グループ化されるデータの並び替え?には影響しないようでした。素人コメントで申し訳ございません。

補足情報(言語/FW/ツール等のバージョンなど)

PHP7,CakePHP3

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

stackoverflowに類似の質問があり、詳しい解説が載っていましたので参考にしてください。

How to limit contained associations per record/group?

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/04 12:50 編集

    教えていただき,どうもありがとうございます。
    Model(Table)の方で制限する方法だと理解できました。
    大変近い参考情報をありがとうございます。ただ,私の力量ゆえ残念ながらまだ上手く出来ておりません。

    Modelの方でDataテーブルをグループごとに1件ずつと制限してしまうと,Controllerの他のアクションでも共有したい場合に困ってしまうように思うのですが,どうなのでしょうか。
    (私が知らないだけかもしれません)

    今回他のアクションではすべてのDataテーブル情報を取得する必要があるのですが,教えて頂いたサイトの方法(一番参考になるとされている投稿の1-3番目の方法)で組んだ場合,やり方によってはそういう取得を同時に同じモデルから行うことができますでしょうか。

    キャンセル

  • 2017/04/04 14:19

    できますよ。
    アソシエーションの名前はテーブルクラス名とは別の名前で定義することができます。
    最新の1件に絞ったものをLastetDataとして、条件を絞っていないものをDataとして定義すればいいと思います。別の名前をつけた場合、元のクラス名をclassNameというオプションで指定します。
    $this->hasOne('LatestData', ['className' => 'Data']);

    キャンセル

  • 2017/04/10 12:41

    お返事が遅くなりましてすみません。
    ご親切に教えて下さり、どうもありがとうございます。
    時間が無くまだ試せていないのですがこれで出来そうです。
    ありがとうございました!

    キャンセル

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

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

関連した質問

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