Полиморфные отношения в Laravel 4 — morphOne()

У меня проблемы с созданием полиморфных отношений между двумя моделями:

  • Загрузить
  • Группа

Упрощенная версия групповой модели:

use Cartalyst\Sentry\Groups\Eloquent\Group as SentryGroupModel;

class Group extends SentryGroupModel {

  ...

  /**
   * returns the logo (upload model) from this agency
   *
   * @return Upload
   */
  public function logo()
  {
      return $this->morphOne('Upload', 'uploadable', 'model_type', 'model_id');
  }  

  ...

}

Упрощенная версия модели Загрузка

class Upload extends Eloquent {

  ...

  /**
   * returns the polymorphic relationship
   *
   * @return Upload
   */
  public function uploadable()
  {
      return $this->morphTo('uploadable', 'model_type', 'model_id');
  }  

  ...

}

Как видите, модель Group на самом деле является расширенной моделью Sentry 2 Group, которая является внутренней частью расширенной модели Eloquent.

При вызове отношения в контроллере как таковом:

$agencyGroup->logo->saveUpload('logo');

я получаю ошибку PHP:

Вызов функции-члена saveUpload() для необъекта

Любая помощь с этим?


person AndrewMcLagan    schedule 19.08.2013    source источник
comment
попробуйте $agencyGroup-›logo()-›saveUpload('logo');   -  person Laurence    schedule 19.08.2013
comment
Вы проверили, что $agencyGroup имеет Upload в базе данных? Похоже, вы вызываете $agencyGroup->logo, который возвращает NULL, а затем вызывает NULL->saveUpload('logo').   -  person vFragosop    schedule 20.08.2013
comment
если у меня есть $agencyGRoup->logo(), он возвращает экземпляр Illuminate\Database\Eloquent\Relations\MorphOne, хотя, если я попробую $agencyGRoup->logo()->saveUpload('logo'), я получу другую ошибку, чем раньше: Call to undefined method Illuminate\Database\Query\Builder::saveUpload()   -  person AndrewMcLagan    schedule 20.08.2013
comment
в моем контроллере у меня есть Use Upload   -  person AndrewMcLagan    schedule 20.08.2013


Ответы (1)


Функция logo() возвращает отношение MorphOne, и, поскольку нет метода с именем saveUpload, определенного или MorphOne, она перенаправляет вызов на свой Builder, который также не имеет метода, и выдает второе исключение, с которым вы столкнулись:

Вызов неопределенного метода Illuminate\Database\Query\Builder::saveUpload()

Такое поведение ожидаемо, и именно так работает Eloquent. Вот почему вы должны использовать только logo без (), как вы пытались в первую очередь.

Хотя у вашего $agencyGroup может не быть логотипа, что вызывает NULL->saveUpload(), о котором я упоминал, и выдает первое исключение:

Вызов функции-члена saveUpload() для не-объекта

Попробуйте просто добавить это на свой контроллер:

if (empty($agencyGroup->logo)) {
    var_dump("There's no logo.");
    die();
}

$agencyGroup->logo->saveUpload('logo');

Если вы видите сообщение «Нет логотипа», это означает, что вы должны сначала создать один логотип, прежде чем вызывать его метод saveUpload.

person vFragosop    schedule 20.08.2013
comment
Итак, я думаю, что вы меня на правильном пути ... хотя я могу упустить фундаментальный принцип моделей Eloqquent: если сделать следующее, это должно работать? $logo = new Upload(); $logo = $agency->logo()->save($logo); $agency->logo->saveUpload('logo'); правильно? Спасибо! - person AndrewMcLagan; 21.08.2013
comment
Я предполагаю, что это действительно так. Это кажется немного странным фрагментом кода, особенно потому, что я не могу точно сказать, что ваш метод saveUpload делает за кулисами. Вам, конечно, следует проверить, есть ли у $agencyGroup загрузка, если вы хотите обновить ее. В противном случае вы можете просто каждый раз создавать новый Upload. - person vFragosop; 21.08.2013