提高 Laravel Eloquent 查询的5个小技巧

翻译自:aschmelyun.com/blog/5-tips-for-sup...

在过去的五年左右的时间里,我一直在与Laravel合作,在那段时间里,我遇到了一些案例,在这些案例中,我需要一种独特或非典型的方式来从应用程序中返回数据。使用Eloquent提取数据变得容易,但是仍然有一些用例需要我进行一些挖掘和理解,以弄清楚如何做自己想完成的事情。

我在下面列出了其中的五个,以及代码示例和为每个示例返回的伪数据。

准备好? 让我们开始吧!

有条件地建立查询

假设我们有一个 Property 模型,其中包含 价格列以及是否允许您养宠物。当用户访问时,我们希望过滤掉数据example.com/properties?rent=1200&pets=true

public function test(Request $request)
{
    if ($request->get('rent') && $request->get('pets')) {
        return Property::where('rent', <=, $request->get('rent'))->where('pets_allowed', true))->get();
    }

    if ($request->get('rent')) {
        return Property::where('rent', <=, $request->get('rent'))->get();
    }

    if ($request->get('pets')) {
        return Property::where('pets_allowed', true))->get();
    }

    return Property::all();
}

我们可以建立一个查询,然后根据这些条件(而不是依赖它们)添加到查询中。
使用Model::query(),然后我们可以根据存在的过滤器链接到 where 语句上。
最后调用get返回我们的数据:

public function test(Request $request)
{
    $properties = Property::query();

    if ($request->get('rent')) {
        $properties->where('rent', <=, $request->get('rent'));
    }

    if ($request->get('pets')) {
        $properties->where('pets_allowed', true));
    }

    return $properties->get();
}

这样可以确保每个过滤器仅需要一个条件语句,并且可以将过滤器组合自动链接到此查询。

返回最新关系

以我们之前的 Property 模型为例,假设有多个与 Tenant 模型相关联的 租户 模型。要拉入所有带有其附加租户的属性,您可能会使用类似以下内容的方法:

public function test(Request $request)
{
    return Property::with('tenants')->get();
}

但是,如果您只想返回一位租户,该怎么办?

public function tenants()
{
    return $this->hasMany(Tenant::class);
}

public function newestTenant()
{
    return $this->hasOne(Tenant::class)->orderBy('lease_expires_at', 'desc');
}

现在,如果我们回到以前的测试方法并将其修改为用 Property::with('newestTenant'),我们将只得到一个租户。

按嵌套值过滤项目

使用我们之前的财产租户模型以及关系,如果只想返回那些租户没有狗或猫的财产,该怎么办?您可能可以使用类似以下的内容:

public function test(Request $request)
{
    return Property::with(['tenants' => function($query) {
        $query->where('has_dogs', false)->where('has_cats', false);
    }])->get();
}

但我想做的是过滤掉这些属性,然后只返回那些包含那些过滤后的关系的属性。我们可以在对象上运行一个foreach循环并检查该空的租户数组,或者可以使用Eloquent的whereHas()方法:

public  function test(Request $request) { 
    return Property::whereHas('tenants', function($query) { 
        $query->where('has_dogs', false)->where('has_cats', false); 
    })->with(['tenants' => function($query) { 
        $query->where('has_dogs', false)->where('has_cats', false);
    }])->get(); 
}

通过使用whereHas(),上面的方法返回与作为第一个参数输入的列匹配的那些属性。我们的第二个参数基于链接到查询对象的方法过滤该列。

然后,我们通过将这些租户附加到返回的属性中来进行后续操作,并获得结果。

生成和插入动态属性

我们假设有两个新模型:TechniciansRequests。技术人员与其他技术人员共享多个请求。如果我们希望有一种方法可以一眼就能轻松地看到我们的数据,那么每个技术人员对象有多少个请求呢?我们可以将它们每个都作为延迟加载包含进来,然后获取数组的长度,或者我们可以创建一个动态属性来计算并保存该值。

首先,我们必须在Technician模型添加以下方法:

public function getRequestsCountAttribute()
{
    return $this->requests()->count();
}

在Laravel中,动态属性的命名约定:

  • 使用camelCase
  • get开始
  • 包含您想要的下一个列名称
  • 结束于 Attribute

因此,以上方法将在我们返回的技术人员上创建一个动态列,称为requests_count,该列将包含附加至模型的已连接请求的数量。

轻松过滤日期

关于第五个也是最后一个技巧,让我们回到租户模型。正如我们前面提到的,每个人的租约到期时都有一列要保存。好吧,如果我们只想返回那些在2021年7月到期的用户,该怎么办?

我们也许可以做类似的事情:

public function test(Request $request)
{
    return Tenant::where('lease_expires_at', 'LIKE', '2021-07-%')->get();
}

那将完美地工作,并且只返回我们想要的租户。但是我并不热衷于LIKE在不需要的地方使用语句。它们可能会变得凌乱,Laravel为我们提供了两种更好的方法:

public function test(Request $request)
{
    return Tenant::whereMonth('lease_expires_at', '07')->whereYear('lease_expires_at', '2021)->get();
}

使用whereMonthwhereYear,我们只能过滤那些租约在2021年7月到期的模型。如果我们想提供一些动态过滤功能,我们甚至可以将那些硬编码的值替换为,$request->get('month')或者$request->get('year')则可以替换。

目前为止就这样了!

这是五个简单但功能强大的方法和组织技巧,可用于Laravel的Eloquent ORM来提高生产力。此外,这可能有助于您开始思考如何优化查询并减少整体代码混乱。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 1

第一条可以用 when 来解决吧

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!