2013-08-29 5 views
17

stworzyłem model grę używając warunku/ograniczenie dla relacji następująco:Jak uzyskać dostęp do modelu ma wiele powiązań z warunkiem, gdzie?

class Game extends Eloquent { 
    // many more stuff here 

    // relation without any constraints ...works fine 
    public function videos() { 
     return $this->hasMany('Video'); 
    } 

    // results in a "problem", se examples below 
    public function available_videos() { 
     return $this->hasMany('Video')->where('available','=', 1); 
    } 
} 

Podczas używania go jakoś tak:

$game = Game::with('available_videos')->find(1); 
$game->available_videos->count(); 

wszystko działa poprawnie, a ról jest uzyskany kolekcja.

mój problem:

gdy próbuję uzyskać do niego dostęp bez chętny załadunku

$game = Game::find(1); 
$game->available_videos->count(); 

jest wyjątek jak to mówi "Zaproszenie do liczby funkcji członka() dla nie- obiekt ".

Korzystanie

$game = Game::find(1); 
$game->load('available_videos'); 
$game->available_videos->count(); 

działa dobrze, ale wydaje się dość skomplikowane do mnie, bo nie trzeba ładować podobnych modeli, jeśli nie używam warunki w moim związku.

Czy coś przeoczyłem? Jak mogę się upewnić, że available_videos są dostępne bez konieczności szybkiego ładowania?

dla wszystkich zainteresowanych, mam również pisał ten problem na http://forums.laravel.io/viewtopic.php?id=10470

+0

Najlepszym sposobem na wdrożenie zarządzania użytkownikami opartymi na rolach w laravel jest skorzystanie z pakietu strażnika. Więc, spróbuj. – harishannam

+0

Jak już powiedziałem w powyższym opisie, nazwy modeli są tylko przykładem, mój problem nie ma nic wspólnego z zarządzaniem użytkownikami. Zamierzam edytować moje pytanie i opublikować mój przykład z prawdziwym słowem. – Remluben

Odpowiedz

6

Just in case ktoś napotyka te same problemy.

Pamiętaj, że wymagane są relacje między liśćmi camelcase. Więc w moim przypadku available_videos() powinien być dostępnyVideos().

można łatwo dowiedzieć się, badając źródła laravel:

// Illuminate\Database\Eloquent\Model.php 
... 
/** 
* Get an attribute from the model. 
* 
* @param string $key 
* @return mixed 
*/ 
public function getAttribute($key) 
{ 
    $inAttributes = array_key_exists($key, $this->attributes); 

    // If the key references an attribute, we can just go ahead and return the 
    // plain attribute value from the model. This allows every attribute to 
    // be dynamically accessed through the _get method without accessors. 
    if ($inAttributes || $this->hasGetMutator($key)) 
    { 
     return $this->getAttributeValue($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 (array_key_exists($key, $this->relations)) 
    { 
     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. 
    $camelKey = camel_case($key); 

    if (method_exists($this, $camelKey)) 
    { 
     return $this->getRelationshipFromMethod($key, $camelKey); 
    } 
} 

To również wyjaśnia, dlaczego mój kod działa, gdy I załadowane dane przed użyciem metody load().

W każdym razie mój przykład działa teraz idealnie dobrze, a $ model-> availableVideos zawsze zwraca kolekcję.

+0

Nie, to nie było powodem . Powinieneś zawsze używać nazwy funkcji z podkreśleniem '_', ponieważ w MVC zawsze powinna się znajdować struktura URL jak'/controller/nazwa_funkcji'. Jeśli nie ustawiłeś odpowiedniego routingu dla funkcji, otrzymasz nazwę funkcji cased w adresie URL, co nie jest przyjazne SEO. – Vineet

+3

@Vineet przepraszam, nie. MVC nie ma nic wspólnego ze strukturą URL. Plik routes.php definiuje mapowanie z adresu URL do kontrolera. – Greg

0

Czy stworzył model „Rola”. Sprawdź, czy problem występuje nawet po utworzeniu modelu dla roli.

+0

Dziękuję za poradę, ale stworzyłem odpowiedni model. Jak widzisz w moim edytowanym pytaniu: moim zdaniem nie ma to nic wspólnego z innym modelem, jak gra $ game-> wideo, ale $ game-> available_videos nie jest – Remluben

35

myślę, że jest to właściwy sposób:

class Game extends Eloquent { 
    // many more stuff here 

    // relation without any constraints ...works fine 
    public function videos() { 
     return $this->hasMany('Video'); 
    } 

    // results in a "problem", se examples below 
    public function available_videos() { 
     return $this->videos()->where('available','=', 1); 
    } 
} 

A potem będziesz musiał

$game = Game::find(1); 
var_dump($game->available_videos()->get()); 
+0

Dziękuję za odpowiedź, twój przykład doskonale działa, ale tak robi moje przy wywołaniu $ game-> available_videos() -> get(). Chodzi o to, że chciałbym skorzystać z $ game-> available_videos, ponieważ mogę również używać $ game-> video bez problemów. O ile mi wiadomo, Eloquent powinien ładować odpowiednie modele, jeśli nie są one wcześniej ładowane, czy też się mylę? – Remluben

+0

zaktualizuj nazwę funkcji do "availableVideos". Jeśli potrzebujesz tylko filmów, aby zwrócić dostępne wideo, które możesz zrobić: 'return $ this-> hasMany ('Video') -> where ('available', '=', 1);' –

5

// niższe dla niektórych wersji v4

public function videos() { 
    $instance =$this->hasMany('Video'); 
    $instance->getQuery()->where('available','=', 1); 
    return $instance 
} 

// v5

public function videos() { 
    $instance =$this->hasMany('Video'); 
    $instance->where('available','=', 1); 
    return $instance 
} 
+0

Świetny pomysł, ale to samo, ponieważ relacja wywołuje tę metodę w konstruktorze zapytań dla ciebie – peter

+0

tak, nie ma potrzeby wywoływać teraz getQuery. niższa wersja potrzebna –

+0

Dla v5 możesz zrobić: 'return $ this-> hasMany ('Video') -> where ('available', '=', 1);' aby uczynić go czystszym –

0

Jeśli chcesz zastosować warunek na tabeli relacyjnej, możesz również użyć innych rozwiązań. To rozwiązanie działa od mojego końca.

public static function getAllAvailableVideos() { 
     $result = self::with(['videos' => function($q) { 
         $q->select('id', 'name'); 
         $q->where('available', '=', 1); 
        }])      
       ->get(); 
     return $result; 
    } 
Powiązane problemy