CakePHP3でhasManyの取得件数を制限する

標準

Posts hasMany Comments の関係で、最新のCommentsを3件だけ紐付けて取得したい場合を考える。

1. containに書く方法

再利用を考えなければ以下のように、containでクエリを書けばよい。

$Posts->find()
    ->contain([
        'Comments' => function (\Cake\ORM\Query $query) {
            // 最新3件
            return $query->orderDesc('Comments.posted_at')->limit(3);
        },
        'Comments.CommentUsers', // <- コメント投稿者
    ]);

2. カスタムファインダーを定義する方法

カスタムファインダーを定義することで、再利用しやすくなる。

CommentsTable に findLatest3 というカスタムファインダーを定義する

class CommentsTable extends Table {
    // ... (snip)
    public function findLatest3(\Cake\ORM\Query $query, array $options)
    {
        return $query->orderDesc($this->aliasField('posted_at'))->limit(3);
    }
    // ... (snip)
}

containでfinderを指定して呼び出す。

$Posts->find()
    ->contain([
        'Comments' => ['finder' => 'latest3'],
        'Comments.CommentUsers', // <- コメント投稿者
    ]);

3. カスタムファインダー+専用アソシエーションを定義する方法

Postsに最新のCommentsを3件取得するアソシエーションを別途定義すると、さらに再利用しやすくなる。

class PostsTable extends Table {
    public function initialize(array $config)
    {
        // ... (snip)
        $this->hasMany('Comments'); // 元のリレーション
        $this->hasMany('LatestComments', [
            'className' => 'Comments',
            'foreignKey' => 'post_id',
            'finder' => 'latest3',
            'propertyName' => 'comments', // propertyNameを設定することで、Commentsリレーションと同プロパティ名で取得できるようにする
        ]);
        // ... (snip)
    }
}

containではLatestCommentsを呼び出す。

$Posts->find()
    ->contain([
        'LatestComments.CommentUsers',
    ]);

コメントを残す

Page optimized by WP Minify WordPress Plugin