problemy relacji laravel

głosy
2

Mam 4 tabele:

Struktura

Moje relacje powinny działać tak:

Elementy mogą mieć tylko jeden rozmiar, kolor i kategorię.

To powinno działać, ale to naprawdę nie jest. Zapytanie generowane Przywraca błędne wyniki.

Oto moje pliki model:

<?php

class Shop_Item extends Eloquent
{
    public static $table = 'items';
    public static $timestamps = false;

    public function scategory() {
        return $this->has_one('Shop_Category','id');
    }

    public function ssize() {
        return $this->has_one('Shop_Size','id');
    }

    public function scolor() {
        return $this->has_one('Shop_Color','id');
    }
}

Reszta plików wzorem dla pozostałych tabelach są takie same (z wyjątkiem nazwy tabeli i nazwy modelu).

<?php
class Shop_Category extends Eloquent
{
    public static $table = 'item_categories';
    public static $timestamps = false;
}

Tak więc, gdy próbuję uzyskać dostęp do dodatkowych wartości (size-> nazwa, zastosowaniu przyjemnej dla oka> nazwa, category-> name), pojawia się błędne wyniki.

Mam dwie płyty testowe w mojej bazy danych: pkt 1 i pkt 2 w innym kolorze, wielkości i kategorii. Element 1 jest niebieski i ma wielkość M, pozycja 2 jest zielony i posiada wymiary XL, lecz nie w zwróconym zapytania. Które mi pokazuje, że pozycja 2 jest czerwony i ma rozmiar S.

Kontroler:

<?php

class Admin_Shop_Controller extends Base_Controller {

    public function action_index() {

        $items = Shop_item::order_by('name')->paginate(10,array('id','name','price','sex','visible','color','size','category'));
        return View::make('admin.shop.index')->with('items', $items);
    }

Widok:

@forelse($items->results as $i)
{{ $i->name }}
{{ $i->price }}
{{ $i->sex }}
{{ $i->scategory->name }}
{{ $i->scolor->name }}
{{ $i->ssize->name }}

<a href = {{ URL::to('admin/shop/edit/'.$i->id) }}>Edit</a>
<a href = #>Delete</a>

@empty
    There are no items in the shop.
@endforelse

Zapytania generowane:

0.23ms  
SELECT COUNT(`id`) AS `aggregate` FROM `items`
0.28ms  
SELECT `id`, `name`, `price`, `sex`, `visible`, `color`, `size`, `category` FROM `items` ORDER BY `name` ASC LIMIT 10 OFFSET 0
0.25ms  
SELECT * FROM `item_categories` WHERE `id` IN ('1', '2')
0.21ms  
SELECT * FROM `item_sizes` WHERE `id` IN ('1', '2')
0.36ms  
SELECT * FROM `item_colors` WHERE `id` IN ('1', '2')

Zauważ, że w widoku, jeśli dostęp do tych wartości z innej tabeli jak poniżej:

{{ Shop_Color::find($i->color)->name }}

To staje mi właściwą wynik, ale ja naprawdę nie chcę kwerendy w bazie N + 3 razy z tego powodu. Wszelkie sugestie, co robię źle?

Edit: Jeszcze nie ma szczęścia. . :( Zrobiłem zmiany wymienione, eksperymentował z nich, ale ta sprawa wciąż nie działa Aktualny błędu:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause'
SQL: SELECT * FROM `item_colors` WHERE `id` IN (?)

Bindings: array (
  0 => 0,
)

Nie wiem, dlaczego to wygląda na id, zmieniłem wszystkie odwołania do tabel podrzędnych i przemianowany kolumny odpowiednio. :(

Utwórz 11/04/2013 o 12:14
źródło użytkownik
W innych językach...                            


2 odpowiedzi

głosy
1

Liczba zapytań! == wydajność. W twoim przypadku, robisz zapytania niemal Atomowej ( where id inwszystkie są wykonane w porównaniu wskaźników podstawowych, które czynią je szybko - tak szybko jak JOIN jeśli wykluczyć czas procesu powrocie-wynik). Jeśli mimo to chcesz rozwiązać problem n + 1 zapytań, elokwentny ma rozwiązanie dla tego: chętny-loading.

Zamiast tego:

Shop_item::order_by('name')

Użyj tego:

Shop_item::with(array("scategory", "ssize", "scolor"))->order_by('name')

Powinieneś zobaczyć tylko jedno zapytanie za pomocą tego. Doc dla tej funkcji jest: http://laravel.com/docs/database/eloquent#eager

Odpowiedział 11/04/2013 o 12:27
źródło użytkownik

głosy
1

Istnieje sporo rzeczy się tu dzieje.

  1. Chciałbym wymienić kolumn odniesienia thing_id... tak to jest color_id, size_idi category_id. To pozwoli Ci ustawić relacje o nazwie „kolor”, „rozmiar” i „kategoria”, zamiast „sthing”.

  2. Musisz belongs_to()zamiast has_one(). Laravel zakłada, że identyfikator będzie jak thing_id, więc jeśli już zaktualizowane 1 powyżej, to możesz zaktualizować swoje referencje jak $this->belongs_to('Shop_Size'). Jeśli nie, to należy użyć kolumny odniesienia tutaj, jak $this->belongs_to('Shop_Size', 'size').

  3. Podczas korzystania z modeli wymowny, że najlepiej, aby nie ograniczać kolumny - może masz logikę w modelu, który zależy od nich wszystkich będąc tam.

  4. Można użyć chętny załadunek poprawa zapytań, ale sposób Eloquent działa nadal będzie potrzebował zapytanie za związek. Przyjrzeć się tej liniiaction_index()

    $items = Shop_Item::with(array('color', 'size', 'category'))
                      ->order_by('name')->paginate(10);
    

Po wykonaniu wszystkich powyższych edycji was będzie w stanie napisać kod jak to w widoku ...

@forelse ($items->results as $item)

    <p>Color: {{ $item->color->name }}</p>

@else
    <p class="no-results">There are no items in the shop.</p>
@endforelse

Większość z nich pokryta jest wymownym Dokumenty, zwłaszcza relacji i zachłanne ładowanie .

Odpowiedział 11/04/2013 o 12:28
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more