Сортировка связанных по промежуточной таблице

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Noobie
Сообщения: 29
Зарегистрирован: 2014.06.03, 13:38

Сортировка связанных по промежуточной таблице

Сообщение Noobie » 2014.07.01, 15:56

Все привет! Только начал изучать Yii.
Ситуация такая, пишу модуль галерея изображений.
В базе есть 3 таблицы

tbl_gallery
с полями:
id, name, url

tbl_images
поля:
id, sml_img, mid_img, big_img

tbl_gallery_images
поля:
id, gallery_id, image_id, sort

В модели Gallery прописываю связь

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

public function getImages()
    {
        return $this->hasMany(\app\models\Image::className(), ['id'=>'image_id'])->viaTable('{{%gallery_images}}', ['gallery_id'=>'id']);
    }
 
И всё в принципе работает, данные есть.

Но мне нужно сделать чтобы связанные изображения сортировались по полю sort из промежуточной таблицы tbl_gallery_images.
Подскажите пожалуйста, как такую сортировку реализовать?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сортировка связанных по промежуточной таблице

Сообщение zelenin » 2014.07.01, 19:27

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

        return $this->hasMany(\app\models\Image::className(), ['id'=>'image_id'])->viaTable('{{%gallery_images}} gallery_images', ['gallery_id'=>'id'])->orderBy('gallery_images.sort');
 
как-то так.

А может и нет - надо тестировать.

Noobie
Сообщения: 29
Зарегистрирован: 2014.06.03, 13:38

Re: Сортировка связанных по промежуточной таблице

Сообщение Noobie » 2014.07.02, 01:20

Неа, так не получается.
Как только встала задача сортировки, сразу попробовал так:

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

public function getImages()
    {
        return $this->hasMany(\app\models\Image::className(), ['id'=>'image_id'])->viaTable('{{%gallery_images}}', ['gallery_id'=>'id'])->orderBy('{{%gallery_images}}.sort');
    } 
выдает ошибку
Database Exception – yii\db\Exception
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'tbl_gallery_images.sort' in 'order clause'
The SQL being executed was: SELECT * FROM `tbl_images` WHERE `id` IN ('1', '2', '3', '4', '5') ORDER BY `tbl_gallery_images`.sort
То есть все таки идет попытка найти это поле в таблице images

codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сортировка связанных по промежуточной таблице

Сообщение codrilla » 2014.07.02, 10:50

Я бы связь оставил как есть, а выборку делал бы следующим образом

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

Gallery::find()->with([
                    'images' => function($query) {
                            $query->orderBy('sort');
                        },
                ]);
 

codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сортировка связанных по промежуточной таблице

Сообщение codrilla » 2014.07.02, 10:53

А в вашем примере надо вероятно писать так:

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

public function getImages()
    {
        return $this->hasMany(\app\models\Image::className(), ['id'=>'image_id'])->viaTable('{{%gallery_images}}', ['gallery_id'=>'id'])->orderBy('sort');
    } 
 

codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сортировка связанных по промежуточной таблице

Сообщение codrilla » 2014.07.02, 10:54

А, виноват, у вас сортировка в связующей таблице, а не в таблице изображений. Тогда мой вариант неверен.

prot
Сообщения: 34
Зарегистрирован: 2013.12.26, 21:02
Контактная информация:

Re: Сортировка связанных по промежуточной таблице

Сообщение prot » 2015.01.12, 10:58

Я тоже ищу решение сортировки связующей таблицы.
Но из ответов так и не понял, как это сделать.

Loveorigami
Сообщения: 974
Зарегистрирован: 2014.08.27, 21:54

Re: Сортировка связанных по промежуточной таблице

Сообщение Loveorigami » 2015.01.12, 11:31

так перенесите sort в tbl_images.
какую особенную функцию sort выполняет в связующей таблице? У вас одна и та же фотография будет находится в разных категориях и иметь разные значения sort?

prot
Сообщения: 34
Зарегистрирован: 2013.12.26, 21:02
Контактная информация:

Re: Сортировка связанных по промежуточной таблице

Сообщение prot » 2015.01.12, 12:02

Это можно сделать.
Но тогда теряется логика в сущностях. Сущность Image - не должна ничего знать о сортировке, ее это не интересует, она отвечает только за фотографию (как минимум id и путь к файлу). А вот Gallery (Gallery_Image) - отвечает за фотографии и сортировку в каждой конкретной Галерее.

aquy
Сообщения: 48
Зарегистрирован: 2014.08.21, 09:35

Re: Сортировка связанных по промежуточной таблице

Сообщение aquy » 2015.01.12, 15:25

Есть еще один не менее интересный вариант, чтобы не задумываться над сложными конструкциями сортировки и фильтрации можно сделать в самой БД нужное представление, из этого представления сгенерировать модель и сеарчмодель и уже сортировать и фильтровать как будто бы это одна таблица.

Loveorigami
Сообщения: 974
Зарегистрирован: 2014.08.27, 21:54

Re: Сортировка связанных по промежуточной таблице

Сообщение Loveorigami » 2015.01.14, 17:02

prot писал(а):Это можно сделать.
Но тогда теряется логика в сущностях. Сущность Image - не должна ничего знать о сортировке, ее это не интересует, она отвечает только за фотографию (как минимум id и путь к файлу). А вот Gallery (Gallery_Image) - отвечает за фотографии и сортировку в каждой конкретной Галерее.
В доках есть еще вариант связи через via(). Может подойдет.
http://www.yiiframework.com/doc-2.0/yii ... %29-detail

andreyrud
Сообщения: 265
Зарегистрирован: 2011.09.26, 14:59

Re: Сортировка связанных по промежуточной таблице

Сообщение andreyrud » 2015.02.03, 14:05

В результате нашли решение или нет?

xtz
Сообщения: 11
Зарегистрирован: 2012.04.02, 18:42

Re: Сортировка связанных по промежуточной таблице

Сообщение xtz » 2015.04.23, 20:36

так что так и не нашли решение?

prot
Сообщения: 34
Зарегистрирован: 2013.12.26, 21:02
Контактная информация:

Re: Сортировка связанных по промежуточной таблице

Сообщение prot » 2015.05.03, 00:06

Нет пока не нашел.
Уже не помню что я сделал. Кажется применил несколько запросов, либо через Query Left Join сделал запрос.

pavlm
Сообщения: 82
Зарегистрирован: 2013.09.02, 16:33

Re: Сортировка связанных по промежуточной таблице

Сообщение pavlm » 2015.05.03, 00:31

вот такой вариант есть:

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

$g = Gallery::find()->with(['galleryImages', 'galleryImages.image'])->one();
$imgs = ArrayHelper::getColumn($g->galleryImages, 'image');
 

Noobie
Сообщения: 29
Зарегистрирован: 2014.06.03, 13:38

Re: Сортировка связанных по промежуточной таблице

Сообщение Noobie » 2015.05.03, 04:43

Я задачу решил, но как именно реализовал сейчас не вспомню. Поищу у себя исходники того проекта, где это реализовывал, выложу.
Точно помню что без join'ов у меня было, но само решение как по мне, являлось костылем.

Noobie
Сообщения: 29
Зарегистрирован: 2014.06.03, 13:38

Re: Сортировка связанных по промежуточной таблице

Сообщение Noobie » 2015.05.03, 05:35

Вот так я реализовал это тогда, в модель Gallery добавил метод getImages, код:

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

    public function getImages()
    {
        if($this->isNewRecord) return false;

        // получаем id изображений, отсортированных по полю 'sort' и формируем условие IN        
        $image_ids = GalleryImage::find()->select('image_id')->asArray()->where('gallery_id='.$this->id)->orderBy('sort')->all();
        $in = '';
        foreach($image_ids as $item){
            $in .= $item['image_id'] .', ';
        }
        $in = trim( trim($in), ', ' );

        $query = new \Yii\db\Query();
        $query->from('{{%images}}');
        $query->where("id IN ($in)");
        $query->orderBy("FIELD (id, $in)");
        $sql = str_replace('`', '', $query->createCommand()->sql);
        $models = \app\modules\gallery\models\Image::findBySql($sql)->all();
        return $models;
    }

Tpona
Сообщения: 218
Зарегистрирован: 2011.06.05, 19:00

Re: Сортировка связанных по промежуточной таблице

Сообщение Tpona » 2015.09.16, 09:56

Где-то нашел вот такой код, но он не работает:

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

public function getSavedQuestions()
    {
        return $this->hasMany(Question::className(), ['id' => 'questionId'])
            ->viaTable('{{%interview_question}}', ['interviewId' => 'id'], function($query){
                return $query->orderBy(['{{%interview_question}}.sort' => SORT_ASC]);
            })->where(['saved' => 1]);
    }
Кто-то нашел решение, как сделать именно связь а не выборку путем построения запроса?

Tpona
Сообщения: 218
Зарегистрирован: 2011.06.05, 19:00

Re: Сортировка связанных по промежуточной таблице

Сообщение Tpona » 2015.09.16, 10:08

Впринципе, как то так можно сделать все работает

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

        return Question::find()
            ->select('{{%question}}.*')
            ->innerJoin( '{{%interview_question}}', '{{%interview_question}}.questionId={{%question}}.id' )
            ->where('{{%question}}.saved=1')
            ->orderBy(['{{%interview_question}}.sort' => SORT_ASC])
            ->all();

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сортировка связанных по промежуточной таблице

Сообщение zelenin » 2015.09.16, 10:22

спросил про связь, а не запрос, ответил сам себе запросом - все работает. ок

Ответить