在 Laravel 中查询这个的最佳方法

Posted

技术标签:

【中文标题】在 Laravel 中查询这个的最佳方法【英文标题】:Best Way to Query This in Laravel 【发布时间】:2019-08-27 17:25:46 【问题描述】:

我将尝试尽可能简化此过程以直截了当。如果您还有其他问题,请务必告诉我。

我有 2 个表如下:

item_centers:

| id | center | identifier | description        |
|----|--------|------------|--------------------|
| 1  | 1A     |       0011 | Description for 1A |
| 2  | 1B     |       0022 | Description for 1B |
| 3  | 1C     |       0033 | Description for 1C |

一个项目中心可以有许多项目。表中的“标识符”列,代表下面“项目”表中的标识符列。所以中心 1A 可以有许多标识符为 0011 的“项目”。

项目:

| id | identifier | description        | quantity |
|----|------------|--------------------|----------|
| 1  |       0011 | Description for 1A |      250 |
| 2  |       0022 | Description for 1B |      500 |
| 3  |       0033 | Description for 1C |      750 |

我有一个项目中心下拉列表,其中列出了“item_centers”表中的所有项目中心。 (例如:1A)。除了该下拉列表,我还有一个项目下拉列表,其中列出了包含“项目”表中的关键字的所有唯一描述。在这 2 个下拉菜单下,我有一个文本框,允许用户输入他们试图从所选“项目”中减去的数量。

当用户选择 item_center、item description 并单击提交时 - 我有一个执行此操作的过程: 1.从“项目”表中获取所有项目,与从项目中心下拉列表中选择的项目具有相同的“标识符”。 2. 总结第一步中所有检索到的物品的数量。 3. 从项目列表中减去用户输入的数量,从最旧的第一个开始(created_at 列)。

所以,对于我的问题...

我们有许多项目中心包含数量为 0 的项目。我希望能够从列表中删除所有数量为 0 的项目中心,这样用户就不必对 100 个进行排序的项目中心,以找到数量大于 0 的项目。

这是我模拟的一个简单示例。这显然是一种可怕的方法,因为它运行了大量的查询——并且会超时。但它可能更适合作为我在这里想要实现的目标的模型。

public function index()

        $itemCenters = ItemCenter::select(['id', 'center', 'identifier', 'description'])
                                    ->orderBy('center', 'asc')
                                    ->orderBy('description', 'asc')
                                    ->get();

        $itemDescriptions = Item::select('description')
                        ->where('description', 'LIKE', '% .$keyword. %')
                        ->orWhere('description', 'LIKE', '.$keyword. %')
                        ->orWhere('description', 'LIKE', '% $.$keyword.')
                        ->distinct('description')
                        ->orderBy('description', 'asc')
                        ->get();

        foreach ($itemCenters as $itemCenter)
        
            foreach ($itemDescriptions as $itemDescription)
            
                $currentQty = Item::where('identifier', $itemCenter->identifier)
                                 ->where('description', $itemDescription->description)
                                 ->sum('quantity');


                if ($currentQty <= 0)
                
                    $itemCenter->forget($itemCenter->id);
                
            
        

        return view('pages.ItemRemoval', compact('itemCenters'), compact('itemDescriptions'));

正如我之前所说,这确实简化了流程 - 并且可以省略一些内容。因此,如果有任何混淆,请告诉我。

【问题讨论】:

我不是 100% 确定您要达到什么目标,但您可以使用联接吗?将项目连接到 itemcenter 并使用 where 子句检查数量是否大于 0。 【参考方案1】:

使用下面的查询,您基本上不再需要 foreach 循环来过滤 $itemCenters。零个项目以及相应的 item_centers 已被过滤掉。

$itemCenters = DB::table('item_centers')
            ->join('items', 'item_centers.identifier', '=', 'items.identifier')     
            ->select('item_centers.id as id', 'item_centers.center as center', 'item.identifier as identifier', 'item_centers.description as description', 'items.quantity as quantity')
            ->where('quantity', '<>', 0)
            ->orderBy('center', 'asc')
            ->orderBy('description', 'asc')
            ->get();

您可能需要为您的操作选择另一列('items.created_at as created_at')。

【讨论】:

【参考方案2】:

我认为最好的方法是使用 laravel 关系,如果你不是,它会是这样的

ItemCenter 模型

public function items()

    return $this->hasMany(Item::class);

物品模型

public function itemCenter()

    return $this->belongsTo(ItemCenter::class);

所以现在在您的表上,如果两个表上的标识符和描述列相同,您可以删除它们,并将它们替换为项目表上的 item_center_id 外键,该键引用 item_centers 表上的 id 列。

现在为了简化查询,我认为应该是这样的

$item_centers = ItemCenter::with(['items' => function($query)
   $query->havingRaw('SUM(quantity) <= 0 ');
])->get();

【讨论】:

以上是关于在 Laravel 中查询这个的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js:在 laravel 中实现 MPA(多页面应用程序)的最佳方式

Laravel 3 - 查询同一天的开始和结束日期的最佳方法是啥

Laravel Sanctum - 登录用户最佳实践

Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?

在 laravel 中使用 REST API 的最佳身份验证方法是啥?

larave学习笔记1-安装配置