Sve*_*art 13 php laravel eloquent
我想列出所有可用产品和每个尺寸的数量
name | size1 | size2 | size 3 | size4 | total
________________________________________________________
t-shirt1 | 0 | 1 | 3 | 9 | 13
t-shirt2 | 3 | 1 | 1 | 9 | 14
t-shirt3 | 0 | 0 | 0 | 0 | 0
Run Code Online (Sandbox Code Playgroud)
我的Product模型与之ProductSize类似:
public function sizeAvailable(){
return $this->hasMany('App\ProductSize');
}
Run Code Online (Sandbox Code Playgroud)
我ProductSize与之有关系Product:
public function product()
{
return $this->belongsTo('App\Product');
}
Run Code Online (Sandbox Code Playgroud)
我productSize与之有关系Size:
public function size(){
return $this->belongsTo('App\Size');
}
Run Code Online (Sandbox Code Playgroud)
ProductSize模型包含金额值.所以我能够获得适当数量的产品的所有尺寸,并且我也能够从一个尺寸获得所有产品.如何在我的示例中创建列表.是否可以使用大小作为索引?所以我可以做(伪代码)来填充<td>标签:
for(all products)
{
if(product[somesize] not null)
{{ product[somesize]->amount }}
else
0
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,<tr>如果有例如1个大小(size3),我不知道如何设置表中的数量,而当我这样做时没有其他数据$product->sizeAvailable()只包含1个值(size3),所以我需要将0放在size1下但是如何检查size1是否不适用于该产品?或者有更好的方法来填充表格大小金额?
我目前拥有的:
<table id="myTable" class="tablesorter table table-striped table-responsive">
<thead>
<tr>
<th>
Product
</th>
@foreach($sizes as $size)
<th>
{{ $size->name }}
</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($products as $product)
<tr >
<td>
{{ucfirst($product->name)}}
</td>
@foreach($sizes as $size)
<td>
HERE I NEED TO DO A CHECK IF $product HAS $size RETURN 0 ELSE RETURN ProductSize->amount
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
Run Code Online (Sandbox Code Playgroud)
我可以在产品模型中创建一个函数,如:
hasSize($size)
{
$result = select from ProductSize where size = $size
if ($result = null)
return 0;
return $result->amount();
}
Run Code Online (Sandbox Code Playgroud)
但是使用这个解决方案,我必须运行一个查询products * sizes时间,如果我有1000个产品和20个大小,那么一个表只能获得20.000个查询.
____________________________
Relevant Database data
____________________________
products
-id (primary key)
-name
sizes
-id (primary key)
-name
product_sizes
-pr (primary key)
-prodcut_id
-size_id
-amount
Run Code Online (Sandbox Code Playgroud)
您已手动构建了多对多关系,Laravel已为其提供了一些有用的功能:
1.更新产品型号(添加或替换现有关系):
public function sizes()
{
// many to many relation with intermediate table column
return $this->belongsToMany('App\Size', 'product_sizes')->withPivot('amount');
}
public function getTotalAttribute()
{
// access pivot table directly and use sum aggregate
return DB::table('product_sizes')->where('product_id', $this->attributes['id'])->sum('amount');
}
Run Code Online (Sandbox Code Playgroud)
2.检索模型(在控制器中),如下所示:
$sizes = Size::all();
$products = Product::with('sizes')->get(); // eager load sizes
Run Code Online (Sandbox Code Playgroud)
3.刀片模板:
...
<td>
{{ucfirst($product->name)}}
</td>
@foreach($sizes as $size)
<td>
{{-- HERE I NEED TO DO A CHECK IF $product HAS $size RETURN 0 ELSE RETURN ProductSize->amount --}}
{{-- check and retrieve by using Collection methods --}}
{{ $product->sizes->contains($size) ? $product->sizes->find($size)->pivot->amount : 0 }}
</td>
@endforeach
<td>{{ $product->total }}</td>
....
Run Code Online (Sandbox Code Playgroud)
在使用上面的更改和一个(非常小的)数据库种子重新创建示例后,我得到:
Product size1 size2 size3 total
T-shirt1 10 3 0 13
T-shirt2 5 0 0 5
Run Code Online (Sandbox Code Playgroud)
默认情况下,此解决方案由于急切加载而仅生成3个查询.(使用DebugBar验证)每个total计算都添加一个查询(遗憾的是,Laravel查询构建器没有透视表的聚合方法).
contains()并find()在视图中遍历预取的集合 - 此处没有其他查询.
您不需要该ProductSize模型,因为它只包含一个带有附加属性(amount)的数据透视表.查看多对多关系并检索中间表列.
为方便起见:如果将product_sizes表重命名为product_size并遵循Laravel的表命名约定,$this->belongsToMany('App\Size', 'product_sizes')则不需要第二个参数,可以这样写:$this->belongsToMany('App\Size')
[product_size]表是从相关模型名称的字母顺序派生而来的.