或者在关系方法中

时间:2017-10-11 18:14:55

标签: php laravel eloquent

是否有人知道在关系中包含orWhere以允许多个值与键匹配的方法?

一个例子是我们有一个产品型号,而产品可以是另一个产品(parent_id)的子产品,我们想要从产品和父产品中提取产品。

对于我们可能想要的关系:

public function items()
{
   return $this->hasMany(Item::class)
               ->orWhere('product_id', $this->parent_id);
}

上面的示例适用于将product_id与id和parent_id进行匹配,但是当我们尝试使用该关系执行更多操作时会快速转换,因为它不会嵌套where调用。

所以SQL将是:SELECT * FROM items WHERE product_id = x OR product_id = y

因此,当我们执行$product->items()->where('value', '>', 1);之类的操作时,它会破坏关系,因为它会:

SELECT * FROM items WHERE product_id = x OR product_id = y AND value > 1

而不是:

SELECT * FROM items WHERE (product_id = x OR product_id = y) AND value > 1

我们有一个解决方法,没有使用Eloquent关系(合并两个集合),但我想尽可能利用关系方法。

1 个答案:

答案 0 :(得分:1)

正如@Danny评论的那样,它是对hasMany关系的滥用,合并$product->items$product->parent->items关系会更合适。但是,如果您需要解决方法,可以手动创建关系:

public function items() // I would rather create another method for this specific relationship
{
    $foreignKey = $this->getForeignKey();

    $instance = new Item;

    $localKey = $this->getKeyName();

    $hasMany = new \Illuminate\Database\Eloquent\Relations\HasMany(
        $instance->newQuery()->whereRaw('(true'),
        $this,
        $instance->getTable().'.'.$foreignKey,
        $localKey
    );

    return $hasMany->orwhereRaw('product_id = ? )', [$this->parent_id]);
}

所以你的查询将是

SELECT * FROM items WHERE (true and product_id = x OR product_id = y) AND value > 1

我无法弄清楚如何删除无用的true条件,Laravel不断在场景后添加and关键字。