Laravel Query Builder с полиморфами c объединения не работают на SQLite - PullRequest
0 голосов
/ 20 января 2020

У меня большой запрос Laravel Query Builder, и вот его минимальная версия

$query = DB::table('trainings')
            ->select(
                'trainings.id as training_id as training_id',
                'taggables.id as taggables_id',
                'taggables.tag_id as taggables_tag',
                'tags.id as tags_id',
                DB::raw('GROUP_CONCAT(tags.category) as tags_category'),
                DB::raw('GROUP_CONCAT(tags.value) as tags_value')
            )
            ->join('taggables', function($join) {
                $join->on('taggables.taggable_id', 'trainings.id')
                    ->where('taggables.taggable_type', 'App\\Training')
                ;
            })
            ->leftjoin('tags','tags.id','=','taggables.tag_id')
            ->groupBy('trainings.id')
            -get()
            ;

, которая генерирует это sql:

select trainings.id as training_id,
taggables.id as taggables_id, 
taggables.tag_id as taggables_tag, 
tags.id as tags_id, 
GROUP_CONCAT(tags.category) as tags_category, 
GROUP_CONCAT(tags.value) as tags_value 

from trainings 

inner join taggables on taggables.id = trainings.id and taggables.taggable_type = "App\\Training"
left join tags on tags.id = taggables.tag_id 

group by trainings.id

, и результат :

enter image description here

Когда я запускаю один и тот же код в тесте phpunit (с другими данными + sqlite), результаты выглядят так:

array:1 [
  0 => {#2579
    +"training_id": "2"
    +"taggables_id": "1"
    +"taggables_tag": "{"value":1,"category":1,"id":1}"
    +"tags_id": null
    +"tags_category": null
    +"tags_value": null
  }
]

По какой-то причине «taggables_tag» возвращает JSON / объект данных таблицы связанных тегов, а также поля tags_ пустые (возможно, из-за того, что последнее соединение не работает).

Есть идеи, как это исправить?

ОБНОВЛЕНИЕ

Проблема в соединении, а не в group_concat:

$query = DB::table('trainings')
            ->join('taggables', function($join) {
                $join->on('taggables.taggable_id', 'trainings.id')
                    ->where('taggables.taggable_type', 'App\\Training')
                ;
            })
            ->get()

Returns:
    +"tag_id": "{"value":1,"category":1,"organisation_id":1,"updated_at":"2020-01-20 10:29:56","created_at":"2020-01-20 10:29:56","id":1}"
    +"taggable_id": "2"
    +"taggable_type": "App\Training"

1 Ответ

0 голосов
/ 20 января 2020

Я смог решить это следующим образом:

// running tests (SQLite) returns json of the related mode
if (App::environment() === 'testing') {
    $query->addSelect('taggables.tag_id->value as taggables_tag_id');
} else {
    $query->addSelect('taggables.tag_id as taggables_tag_id');
}

и изменив последнее левое соединение на ->leftjoin('tags','tags.id','=','taggables_tag_id')

...