2013-11-07 5 views
6

Я пытаюсь установить полиморфные отношения в Laravel 4, чтобы у меня был один класс Image, который обрабатывает все, что связано с загрузкой, отключает и т. Д., А затем использовать его несколькими разные модели. Все в порядке, пока я не попытаюсь создать несколько ссылок из одной и той же модели.Laravel 4, множественные полиморфные отношения от одной модели

Например, я в настоящее время есть что-то вроде этого:

Модели/image.php

class Image extends Eloquent { 
    public function of() { return $this->morphTo(); } 
} 

Модели/Person.php

class Person extends Eloquent { 
    public function mugshot() { return $this->morphOne('Image', 'of'); } 
    public function photos() { return $this->morphMany('Image', 'of'); } 
} 

Модели/Place.php

class Place extends Eloquent { 
    public function photos() { return $this->morphMany('Image', 'of'); } 
} 

Здесь, Человек может загрузить один mugshot и многие photos, а на месте может быть много photos. Проблема заключается в том, что когда я создаю mugshot на человека, он сохраняет это в images таблицы в базе данных:

id: 1 
of_id: 1 
of_type: Person 

Он не хранит тот факт, что это mugshot и не photo, поэтому, когда я пойдите, чтобы восстановить его, $person->mugshot может иногда возвращать один из $person->photos и наоборот.

Есть ли (a) лучший способ сделать это, чем создать 2 ссылки на одной и той же модели, или (б) способ сделать так, чтобы этот способ работал?

+0

Могу ли я спросить, как ваши данные отношения базового стола выглядят? Я думаю, что у меня есть аналогичный случай, но не знаю, как настроить отношения для использования morphOne() – moleculezz

ответ

20

Нет встроенного способа прямо сейчас. Возможно, в Laravel 4.1 это должно привести к полной переработке полиморфных отношений.

Добавить type свойство Image, а затем определить where условия на отношения:

public function mugshot() { 
    return $this->morphOne('Image', 'of')->where('type', 'mugshot'); 
} 

public function photos() { 
    return $this->morphMany('Image', 'of')->where('type', 'photo'); 
} 

Не забудьте установить type на Image s вы создаете. Или, как я сделал, скрыть эту логику внутри модели.

Вот мой код (я использую PHP 5.4 с краткой нотации массива):

Изображение:

namespace SP\Models; 

class Image extends BaseModel { 

    const MUGSHOT = 'mugshot'; 
    const PHOTO = 'photo'; 

    protected $hidden = ['type']; 

    public function of() 
    { 
     return $this->morphTo(); 
    } 
} 

лицо:

namespace SP\Models; 

use SP\Models\Image; 

class Person extends BaseModel { 

    public function mugshot() { 
     return $this->morphOne('SP\Models\Image', 'of') 
          ->where('type', Image::MUGSHOT); 
    } 

    public function photos() { 
     return $this->morphMany('SP\Models\Image', 'of') 
          ->where('type', Image::PHOTO); 
    } 

    public function saveMugshot($image) 
    { 
     $image->type = Image::MUGSHOT; 
     $image->save(); 
     $this->mugshot()->save($image); 
    } 

    public function savePhotos($images) 
    { 
     if(!is_array($images)) 
     { 
      $images = [$images]; 
     } 

     foreach($images as $image) 
     { 
      $image->type = Image::PHOTO; 
      $image->save(); 
      $this->photos()->save($image); 
     } 
    } 
} 

Где-то в контроллере/услуги:

$person->savePhotos([$image1, $image2]); 
+0

Это выглядит довольно красиво, поскольку код идет :) Я сейчас буду работать над проектом, поэтому я позволю вам знаешь, как все идет - если все идет гладко (и я думаю, что это будет, идея выглядит здорово), я соглашусь и надушу тебя :) Cheers – Joe

+0

Счастливые дни, это все хорошо :) Большое спасибо за ваше время, это очень ценится – Joe

+1

Как следует из моего теста, оказывается, что -> где больше не требуется, если вы используете автоименование laravel для столбцов для типа.Что в этом случае будет 'of_type'. По крайней мере, к моему пониманию. –

Смежные вопросы