Model + related count

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
a.k.
Сообщения: 56
Зарегистрирован: 2014.11.29, 10:39

Model + related count

Сообщение a.k. »

Добрый день.
Имеется две таблицы: news и comment. У каждой новости связь HAS_MANY комментариев. Есть ли возможность получить список новостей + количество комментариев? Вида

id: 1, name: Новость 1, comments: 21
id: 2, name: Новость 2, comments: 0
id: 3, name: Новость 3, comments: 10
Аватара пользователя
anton44eg
Сообщения: 2716
Зарегистрирован: 2012.01.25, 13:37
Откуда: Киев

Re: Model + related count

Сообщение anton44eg »

что-то типа такого

Код: Выделить всё

SELECT news.id, news.name, COUNT(commnets.id)
FROM news
LEFT JOIN comments ON news.id = comments.news_id
GROUP BY  news.id
a.k.
Сообщения: 56
Зарегистрирован: 2014.11.29, 10:39

Re: Model + related count

Сообщение a.k. »

т.е. из коробки нет возможности? по JOIN сделать понятно как
я так понимаю из коробки в 2.1 релиз добавят
https://github.com/yiisoft/yii2/issues/2179
a.k.
Сообщения: 56
Зарегистрирован: 2014.11.29, 10:39

Re: Model + related count

Сообщение a.k. »

И все-таки вопрос остался...Сейчас опишу подробнее.
Я использую yii2 для API мобильного приложения.
Нужно отдавать новости и кол-во комментариев к новости в зависимости от запроса (по дате, по рубрике, старее указанного id, по поисковой строке).

Сам код выглядит так:

Код: Выделить всё

public function actionIndex()
    {
        $query = News::find()->where(['show'=>1]);
        
        $rubric = @$_GET['rubric'];
        $date = @$_GET['date'];
        $lastId = @$_GET['last_id'];
        $search = @$_GET['search'];
        
        $query->andFIlterWhere([
            'rubric' => $rubric,
            'date' => $date,
        ]);
        
        //$query->andFilterWhere(['like', 'text', $search]);        
        
        if($search) {
            $query->andWhere('text LIKE "%' . $search . '%" ' .
                'OR name LIKE "%' . $search . '%"'
            );
        }
        
        if($lastId) {
            $query->andWhere('id < :id', [':id' => $lastId]);
        }                
                                
        return new ActiveDataProvider([
            'query' => $query,
            'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
        ]);
    } 
Как можно вставить LEFT JOIN с таблицей COMMENTS, чтобы комментарии учитывались только если обращение к API приходит с запросом /?expand=comments? Ну и работали с фильтром рубрик, дат, и т.п.?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Model + related count

Сообщение zelenin »

о, господи.
a.k.
Сообщения: 56
Зарегистрирован: 2014.11.29, 10:39

Re: Model + related count

Сообщение a.k. »

Сделал вроде все правильно, но все равно не считает...


Код: Выделить всё

$query = News::find()->select(['news.*, COUNT(comments.id) AS comments'])->joinWith('comments')->groupBy(['news.id'])->where(['show'=>1]);
return new ActiveDataProvider([
            'query' => $query,
            'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
        ]);
        
 // relation:
 
 public function getComments()
    {
        return $this->hasMany(Comments::className(), ['news_id' => 'id']);
    }       
  
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: Model + related count

Сообщение Insolita »

Код: Выделить всё

  $rubric = @$_GET['rubric'];
        $date = @$_GET['date'];
        $lastId = @$_GET['last_id'];
        $search = @$_GET['search'];
        
        ...
         if($search) {
            $query->andWhere('text LIKE "%' . $search . '%" ' .
                'OR name LIKE "%' . $search . '%"'
            );
        }
         
Изображение
Аватара пользователя
Insolita
Сообщения: 788
Зарегистрирован: 2011.06.06, 01:39
Контактная информация:

Re: Model + related count

Сообщение Insolita »

http://www.yiiframework.com/doc-2.0/yii ... %29-detail

Код: Выделить всё

public function actionIndex()
    {
        $query = News::find()->where(['show'=>1]);
        $expand=Yii::$app->request->get('expand',null);
        if($expand=='comments'){
           $query->select('{{%news}}.*','{{%comments}}.id','COUNT("{{%comments}}.id") as comments_count');
            $query->joinWith(['comments']);
            $query->groupBy([''{{%news}}.id''])
        }else{
           //Чё-нибудь другое
        }
        $rubric = Yii::$app->request->get('rubric',null);
        $date = Yii::$app->request->get('date',null);
        $lastId = Yii::$app->request->get('lastid',null);
        $search = Yii::$app->request->get('search',null);
        
        $query->andFilterWhere([
            'rubric' => $rubric,
            'date' => $date,
        ]);
        
        $query->andFilterWhere(['like', 'text', $search])
                  ->orFilterWhere('like','name',$search);         
        
        $query->andFilterWhere('id < :id', [':id' => $lastId]);
                                         
        return new ActiveDataProvider([
            'query' => $query,
            'sort'=> ['defaultOrder' => ['id'=>SORT_DESC]]
        ]);
    } 
Что-то типа так (алиасы поправить), но лучше всё это делать в модели (блин специально же так замечательно придумали дополнительные поисковые модели для этого всего - зачем это в контроллер вообще лепить) так как для вывода еще в модель

Код: Выделить всё

   public function attributes()
    {
        return array_merge(parent::attributes(), ['{{%comments}}.comments_count']);
    }
 
а вообще по JoinWith связь comments должна подгрузиться и можно количество комментов как count($model->comments) получить кажись где то это прокатывало
Ответить