У меня есть модельный список, который наследуется через его отношение toTo ('Model'), по сути, принадлежит производителю, к которому принадлежит соответствующая модель.
Вот из моей модели листинга:
public function model() { return $this->belongsTo('Model', 'model_id'); } public function manufacturer() { return $this->belongsTo('Manufacturer', 'models.manufacturer_id'); /* $manufacturer_id = $this->model->manufacturer_id; return Manufacturer::find($manufacturer_id)->name;*/ }
и моя модель производителя:
public function listings() { return $this->hasManyThrough('Listing', 'Model', 'manufacturer_id', 'model_id'); } public function models() { return $this->hasMany('Model', 'manufacturer_id'); }
Я могу отозвать имя $ listing-> model-> в представлении, но не $ listing-> manufacturer-> name. Это порождает ошибку. Я попробовал прокомментировать 2 строки в листинговой модели, чтобы получить эффект, поэтому я мог бы повторить $ listing-> manufacturer (), и это сработает, но это неправильно устанавливает их отношения. Как мне это сделать? Благодарю.
Пересмотренная модель листинга (спасибо ответчику):
public function model() { return $this->belongsTo('Model', 'model_id'); } public function manufacturer() { return $this->belongsTo('Model', 'model_id') ->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id'); }
Я нашел решение, но это не слишком прямолинейно. Я разместил его ниже, но я опубликовал то, что я считаю лучшим решением в первую очередь.
Вы не должны иметь доступ к производителю напрямую из списка, так как производитель относится только к модели. Хотя вы можете с нетерпением загружать отношения производителя с объектом листинга, см. Ниже.
class Listing extends Eloquent { public function model() { return $this->belongsTo('Model', 'model_id'); } } class Model extends Eloquent { public function manufacturer() { return $this->belongsTo('manufacturer'); } } class Manufacturer extends Eloquent { } $listings = Listing::with('model.manufacturer')->all(); foreach($listings as $listing) { echo $listing->model->name . ' by ' . $listing->model->manufacturer->name; }
Потребовалось немного финализации, чтобы заставить ваше запрошенное решение работать. Решение выглядит так:
public function manufacturer() { $instance = new Manufacturer(); $instance->setTable('models'); $query = $instance->newQuery(); return (new BelongsTo($query, $this, 'model_id', $instance->getKeyName(), 'manufacturer')) ->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id') ->select(DB::raw('manufacturers.*')); }
Я начал с работы с запросом и создания ответа от этого. Запрос, который я искал для создания, был следующим:
SELECT * FROM manufacturers ma JOIN models m on m.manufacturer_id = ma.id WHERE m.id in (?)
Запрос, который обычно создается, return $this->belongsTo('Manufacturer');
select * from `manufacturers` where `manufacturers`.`id` in (?)
?
будет заменено значением столбцов manufacturer_id
из таблицы списков. Этот столбец не существует, поэтому будет вставлен один 0, и вы никогда не вернете производителя.
В запросе, который я хотел воссоздать, я сдерживал models.id
. Я мог бы легко получить доступ к этому значению в моих отношениях, указав внешний ключ. Таким образом, отношения стали
return $this->belongsTo('Manufacturer', 'model_id');
Это вызывает тот же запрос, что и раньше, но заполняет ?
с model_ids. Таким образом, это возвращает результаты, но в целом неверные результаты. Затем я попытался изменить базовую таблицу, которую я выбирал. Это значение выводится из модели, поэтому я изменил переданную модель на Model
.
return $this->belongsTo('Model', 'model_id');
Мы теперь имитируем отношения модели, так что здорово, что я ничего не получил. Но по крайней мере сейчас, я мог бы присоединиться к таблице производителей. Поэтому я снова обновил отношения:
return $this->belongsTo('Model', 'model_id') ->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id');
Это приблизило нас на один шаг, создав следующий запрос:
select * from `models` inner join `manufacturers` on `manufacturers`.`id` = `models`.`manufacturer_id` where `models`.`id` in (?)
Отсюда я хотел бы ограничить столбцы, которые я запрашивал только для столбцов производителя, для этого я добавил спецификацию выбора. Это привело к:
return $ this-> attribTo ('Model', 'model_id') -> join («производители», «производители.», «=», «models.manufacturer_id») -> select (DB :: raw («производители . * '));
И получил запрос к
select manufacturers.* from `models` inner join `manufacturers` on `manufacturers`.`id` = `models`.`manufacturer_id` where `models`.`id` in (?)
Теперь у нас есть 100% действительный запрос, но объекты, возвращаемые из отношения, имеют тип Model
not Manufacturer
. И вот тут вошла последняя битка. Мне нужно было вернуть Manufacturer, but wanted it to constrain by the
table in the where clause. I created a new instance of Manufacturer and set the table to
моделей table in the where clause. I created a new instance of Manufacturer and set the table to
table in the where clause. I created a new instance of Manufacturer and set the table to
модели и вручную создал отношения.
Важно отметить, что экономия не будет работать .
$listing = Listing::find(1); $listing->manufacturer()->associate(Manufacturer::create([])); $listing->save();
Это создаст новый производитель, а затем обновит listings.model_id
до идентификатора нового производителя.