2013-11-09 17 views
10

Próbowałem wprowadzić polimorficzne relacje. Pracują doskonale ... Jednak staram się zmniejszyć mój rozmiar bazy danych jak najwięcej tak ... mam tenPolimorficzne Eloquent relacje z przestrzeniami nazw

Table action 
| id | realatable_type | relatable_id 
| 1 | Lion\People  | 65 
| 2 | Lion\Company  | 13 

Oczywiście mam ten

<?php namespace Lion; 

class Company extends \Eloquent { ... } 
class People extends \Eloquent { ... } 

Czy istnieje w jaki sposób przechowywać tylko "People" lub "Company" zakładając, że przestrzeń nazw będzie zawsze "Lion"?

+2

istnieje sposób na osiągnięcie tego, ale to wymaga sporo pracy i nie jest to chyba najlepsze rozwiązanie dla Twojej bazy danych problem z rozmiarem. Czy rozważałeś zamianę "readable_type" na pole 'ENUM (" Lion \ People "," Lion \ Company ")? – rmobis

+0

@Raphael_ Muszę przyznać, że oczekiwałem na rozwiązania Eloquent, ale ta wygląda jak jedna możliwość ...: D –

+0

To zajmuje nawet mniej miejsca niż tylko "People" lub "Company". Jeśli naprawdę chcesz Wymowne rozwiązanie, daj mi znać, opublikuję to. – rmobis

Odpowiedz

23

Od laravel 4.1, wewnątrz modelu (w tym przypadku firmy i Ludzie) można ustawić chronionej własności $morphClass do co chcesz.

<?php namespace Lion; 

class Company extends \Eloquent { 

    protected $morphClass = 'Company'; 
} 

Teraz w tabeli można przechowywać typ bez nazw:

| id | realatable_type | relatable_id 
| 2 | Company   | 13 
+0

Nie wiedziałem tego ... Naprawdę dobra odpowiedź, bardzo ci dziękuję;) –

+1

W Laravel 5.3 własność $ morphClass ma zostały usunięte. Teraz musisz użyć 'Relation :: morphMap (['company' => Company :: class]);' –

3

Uważam, że najlepszym rozwiązaniem w tym miejscu (przynajmniej dla rozmiaru bazy danych) byłoby po prostu zmienić readable_type na ENUM('Lion\Company', 'Lion\People').


Biorąc to pod uwagę, jeśli naprawdę chcesz się tym zająć na stronie laravel, musisz utworzyć nowe klasy rozciągające się od Illuminate\Database\Eloquent\Relations\Morph*¹ i nadpisanie konstruktorów ² jak uzyskać tylko ostatni wartość po kresce, na $morphClass. Coś takiego:

<?php 

use \Illuminate\Database\Eloquent\Model; 
use \Illuminate\Database\Eloquent\Builder; 

class MyMorphOne extends \Illuminate\Database\Eloquent\Relations\MorphOne { 
    public function __construct(Builder $query, Model $parent, $type, $id) { 
     parent::__construct($query, $parent, $type, $id); 

     $this->morphClass = substr($this->morphClass, strrpos($this->morphClass, '\\') + 1); 
    } 
} 

Następnie przedłużyć swój własny model lub bazowy model nadpisać morphOne, morphMany i morphToMany metod, aby skorzystać z nowych rozszerzonych klas. Coś takiego:

<?php 

class People extends Eloquent { 

    // ... 

    public function morphOne($related, $name, $type = null, $id = null) { 
     $instance = new $related; 

     list($type, $id) = $this->getMorphs($name, $type, $id); 

     $table = $instance->getTable(); 

     return new MyMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id); 
    } 

} 
  1. * = One, Many i ToMany
  2. które są rzeczywiście odziedziczony MorphOneOrMany na MorphOne i MorphMany.