#laravel #eloquent-relationship
#laravel #красноречивый-связь
Вопрос:
Объяснение базы данных:
- Элемент имеет много уровней
- Уровень имеет один тип (размер, параметр ИЛИ дополнение)
- тип имеет отношение «многие ко многим» с параметром
- optionType имеет множество размеров и цен
Проблема: в запросе eloquent я могу извлекать данные до option_type, я не знаю, как создать связь сводной модели option_type с моделью размера.
Красноречивый запрос:
$items = Item::with(['tiers' => function ($query) {
$query->with(['type' => function($query) {
$query->with('sizes')
->with('options')
->with('addons');
}]);
}])->where('id', 1)->get();
return $items;
Чего я хочу достичь:
Я хочу с нетерпением загружать option_type с размерами, для каждой строки optiontype у меня может быть size и его цена.
Проблема: когда я пишу запрос, подобный:
$query->with(['options' => function($query) {
$query->with('sizes);
}])
В основном говорится, что параметры имеют отношение к размерам, что неверно, должно быть, optionType имеет отношение к размеру. как я могу получить данные, чтобы я мог показать мне для записи для каждого optiontype_id, size_id и price.
Тип модели:
class Type extends Model
{
protected $table = 'types';
public function options()
{
return $this->belongsToMany(Option::class);
}
}
Модель опций:
class Option extends Model
{
public function type()
{
return $this->belongsToMany(Type::class);
}
}
Модель optionType:
use IlluminateDatabaseEloquentRelationsPivot;
class OptionType extends Pivot
{
protected $table = 'option_type';
public function optiontypesize()
{
return $this->belongsToMany(Size::class, 'option_type_size', 'size_id', 'option_type_id');
}
}
Модель размера:
class Size extends Model
{
public function optiontypesize()
{
return $this->belongsToMany(OptionType::class, 'option_type_size', 'size_id', 'option_type_id');
}
}
Ответ №1:
Я сам решил проблему, я напишу подробный ответ здесь на случай, если кто-то столкнется с такой же проблемой в будущем.
Я изменил базу данных, но концепция проблемы осталась прежней.
Объяснение:
- элементы имеют много уровней
- уровни имеют один тип
- уровни имеют много опций, а параметры имеют много уровней (приведение таблицы option_tier в сцену)
- option_tier имеет много размеров, а sizes имеет много option_tier (приведение таблицы option_tier_price в сцену с дополнительным полем «цена»)
Решения: я использую AjCastro EagerLoadPivotRelations EagerLoadPivotTrait для быстрой загрузки сводных отношений. Концепция взята из этой статьи https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a Единственная разница в том, что я изменил отношения с belongTo
на hasMany
на, и это работает как заклинание.
Модель уровня:
use AjCastroEagerLoadPivotRelationsEagerLoadPivotTrait;
class Tier extends Model
{
use EagerLoadPivotTrait;
protected $table = 'tiers';
public function options()
{
return $this->belongsToMany(Option::class, 'option_tier')
->using(OptionTier::class)
->withPivot('id');
}
}
Модель опций:
use AjCastroEagerLoadPivotRelationsEagerLoadPivotTrait;
class Option extends Model
{
use EagerLoadPivotTrait;
protected $table = 'options';
public function tiers()
{
return $this->belongsToMany(Tier::class, 'option_tier');
}
}
Модель на уровне опций:
use AjCastroEagerLoadPivotRelationsEagerLoadPivotTrait;
use IlluminateDatabaseEloquentRelationsPivot;
class OptionTier extends Pivot
{
use EagerLoadPivotTrait;
protected $table = 'option_tier';
public function price()
{
return $this->hasMany(OptionTierPrice::class, 'option_tier_id');
}
}
Модель OptionTierPrice:
use AjCastroEagerLoadPivotRelationsEagerLoadPivotTrait;
class OptionTierPrice extends Model
{
use EagerLoadPivotTrait;
protected $table = 'option_tier_price';
public function size()
{
return $this->belongsTo(Size::class);
}
}
Контроллер:
$tiers = Product::with(['tiers' => function($query) {
$query->with(['type'])
->with(['sizes'])
->with(['options.pivot.price.size'])
->with(['addons.pivot.price.size']);
}])
->get();
return $tiers;