2013-04-11 151 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