在Laravel 5.1中将Query Builder条件设置为Model

时间:2015-12-18 04:53:18

标签: php laravel model

首先我要说我试图找到解决方案,但我没有。

基本问题:

$Br = new BrandTop;
dd( $Br->limit(10)->get() ); // Will return 10 rows

$Br = new BrandTop;
$Br->limit(10);
dd( $Br->get() ); // Will return all rows.

那么,基本问题 - 为什么?如何为模型设置一些限制,但仍然可以使用它,例如设置(或不设置)某些 顺序依赖于其他变量。

高级问题:

我想使用这样的模型:

class BrandTop extends Model
{
    public function withBrand() {
        return $this->leftJoin('brand', 'brand.id' , '=', 'brandtop.brand_id');
    }
    public function forType($type) // there is much more conditions for type
    {
        return $this->where(['type' => $type]);
    }

    // main function
    public function forSunglasses($limit = 0, $logo = false)
    {
        if ($logo)
            $this->where(['menu_logo' => 1])->orderBy('total_sales', 'desc');
        if ($limit)
            $this->limit($limit);

        return $this->forType('sunglasses')->withBrand();
        // But there goes Error, because forType() return Builder object, and it has no withBrand() method
    }
}

因此,有更多的条件,并且在单独的方法中设置所有条件要容易得多。但是如何?

1 个答案:

答案 0 :(得分:4)

模型与构建器

这里要理解的是<wsse:Security>对象与底层Model(查询构建器)对象之间的区别。

语句Builder将创建$Br = new BrandTop;的新实例,并将其分配给Model变量。接下来,$Br语句将为brand_tops表创建一个$Br->limit(10)对象的新实例,其限制为10。

在您的第一个示例中,通过Builder,您在已应用限制的$Br->limit(10)->get()上调用get()

在您的第二个示例中,您的个人Builder创建了新的$Br->limit(10)实例,但从未将其用于任何事情。下一个语句Builder创建另一个没有任何约束的新$Br->get()实例,因此它会检索所有记录。

为了能够构建查询,您需要将Builder实例分配给变量,并在最终调用Builder之前继续修改该实例。例如,要使您的第二个示例起作用:

get()

查询范围

关于问题的第二部分,您可能希望查看query scopes

$query = BrandTop::query();
$query->limit(10);
$query->where(/*conditions*/);
dd($query->get());

使用上面的模型,您的代码看起来像:

class BrandTop extends Model
{
    // renamed to "JoinBrand" instead of "WithBrand", as "with" would imply
    // an eager loaded relationship vs a joined table
    public function scopeJoinBrand($query)
    {
        return $query->leftJoin('brand', 'brand.id' , '=', 'brandtop.brand_id');
    }

    // got rid of "for" prefix
    public function scopeType($query, $type)
    {
        return $query->where('type', $type);
    }

    // got rid of "for" prefix
    public function scopeSunglasses($query, $limit = 0, $logo = false)
    {
        if ($logo)
            $query->where(['menu_logo' => 1])->orderBy('total_sales', 'desc');
        if ($limit)
            $query->limit($limit);

        return $query->type('sunglasses')->joinBrand();
    }
}