【发布时间】:2020-05-22 19:51:33
【问题描述】:
背景信息:
我正在通过创建库存系统来学习 laravel 7。 我有几个模型:产品、库存和属性。
- 产品就像一个持有所有股票的集团。因为我可以拥有像扬声器这样的产品。但是我可以拥有许多具有不同属性值的相同产品。这是股票变得重要的时候。
-
库存 是我在我的库存中拥有所有物品的地方。
- 例如:如果我有 20 个发言者,products 表中会有 1 条记录,stocks 表中有 20 条记录。
- 属性是因为我想根据产品跟踪不同的属性。但这些属性的价值不属于产品;它属于产品的库存。
这就是我的模型的关联方式:
一个产品有很多库存
股票属于产品
一个产品有很多属性
属性属于产品
属性 belongsToMany Stock
A Stock belongsToMany 属性(我对这个不是很有信心。)
目标:
产品是L-Acoustics LA12X
产品的属性是序列号和固件
产品的库存是显示“库存水平”的卡片。
为了测试和简化,我将相同的序列号和固件值复制到所有产品的库存中;但在现实生活中,它们应该都有不同的序列号和固件版本。
问题:
我只有在每个属性都有值的情况下才得到上图的输出。例如:如果我从第一只股票中删除序列号的属性值,我会得到这个。
您看到它是如何将固件值转移到序列号列的吗?
如果记录被删除或值尚未创建,我想在该表中放置一个空单元格,使其看起来像这样。 (我通过编辑页面的HTML创建了这个图像,我仍然不知道如何得到这个输出)
我尝试过的:
我很快想到在我的数据库中创建属于该属性的空单元格,这样当我遍历我的记录时,我会得到一个完美的表格。但是当我的数据库增大时,这将很快成为一个问题。
你能想到为什么会有不存在的记录吗?一个例子是我的库存太旧了,有一些我无法检索的序列号。因此,表中不会有任何记录。
显示一些代码:
这是我的产品模型:
class Product extends Model {
protected $guarded = [];
protected $casts = [
'brand_id' => 'integer',
'category_id' => 'integer',
'price' => 'decimal:2',
'rental_price' => 'decimal:2',
'active' => 'boolean'
];
public function setNameAttribute($value)
{
$this->attributes['name'] = $value;
$this->attributes['slug'] = Str::slug($value);
}
public function brand()
{
return $this->belongsTo(Brand::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
public function stocks()
{
return $this->hasMany(Stock::class)->orderBy('barcode', 'asc');
}
public function attributes()
{
return $this->hasMany(Attribute::class);
}
}
这是我的库存模型:
class Stock extends Model {
protected $guarded = [];
protected $casts = [
'quantity' => 'integer',
'product_id' => 'integer',
];
public function product()
{
return $this->belongsTo(Product::class);
}
public function attributes()
{
return $this->belongsToMany(Attribute::class)->withPivot('value');
}
}
这是我的属性模型:
class Attribute extends Model {
protected $guarded = [];
protected $casts = ['product_id' => 'integer'];
public function product()
{
return $this->belongsTo(Product::class);
}
public function stocks()
{
return $this->belongsToMany(Stock::class);
}
public function values()
{
// This method is empty because I don't know how to relate the attribute to its values.
}
我知道我已经倾倒了很多信息,但我真的需要帮助。我有一个开放的心态,我对新的实施持开放态度。
更新
这是我的观点的代码:
<div class="block-content block-content-full">
<div class="table-responsive">
<table class="table table-borderless table-striped table-vcenter font-size-sm">
<thead>
<tr>
<th class="text-left">Barcode</th>
@foreach($product->attributes as $attribute)
<th class="text-center">{{ $attribute->name }}</th>
@endforeach
<th class="text-right">Condition</th>
<th class="text-right">Updated</th>
</tr>
</thead>
<tbody>
@forelse($product->stocks as $stock)
<tr>
<td class="text-left">
<a href="{{ route('products.stocks.show', [$product->slug, strtolower($stock->barcode)]) }}"><strong>{{ $stock->barcode }}</strong></a>
</td>
@foreach($stock->attributes as $attribute)
<td class="text-center">{{ $attribute->pivot->value }}</td>
@endforeach
<td class="text-right">
@switch($stock->condition)
@case('Great')
<span class="badge badge-success"><i class="fa fa-check-circle mr-1"></i>Great</span>
@break
@case('Damaged')
<span class="badge badge-warning"><i class="fa fa-exclamation-circle mr-1"></i>Damage</span>
@break
@case('Broken')
<span class="badge badge-danger"><i class="fa fa-times-circle mr-1"></i>Broken</span>
@break
@endswitch
</td>
<td class="text-right">{{ $stock->updated_at->format('M d, Y') }}</td>
</tr>
@empty
<tr><td colspan="100" class="text-center">No Stock Available</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
这是我的控制器中的 show 方法:
public function show(Product $product)
{
return view('products.show', compact('product'));
}
更新 2:
我将我的 Attribute 模型更新为:
class Attribute extends Model {
protected $guarded = [];
protected $casts = ['product_id' => 'integer'];
public function getValueByBarcode($stock)
{
return $this->values()->where('barcode', $stock)->first()->value ?? '';
}
public function product()
{
return $this->belongsTo(Product::class);
}
public function stocks()
{
return $this->belongsToMany(Stock::class);
}
public function values()
{
return $this->belongsToMany(Stock::class)->select('value');
}
}
在我的刀片中,我得到了这样的值:
<table class="table table-borderless table-striped table-vcenter font-size-sm">
<thead>
<tr>
<th class="text-left">Barcode</th>
@foreach($product->attributes as $attribute)
<th class="text-center">{{ $attribute->name }}</th>
@endforeach
<th class="text-right">Condition</th>
<th class="text-right">Updated</th>
</tr>
</thead>
<tbody>
@forelse($product->stocks as $stock)
<tr>
<td class="text-left">
<a href="{{ route('products.stocks.show', [$product->slug, strtolower($stock->barcode)]) }}"><strong>{{ $stock->barcode }}</strong></a>
</td>
@foreach($product->attributes as $attribute)
<td class="text-center">{{ $attribute->getValueByBarcode($stock->barcode) }}</td>
@endforeach
<td class="text-right">
@switch($stock->condition)
@case('Great')
<span class="badge badge-success"><i class="fa fa-check-circle mr-1"></i>Great</span>
@break
@case('Damaged')
<span class="badge badge-warning"><i class="fa fa-exclamation-circle mr-1"></i>Damage</span>
@break
@case('Broken')
<span class="badge badge-danger"><i class="fa fa-times-circle mr-1"></i>Broken</span>
@break
@endswitch
</td>
<td class="text-right">{{ $stock->updated_at->format('M d, Y') }}</td>
</tr>
@empty
<tr><td colspan="100" class="text-center">No Stock Available</td></tr>
@endforelse
</tbody>
</table>
这就是改变的结果
我终于设法得到了我想要的东西,但是有没有更清洁的方法来做同样的事情?
【问题讨论】:
-
我认为重要的部分是您的视图,并且缺少它,您可以直接在那里进行显示逻辑。
-
您提供了很多信息,太好了。但问题可能在于您的刀片模板视图,您可能需要一些条件逻辑来包含一个空单元格,即使该字段没有数据也是如此。请为您的视图模板添加代码,并为您的控制器添加完整性。
-
@ChristopheHubert 我已经用视图和控制器更新了帖子
-
@Andrew 我已经用视图和控制器更新了帖子
-
您的问题是您假设
$product->attributes与您的$stock->attributes相同,但如果列的顺序不同或在您的情况下属性为空,您最终会遇到问题