【问题标题】:How can I avoid Eloquent query to be chained?如何避免 Eloquent 查询被链接?
【发布时间】:2017-05-12 13:22:25
【问题描述】:

我是 Laravel 的新手。

我想知道如何避免查询被链接。

$visitRecords = VisitRecord::whereDate('visited_at', '=', Carbon::today()->toDateString());


$knockBounce = $visitRecords->where("bounce_zone", "1")->get()->count();


$approachBounce = $visitRecords->where("bounce_zone", "2")->get()->count();

这是我编写的代码,但这给了我意想不到的结果......

结果

select * from `visit_records` where date(`visited_at`) = '2017-05-12' 

select * from `visit_records` where date(`visited_at`) = '2017-05-12' and `bounce_zone` = '1'

select * from `visit_records` where date(`visited_at`) = '2017-05-12' and `bounce_zone` = '1' and `bounce_zone` = '2'

我检查了进行的查询,这就是我得到的。

我的期望...

select * from `visit_records` where date(`visited_at`) = '2017-05-12' 

select * from `visit_records` where date(`visited_at`) = '2017-05-12' and `bounce_zone` = '1'

select * from `visit_records` where date(`visited_at`) = '2017-05-12' and `bounce_zone` = '2'

我想通过 Eloquent 方法执行此查询。

【问题讨论】:

  • 检查this - 你确定它是链式的吗?它不应该
  • 我从调试栏控制台得到了这些 sql 查询。

标签: php laravel laravel-5 laravel-4


【解决方案1】:

您只实例化了一个 QueryBuilder 对象。

您应该为第二个查询创建第二个 QueryBuilder 对象。

//Only create one carbon object
$date = Carbon::today()->toDateString()

$knockBounce = VisitRecord::whereDate('visited_at', '=', $date)->where("bounce_zone", "1")->count();

$approachBounce = VisitRecord::whereDate('visited_at', '=', $date)->where("bounce_zone", "2")->count();

根据 Matthew 的评论进行了更新,Laravel 将在底层为聚合函数(countminmaxavg)执行 ->get(),因此不需要它。

【讨论】:

  • 你应该直接使用 ->count() 而没有 ->get() :)
【解决方案2】:

你需要有两个不同的objects

你可以试试下面的代码

$visitRecords = VisitRecord::whereDate('visited_at', '=', Carbon::today()->toDateString());

$visitRecords1 = clone $visitRecords;    

$knockBounce = $visitRecords->where("bounce_zone", "1")->get()->count();    

$approachBounce = $visitRecords1->where("bounce_zone", "2")->get()->count();

这里我使用clone复制$visitRecords对象

进一步阅读php clone

【讨论】:

    【解决方案3】:

    编辑以仅获取所需的bounce_zone

    或者,您可以使用集合:

    $visitRecords = VisitRecord::whereDate('visited_at', '=', Carbon::today()->toDateString())->where("bounce_zone", "1")->orWhere("bounce_zone", "2")->get();
    
    
    $knockBounce = $visitRecords->where("bounce_zone", "1")->count();
    
    
    $approachBounce = $visitRecords->where("bounce_zone", "2")->count();
    

    您只运行一个查询并使用 Laravel 的所有功能 :)

    【讨论】:

    • 运行一次查询,但费用是多少?取决于业务逻辑,但我会避免获取您不打算处理的数据。例如所有记录 where bounce_zone not in (1, 2) 可能是您永远不需要的数百万行?
    • @luke 这种方法需要更多的计算吗?
    • 这个答案也使用了 where() 的 Collection 版本,最终可能会非常慢。
    • @Hayatomo 没有更多的计算,但可能会返回您永远不需要的集合中的值。如果bounce_zone12 之外的其他值,它们将在$visitRecords 集合中返回,但只是坐在那里直到垃圾收集器删除该集合,因为它们不会在$knockBounce 中使用或$approachBounce
    猜你喜欢
    • 2011-04-06
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2016-06-28
    • 1970-01-01
    • 2020-04-12
    相关资源
    最近更新 更多