2016-11-21 7 views
2

Я создаю пакет, который в значительной степени полагается на морфинг многих отношений. Как обычно с этим отношением, требуется определить отношения как так:Laravel 5 Метод динамической морфологии

public function foos() 
{ 
    return $this->morphToMany('App\Models\Foo', 'barable'); 
} 

Это, очевидно, работает нормально, и нет никаких проблем здесь.

Дело в том, что существует много таких отношений, которые необходимо определить. И я бы хотел просто пропустить их и создать их автоматически, чтобы упростить настройку пакета.

Я попытался следующие:

public function __get($name) 
{ 
    if($name == 'foos') { 
     return $this->morphToMany('App\Models\Foo', 'barable'); 
    } 
} 

Это не инициирует запрос для извлечения данных. Он вызывается, но он не возвращает данные.

Функция __call показалась мне логичной, но это просто ломает Laravel. Насколько я могу судить, он поднимает все, что называется в классе.

Альтернативой теперь является включение признака и включение программиста в эти отношения в файл для публикации, но это просто неправильно.

Любые предложения?

ответ

1

Оказывается, это двухэтапный ответ. Вам нужно исправление для интенсивной загрузки и одно для ленивой загрузки.

Загружаемый загрузчик принимает функцию __call(), указанную в файле model.php, и перенаправляет ее, если инструкция не выполняется.

public function __call($method, $arguments){ 
    if(in_array($method, ['bars'])) { 
     return $this->morphToMany('App\Bar', 'barable'); 
    } 
    return parent::__call($method, $arguments); 
} 

Ленточный загрузчик проверяет, существует ли метод, которого, очевидно, нет. Добавление его в вашу модель и добавление оператора «OR» заставят их работать. Исходная функция также находится в model.php. Добавление:

|| in_array($key, $this->morphs) 

Сделает функцию работы, как ожидается, и, таким образом, приводит к:

public function getRelationValue($key) 
{ 
    // If the key already exists in the relationships array, it just means the 
    // relationship has already been loaded, so we'll just return it out of 
    // here because there is no need to query within the relations twice. 
    if ($this->relationLoaded($key)) { 
     return $this->relations[$key]; 
    } 

    // If the "attribute" exists as a method on the model, we will just assume 
    // it is a relationship and will load and return results from the query 
    // and hydrate the relationship's value on the "relationships" array. 
    if (method_exists($this, $key) || in_array($key, $this->morphs)) { 
     return $this->getRelationshipFromMethod($key); 
    } 
} 
Смежные вопросы