Почему Yii2 пагинация считает связанные модели?

Yii2 предоставляет пагинацию встроенным функционалом, который упрощает процесс разделения результатов запросов на страницы. Однако, в некоторых случаях, можно заметить, что пагинатор считает связанные модели вместе с основной моделью, что может привести к неправильной подсчету количества страниц.

Причина такого поведения заключается в том, что по умолчанию Yii2 выполняет JOIN запросы, чтобы извлечь связанные модели вместе с основной моделью. Это делается для улучшения производительности при получении релейций с помощью жадной загрузки (eager loading).

Пагинатор в Yii2 использует общее количество записей в запросе для подсчета количества страниц. И поскольку связанные модели также участвуют в запросе, их количество также учитывается пагинатором. Это может привести к неправильному количеству страниц при пагинации.

Чтобы решить эту проблему, можно воспользоваться различными стратегиями в зависимости от конкретной ситуации:

1. Вы можете явно указать, что пагинатор должен считать только основную модель, игнорируя связанные модели. Для этого можно использовать метод count() вместо all(), указав ignoreRelations параметр на true, например:

$count = $query->count("id", true);

2. Еще один способ - это использовать свою собственную логику подсчета количества записей. Вместо того, чтобы полагаться на автоматическое подсчет из ленивой или жадной загрузки, вы можете явно выполнить запрос только для подсчета, игнорируя связи. Например:

$count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM my_table')->queryScalar();

3. Если вы используете жадную загрузку в своем запросе и хотите, чтобы пагинатор правильно подсчитывал количество страниц, то вы можете применить метод afterFind и добавить в нем логику, чтобы уменьшить количество результатов до размера, необходимого для пагинации. Например:

public function afterFind()
{
    parent::afterFind();

    if ($this->isRelationPopulated('relatedModel')) {
        $relatedModels = $this->getRelatedModels();
        $this->relatedModel = array_slice($relatedModels, 0, Pagination::DEFAULT_PAGE_SIZE);
        $this->relatedModelCount = count($relatedModels);
    }
}

Независимо от выбранного способа, важно помнить о том, что Yii2 предоставляет гибкую возможность настройки и переопределения поведения пагинатора и других компонентов фреймворка.