2013-04-11 142 views
2

我有4個表:Laravel關係問題

structure

我的關係應該像這樣工作:

項目只能有一個大小,顏色和類別。

這應該是工作,但它不是真的。生成的查詢返回錯誤的結果。

這裏是我的模型文件:

<?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'); 
    } 
} 

其餘各表的模型文件的其餘部分是相同的(除表名和型號名稱)。因此,當我嘗試訪問額外的值(大小 - >名稱,顏色 - >名稱,類別 - >名稱)時,我得到錯誤的結果。

我在我的數據庫中有兩個測試記錄: 項目1和項目2具有不同的顏色,大小和類別。 項目1是藍色並且具有M的大小, 項目2是綠色的並且具有XL的大小,但不在返回的查詢中。這表明我,第2項爲紅色,並有S.

控制器的尺寸:產生

@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 

查詢:

<?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); 
    } 

查看

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') 

注意在視圖中,如果我從其他表中訪問這些值,如下所示:

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

它得到我正確的結果,但我真的不希望查詢數據庫n + 3次因此。任何建議我做錯了什麼?

編輯:仍然沒有運氣。 。:(我做你所列出的變化,他們嘗試,但是這件事情仍無法正常工作電流的錯誤是:

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

Bindings: array (
    0 => 0, 
) 

我不知道爲什麼它尋找一個id,我已經改變(

回答

1

查詢的數量!==性能。對於你的情況,你正在做幾乎原子查詢(where id in都與主索引完成,會使它們變得更快 - 如果排除返回結果處理時間,就會像JOIN一樣快)。如果你仍然想解決n + 1查詢問題,Eloquent爲此提供了一個解決方案:ea GER加載。

取而代之的是:

Shop_item::order_by('name') 

使用此:

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

你應該通過這個只看到一個查詢。該功能的文檔位於:http://laravel.com/docs/database/eloquent#eager

+0

我做了,但$ include包含在模型文件中,因爲(主要)我需要這些在前端頁面上。但它仍然給了我提到的領域錯誤的結果。 – peaks 2013-04-11 13:30:28

+0

'return $ this-> has_one('Shop_Category','id');'...你真的認爲當你告訴它選擇'id'時,它會知道如何選擇顏色嗎? – 2013-04-11 13:47:56

+0

請參閱我對下面的Phill的評論的評論。 – peaks 2013-04-11 13:49:57

1

這裏有很多事情正在進行。

  1. 我會說出你的參考列thing_id ......所以這是color_idsize_idcategory_id。這將允許您設置名爲「顏色」,「尺寸」和「類別」的關係,而不是「拖動」。您需要belongs_to()而不是has_one()。 Laravel假設ID將如thing_id,所以如果您已更新爲上面的1,那麼您可以更新您的參考,如$this->belongs_to('Shop_Size')。如果不是,那麼您應該在這裏使用參考列,如$this->belongs_to('Shop_Size', 'size')

  2. 當你使用Eloquent模型時,最好不要限制列 - 你的模型中可能有邏輯取決於它們都在那裏。

  3. 您可以使用預先加載來改進查詢,但Eloquent的工作方式仍然需要每個關係的查詢。看看這行action_index()

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

所有的編輯的上面,你將能夠寫出這樣的代碼在您的視圖後...

@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 

大部分是涵蓋在Eloquent文檔中,特別是RelationshipsEager Loading

+0

這從某種意義上說不會改變,我仍然會得到錯誤的結果。 正如我所說,我得到了錯誤的結果,因爲我的第二個測試項目,得到錯誤的大小和錯誤的顏色。 (所以不訪問這些值和分頁整體不是問題。) – peaks 2013-04-11 13:43:29

+0

你是否遵循了我所有的步驟?數字2非常重要,因爲這就是爲什麼你的所有關係在他們的查詢中都得到錯誤的ID。如果你沒有改變任何東西,你應該把'$ this-> has_one('Shop_Size','id')'改爲'$ this-> has_one('Shop_Size','size')'(對於每個關係)。 – 2013-04-11 13:45:37

+0

哪一個會以此結尾: SQLSTATE [42S22]:未找到列:1054'where子句'中的未知列'color' SQL:SELECT * FROM'item_colors' WHERE'color' IN(?,?) 綁定:陣列( 0 => 1, 1 => 2, ) 由此說明我我分配字段有正在尋找錯誤的列。 – peaks 2013-04-11 13:48:22