Как установить модель Laravel Eloquent через 3+ таблицы - PullRequest
0 голосов
/ 15 июня 2019

В настоящее время я работаю над очень простой проблемой трех таблиц / моделей в Laravel и при правильной настройке Eloquent протекает мой мозг.

COLLECTION -> coll_id, ...

ITEM -> item_id, coll_id, type_id, ...

TYPE -> type_id, ...

Я могу сформулировать это тысячью способов, но не могу начать концептуализировать соответствующие отношения Eloquent:

У КОЛЛЕКЦИЙ много ЭЛЕМЕНТОВ, у каждого ТИПА есть.Или, ПУНКТ принадлежит одной КОЛЛЕКЦИИ, ТИПЫ связаны со многими ПУНКТАМИ.

Для меня КОЛЛЕКЦИЯ и ПУНКТ являются ключевыми, в то время как ТИП является действительно дополнительными справочными данными по данному ПУНКТУ;в основном это категория для элемента.

Моя цель - создать решение, в котором пользователи создают КОЛЛЕКЦИИ, добавляют ЭЛЕМЕНТЫ в эти КОЛЛЕКЦИИ, и эти ЭЛЕМЕНТЫ связаны с одним из многих ТИПОВ (которые они также определяют).

Я знаю, что этот пример не далек от других Автор, Книга, Категория;или примеры «Город», «Штат», «Страна», но реализация этих каркасов моделей не создает полное соединение из «ТИП КОЛЛЕКЦИИ <-> ЭЛЕМЕНТ <->» и, скорее всего, завершается неудачно при попытке связать ТИПЫ в СБОРКЕ.

Модели

COLLECTION

class Collection extends Model
{
    protected $guarded = [];

    public function items()
    {
        return $this->hasMany(Item::class);
    }

    public function types()
    {
        return $this->hasManyThrough(Type::class, Item::class);
    }

}

ITEM

class Item extends Model
{
    public function collection()
    {
        return $this->belongsTo(Collection::class);
    }

    public function type()
    {
        return $this->belongsTo(Type::class);
    }
}

TYPE

class Type extends Model
{
    public function item()
    {
        return $this->hasMany(Item::class);
    }

}

Эти модели имеют пункт COLLECTION <-> в обоих направлениях, работающий хорошо,но колеса отваливаются, когда я пытаюсь интегрировать ТИП.В зависимости от 1000 вариантов, которые я попробовал, я либо получаю NULL в Tinker, либо он ищет ITEM_ID в TYPE, которого нет и не должно существовать.

Каким будет решение для точного обновления моделиотражать ПУНКТЫ, имеющие один ТИП и возможный набор ТИПОВ в КОЛЛЕКЦИИ?

Заранее спасибо!


ОБНОВЛЕНИЕ: Рабочее решение вложенное - первичное решение ответапоказывал 2 отношения при КОЛЛЕКЦИИ, нет вложенности:

class Collection extends Model
{
    protected $guarded = [];

    public function items()
    {
        return $this->hasMany(Item::class);
    }
class Item extends Model
{
    public function collection()
    {
        return $this->hasOne(Collection::class);
    }

    public function type()
    {
        return $this->belongsto(Type::class);
    }
}
class Type extends Model
{
    public function items()
    {
        return $this->hasMany(Item::class);
    }
}
$collection->load('items.type');

        dd($collection);
Collection {#280 ▼
  #guarded: []
  #connection: "mysql"
  #table: "collections"
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #attributes: array:5 [▶]
  #original: array:5 [▶]
  #changes: []
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  **#relations: array:1** [▼
    "items" => Collection {#285 ▼
      #items: array:2 [▼
        0 => Item {#288 ▼
          #connection: "mysql"
          #table: "items"
          #primaryKey: "id"
          #keyType: "int"
          +incrementing: true
          #with: []
          #withCount: []
          #perPage: 15
          +exists: true
          +wasRecentlyCreated: false
          #attributes: array:13 [▶]
          #original: array:13 [▶]
          #changes: []
          #casts: []
          #dates: []
          #dateFormat: null
          #appends: []
          #dispatchesEvents: []
          #observables: []
          **#relations: array:1** [▼
            "type" => Type {#296 ▶}
          ]
          #touches: []
          +timestamps: true
          #hidden: []
          #visible: []
          #fillable: []
          #guarded: array:1 [▶]
        }
        1 => Item {#289 ▶}
      ]
    }
  ]

Ответы [ 2 ]

2 голосов
/ 15 июня 2019

HasManyThrough неправильная связь между коллекцией и типом. HasManyThrough похоже на связывание 2 HasMany отношений вместе:

Country -> State -> City

Обратите внимание, как все стрелки идут в одну сторону. Это потому, что у Сити есть внешний ключ для государства, а у штата - внешний ключ от страны.

Ваши отношения выглядят так:

Collection -> Item <- Type

Таким образом, у Item есть внешние ключи как для Collection, так и для Type. В этом случае отношение между Collection и Type на самом деле BelongsToMany, а таблица Item является таблицей соединений.

https://laravel.com/docs/5.8/eloquent-relationships#many-to-many

class Collection extends Model
{
    protected $guarded = [];

    public function items()
    {
        return $this->hasMany(Item::class);
    }

    public function types()
    {
        // Substitute your table and key names here
        return $this->belongsToMany(Type::class, 'items_table', 'coll_id', 'type_id');
    }

}

class Type extends Model
{
    public function items()
    {
        return $this->hasMany(Item::class);
    }

    public function collections()
    {
        // Substitute your table and key names here
        return $this->belongsToMany(Collection::class, 'items_table', 'type_id', 'coll_id');
    }

}

class Item extends Model
{
    public function collection()
    {
        return $this->belongsto(Collection::class);
    }

    public function type()
    {
        return $this->belongsto(Type::class);
    }
}

Если вы хотите получить коллекции с их элементами и соответствующим типом для каждого элемента, вы можете сделать:

Collection::with(['items.type'])->get();
0 голосов
/ 15 июня 2019

Сначала вы можете вызвать предмет, а затем выяснить тип предмета через ваши отношения.

public function getCollectionOfItemsBaseOnType($type){

$collections = Collection::all();
$items = [];
  foreach($collections as $collection){
   if($collection->item->type == $type){
       array_push($items, $collection->item);    
   }
  }
}
return $items;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...