【问题标题】:How to handle missing records of a Product's attribute value in laravel 7如何在 laravel 7 中处理产品属性值的缺失记录
【发布时间】: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-&gt;attributes 与您的$stock-&gt;attributes 相同,但如果列的顺序不同或在您的情况下属性为空,您最终会遇到问题

标签: laravel eloquent


【解决方案1】:

我会在您的股票属性集合上使用keyBy(未经测试)

@php($s_attributes = $stock->attributes->keyBy('attribute_id'))
@foreach($product->attributes as $p_attribute)
    <td class="text-center">{{ isset($s_attributes[$p_attribute->id]) ? $s_attributes[$p_attribute->id]->pivot->value : ''}}</td>
@endforeach

【讨论】:

  • 我用代码编辑了问题,得到了我想要的输出,它与此类似。我从刀片中取出逻辑并将其放入模型中。但我的问题是,是否有清洁工可以完成我所做的事情?
猜你喜欢
  • 2019-05-31
  • 2016-09-17
  • 2020-09-07
  • 1970-01-01
  • 2020-02-12
  • 2021-01-17
  • 2020-09-27
  • 2020-12-02
  • 2021-07-28
相关资源
最近更新 更多