【问题标题】:Set Query Builder conditions to Model in Laravel 5.1在 Laravel 5.1 中将查询生成器条件设置为模型
【发布时间】:2015-12-18 04:53:17
【问题描述】:

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

基本问题:

$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.

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

高级问题:

我想像这样使用模型:

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
    }
}

因此,条件要多得多,而且在单独的方法中设置所有条件要容易得多。但是怎么做呢?

【问题讨论】:

    标签: php laravel model


    【解决方案1】:

    模型与构建器

    这里要理解的是Model 对象和底层Builder(查询构建器)对象之间的区别。

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

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

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

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

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

    查询范围

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

    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();
        }
    }
    

    使用上述模型,您的代码将如下所示:

    dd(BrandTop::sunglasses()->get());
    
    // or, more verbosely:
    
    $query = BrandTop::query();
    $query->sunglasses(); // $query already an object, no need to reassign it to itself
    dd($query->get());
    

    【讨论】:

      猜你喜欢
      • 2016-08-10
      • 2021-09-07
      • 2016-11-11
      • 2015-12-13
      • 2019-02-22
      • 1970-01-01
      • 2016-07-30
      • 2017-03-30
      • 2016-08-16
      相关资源
      最近更新 更多