php - 在 Laravel Eloquent 中获取由父模型中的字段过滤的相关列的 SUM

标签 php laravel

我有以下表格:

采购订单

  • 编号
  • 状态

行项目

  • 编号
  • purchase_order_id
  • 产品编号
  • 数量

产品

  • 编号
  • 产品名称

采购订单包含多个订单项,每个订单项有一个产品和一个数量字段('数量')。

See ERD Model

这是我定义 Laravel 模型的方式:

产品型号:

class Product extends Model
{
    public function lineitems()
    {
        return $this->hasMany('App\LineItem');
    }
}

订单项模型:

class LineItem extends Model
{
    public function purchase_order()
    {
        return $this->belongsTo('App\PurchaseOrder', 'purchase_order_id');
    }

    public function product()
    {
        return $this->hasOne('App\Product', 'product_id');
    }
}

采购订单模型:

class PurchaseOrder extends Model
{
    public function lineitems()
    {
        return $this->hasMany('App\LineItem');
    }

}

我想获得所有 'line_items.qty' 的总和,用于通过 'purchase_order.status' 过滤的 'product.id' .

如何在 Model 函数 中编写查询,以便我可以使用它通过 Blade @foreach 遍历所有产品?

提前致谢!

最佳答案

如果你想获得更快的速度并一次获得所有内容,那么你可以尝试这个查询:

$products = Product::selectRaw('products.*, sum(line_items.qty) as qty_sum')
            ->join('line_items', 'line_items.product_id', '=', 'products.id')
            ->join('purchase_orders', 'purchase_orders.id', '=', 'line_items.purchase_order_id')
            ->where('purchase_orders.status', 'sold')
            ->groupBy('products.id')
            ->get();

但如果 MySql,则您的数据库必须接受一列始终与其他列匹配的整个分组。

但是如果你只想坚持使用 Laravel 关系,请执行以下步骤。

1-当你的表名是复数时,PK是id,FK是单数表名,_id ex (table products(id), table line_items(product_id )), 关系中不需要指定外键。

2- 因为是多对多的情况,你不一定要为中间表 line_items 定义一个模型,你可以用它来进行特殊和快速的查询,但是你可以通过 Laravel Pivot 系统在其上处理 CRUD。您可以了解有关 Pivot 的更多信息 https://laravel.com/docs/5.7/eloquent-relationships#many-to-many

Retrieving Intermediate Table Columns

As you have already learned, working with many-to-many relations requires the presence of an intermediate table. Eloquent provides some very helpful ways of interacting with this table. For example, let's assume our User object has many Role objects that it is related to. After accessing this relationship, we may access the intermediate table using the pivot attribute on the models:

所以你的模型看起来像这样:

产品型号:

class Product extends Model
{
    public function purchaseOrders()
    {
        return $this->belongsToMany('App\PurchaseOrder', 'line_items')->withPivot('qty')->withTimestamps();
    }

    public function soldPurchaseOrders()
    {
        return $this->belongsToMany('App\PurchaseOrder', 'line_items')
                    ->where('status', 'sold')
                    ->withPivot('qty')->withTimestamps();
    }
}

采购订单模型:

class PurchaseOrder extends Model
{
    public function products()
    {
        return $this->belongsToMany('App\Product', 'line_items')->withPivot('qty')->withTimestamps();
    }

}

使用 ->withPivot('field1', 'field2', 'etc')->withTimestamps() 如果你的数据透视表有 created_at , updated_at 列。并在查询构建器中使用前缀 pivot_+attribute 访问 pivot 值,并在结果对象方法中使用 pivot->+attribute,例如:$products->first( )->pivot->qty.

如果您仍想使用 LineItem 模型,则将 Product 关系更改为 belongsTo

订单项模型:

class LineItem extends Model
{
    public function purchaseOrder()
    {
        return $this->belongsTo('App\PurchaseOrder');
    }

    public function product()
    {
        return $this->belongsTo('App\Product');
    }
}

3- 最后使用以下代码检索数量为 SUM 的产品:

使用预先加载在 1 个请求中同时自动加载所有产品的采购订单,以避免 N-Products + 1 请求到数据库。 https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

$products = Product::with('soldPurchaseOrders')->get();

foreach($products as $product) {
    $qtySum = $product->soldPurchaseOrders->sum('pivot.qty');
    echo '<br/> Product '.$product->id.' - '.$product->name.' - '.$qtySum;
}

所以最后,Laravel 将像上面的第一个示例一样使用 INNER JOIN 查询转换它,但只使用花哨的设计和数据透视表。

编辑------

在 OP 将订单状态指定为 sold 后,我更新了代码以使用 sold。

编辑 2 -----

$product->pivot->qty 替换为 $qtySum。在调用 soldPurchaseOrders 关系后,数据透视数量将可用,例如:

foreach($product->soldPurchaseOrders as $order) {
    echo '<br/>Order .'$order->id.' - '.$order->pivot->qty;
} 

关于php - 在 Laravel Eloquent 中获取由父模型中的字段过滤的相关列的 SUM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54956377/

相关文章:

php - 在 Symfony2 中异步调用命令

php - Backbone.js:保存方法总是返回错误回调

javascript - 在页面上存储 Ajax 请求数据的最佳方式

mysql - 四表查询

php - Laravel API 与谷歌分析

javascript - 在 javascript 函数内以 Eloquent ORM 传递参数

php - 如何将按钮添加到此 wordpress 导航栏中?

php - mysql消息系统-PHP MySQL的在线离线状态

php - Nova 相关过滤 - 如何过滤 company_id 与位置 company_id 匹配的用户

laravel - npm 安装后不显示 ionic 图标