#mysql #laravel #eloquent
Вопрос:
У меня есть столик tariff_groups
:
ID | Имя |
---|---|
1 | Зеленые тарифы |
2 | Синие тарифы |
3 | Красные тарифы |
и у меня есть таблица things_usage_tariffs
, которая определяет, какие вещи используют, какие тарифы тарифной группы:
ID | thing_id | тарифная группа | Описание | дельта |
---|---|---|---|---|
1 | 1 | 1 | Хороший тариф Зеленой группы. | 0 |
2 | 1 | 1 | Еще более приятный тариф Зеленой группы. | 1 |
3 | 1 | 1 | Лучший зеленый тариф. | 2 |
4 | 1 | 2 | Классный синий тариф. | 3 |
5 | 1 | 3 | Удивительный красный тариф. | 4 |
С помощью этого кода я получаю все тарифы thing
, которые с id
1:
$tariffs = DB::table('things_usage_tariffs')
->where(
[
'thing_id' => $id,
]
)
->orderBy('delta', 'asc')
->get()
->groupBy('tariff_group')
;
Который возвращает:
IlluminateSupportCollection {#1257 ▼
1 => IlluminateSupportCollection {#1247 ▼
#items: array:4 [▶]
}
2 => IlluminateSupportCollection {#1253 ▼
#items: array:1 [▶]
}
3 => IlluminateSupportCollection {#1246 ▼
#items: array:1 [▶]
}
}
Это круто, но я хотел бы знать, как изменить запрос, который я получаю напрямую:
IlluminateSupportCollection {#1257 ▼
'Green tariffs' => array(4)
'Blue tariffs' => array(1)
'Red tariffs' => array(1)
}
Я знаю, что мог бы повторить результат и заменить цифровые клавиши их соответствующим названием тарифной группы, но для этого мне нужно было бы сделать другое заявление, в котором будут указаны имена, и я чувствую, что это можно сделать с помощью соединения. Есть какие-нибудь идеи?
Комментарии:
1. Один из простых способов-использовать красноречие в правильных отношениях.
Ответ №1:
С красноречивыми и правильными отношениями:
Две модели:
class TariffGroup extends Model{
public function thingsUsageTariffs(){
return $this->hasMany(ThingsUsageTariff::class, 'tariff_group', 'id');
}
}
class ThingsUsageTariff extends Model{
public function tariffGroup(){
return $this->belongsTo(TariffGroup::class, 'id', 'tariff_group');
}
}
Теперь в вашем контроллере:
$tariffs = TariffGroup::with(['thingsUsageTariffs' => function($query){
return $query->orderBy('delta', 'asc');
}])->get();
должно получиться что-то похожее на то, чего вы хотите достичь.
Если вы хотите использовать таблицы без моделей, одним из подходов может быть объединение таблиц, затем применение по группам и keyBy
определение ключей для групп:
$tariffs = DB::table('things_usage_tariffs')
->join('tariff_groups', 'tariff_groups.id', '=', 'things_usage_tariffs.tariff_group')
->orderBy('things_usage_tariffs.delta', 'asc')
->get()
->groupBy('tariff_group')
->map(function ($group) {
return $group->keyBy('name');
});
Этот результат должен быть ближе к желаемому результату.
Примечание: Имя должно быть уникальным, так как мы назначаем его в качестве ключей. Кроме того, этот код не тестируется, но я надеюсь, что это укажет вам правильное направление.
Комментарии:
1. Так что это не очень просто без использования моделей? Только с помощью конструктора запросов?
2. кроме того, это приводит к ошибке «mb_strpos() ожидает, что параметр 1 будет строковым, заданным объектом».
3. @Alex исправлено с помощью метода, чтобы исправить эту ошибку.
4. @Alex также добавил альтернативный метод, который не использует модели.
5. спасибо за ваши усилия. в итоге я создал модель тарифов и, используя сводные данные, я вроде как близок к тому, что мне нужно.