Как на yii написать аналогичный запрос sql?

SELECT distinct
post.id as id,
post.authorID as authorID
FROM post left OUTER JOIN comment ON post.id = comment.postID
WHERE comment.authorID <>1;


или может можно как-то написать на чистом sql и скормить в dataprovider как query вместо текущего запроса?:

$dataProvider = new ActiveDataProvider([
                    'query' => Post::find()->where(['activateStatus' => 1])->andWhere(['closedDate' => NULL])->orderBy('rating DESC'),
                    'pagination' => [
                        'pageSize' => 20,
                    ],
                ]);
  • Вопрос задан
  • 119 просмотров
Пригласить эксперта
Ответы на вопрос 2
slo_nik
@slo_nik Куратор тега Yii
Доброй ночи.
Есть SqlDataProvider.
Вот статья по использованию join в ActiveRecord
Ответ написан
proudmore
@proudmore
Смотрите:
метод find() - вызываемый у AR объекта возвращает AR.

В вашем коде:
$query = (new Query())->select([
                    'post.id' => 'id',
                    'post.authorID' => 'authorID',
                    'post.title' => 'title',
                    'post.content' => 'content',
                ])
                    ->distinct()
                    ->from('post')
                    ->leftJoin('comment', '`comment`.`postID` = `post`.`id`')
                    ->where(['comment.authorID' => 1])
                    ->with('comments')
                    ->all();

Ошибка в том, что когда вы создаете запрос через new yii\db\Query - то у вас тип результата - массив, а не AR. А метод with есть только у AR объектов, причем сработает он только тогда, когда у вас есть объявленный геттер для запрашиваемого свойства. В данном конкретном случае, вам нужно метод with() вам не нужен
в принципе, вы уже сделали join таблицы. Что же касается запроса, то нижеприведенный код сгенерирует следующий SQL:
SELECT DISTINCT 
"post"."id" AS "id", 
"post"."authorID" AS "authorID",
"post"."title" AS "title", 
"post"."content" AS "content" 
FROM "post" 
LEFT JOIN "comment" ON `comment`.`postID` = `post`.`id` 
WHERE "comment"."authorID"<>1

$query = (new Query())
            ->select([
                'id' => 'post.id',
                'authorID' => 'post.authorID',
                'title' => 'post.title',
                'content' => 'post.content',
            ])->distinct()
            ->from('post')
            ->leftJoin('comment', '`comment`.`postID` = `post`.`id`')
            ->where(['<>','comment.authorID', 1]);


Также вы можете создавать кастомные запросы следующим образом:
Yii::$app->db->createCommand('SELECT distinct
post.id as id,
post.authorID as authorID
FROM post left OUTER JOIN comment ON post.id = comment.postID
WHERE comment.authorID <> :author_id;', [':author_id' => 1])


P.S. Если вы хотите вернуть именно ActiveDataProvider - то имейте ввиду, что передать ему как query нужно именно объект ActiveQuery, который, в свою очередь, возвращает AR. Следовательно, вызываться должен методом find(), о котором шла речь в самом начале. Я бы предложил вам в данном конкретном случае использовать SqlDataProvider, как правильно сказал slo_nik, либо же ArrayDataProvider, но тогда вы всегда будете загружать в память все объекты, которые есть у вас в базе, вне зависимости от пагинации. Это весьма затратно и лучше этого избегать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы