【问题标题】:How to get items are not in a collection in Laravel Eloquent?如何在 Laravel Eloquent 中获取不在集合中的项目?
【发布时间】:2020-05-19 11:43:32
【问题描述】:

在我的 Laravel 6.x 项目中,我有 Product 模型、WarehouseWarehouseProduct 模型。

在产品中,我存储了我的产品的基本信息。在 WarehouseProduct 中,我存储有关仓库中产品的库存数量信息。当然,我有很多仓库,里面有很多产品。

我的Product 看起来像这样:

class Product extends Model
{
    protected $fillable = [
        'name',
        'item_number',
        // ...
    ];
}

Warehouse 看起来像这样:

class Warehouse extends Model
{
    protected $fillable = [
        'name',
        'address',
        // ...
    ];

    public function products() {
        return $this->hasMany(WarehouseProduct::class);
    }

    public function missingProduct() {
        // here I need to return a Product collection which are not in this Warehouse or the
        // stored amount is 0
    }
}

最后WarehouseProduct 看起来像这样:

class WarehouseProduct extends Model
{
    protected $fillable = [
        'product_id',
        'warehouse_id',
        'amount',
        // ...
    ];

    public function product() {
        return $this->belongsTo(Product::class, 'product_id');
    }

    public function warehouse() {
        return $this->belongsTo(Warehouse::class, 'warehouse_id');
    }

如何获得未存储在Warehouse 或金额为0Product 集合?

【问题讨论】:

  • 您是指一个特定的 Warehouse 实例还是任何一个?

标签: php laravel eloquent eloquent-relationship


【解决方案1】:

这样的事情应该可以工作:

use App\Product;

public function missingProduct() {
    $excludedProducts = $this->products()->where('amount', '>', 0)->pluck('id');

    return Product::whereNotIn('id', $excludedProducts)->get();
}

基于@KarolSobański 的解决方案,当您向产品模型添加warehouse_products 关系时:

use App\Product;
use Illuminate\Database\Eloquent\Builder;

public function missingProduct() {
    return Product::whereDoesntHave('warehouse_products', function (Builder $query) {
        $query->where('warehouse_id', $this->id);
    })->orWhereHas('warehouse_products', function (Builder $query) {
        $query->where('warehouse_id', $this->id);
        $query->where('amount', 0);
    })->get();
}

【讨论】:

  • 这实际上不是一个好的解决方案 - 您发出两个数据库请求而不是一个。您应该在查询中使用关系来避免这种情况。
  • @KarolSobański 我想不出一个使用 laravel 提供的正常关系的解决方案,所以我不认为在这种情况下两个查询不好,但是你能添加一个使用正常关系的解决方案吗,会很有趣。
  • 添加了答案。至少一种建议的解决方案应该有效
  • 谢谢,第一个代码可以正常工作,第二个不行。
【解决方案2】:

最短的答案可能是这样的:

Product::doesntHave('warehouse_products')
       ->orWhereHas('warehouse_products', function (Builder $query) {
           $query->where('amount', '=', 0)
       })->get();

虽然我不确定上述方法是否有效。

但以下更长的查询肯定可以解决问题:

Product::where(function ($query) {
    $query->doesntHave('warehouse_products');
})->orWhere(function ($query) {
    $query->whereHas('warehouse_products', function (Builder $query) {
       $query->where('amount', '=', 0);
    });
})->get();

【讨论】:

    猜你喜欢
    • 2018-06-26
    • 1970-01-01
    • 2021-09-08
    • 2015-06-24
    • 1970-01-01
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    相关资源
    最近更新 更多