0

0

Laravel 8 教程:基于关联模型高效筛选 Blade 视图中的数据

DDD

DDD

发布时间:2025-11-09 12:15:01

|

668人浏览过

|

来源于php中文网

原创

laravel 8 教程:基于关联模型高效筛选 blade 视图中的数据

本教程旨在详细指导如何在 Laravel 8 应用中,根据数据库中存储的特定分类列表,高效地筛选产品数据并将其展示在 Blade 视图中。我们将深入探讨利用 Eloquent 关系查询 whereHas 进行数据库层面过滤的推荐方法,以及使用 Collection 的 filter 方法进行内存过滤的替代方案,并提供完整的代码示例、最佳实践和性能考量。

理解筛选需求与背景

在 Web 开发中,根据特定条件过滤数据是常见需求。本教程聚焦于一个典型场景:你有一个产品列表,每个产品都归属于某个分类。现在,你需要根据一个预定义的“目标分类”列表(例如,只显示“图书”和“衬衫”类的产品),从所有产品中筛选出符合条件的数据,并在 Blade 视图中展示。

为了实现这一目标,我们需要处理以下几个关键点:

  1. 数据模型设计: 确保产品和分类之间存在清晰的关联关系。
  2. 获取筛选条件: 从数据库或其他来源获取用于过滤的目标分类名称列表。
  3. 数据过滤逻辑: 在控制器中实现高效的数据筛选。
  4. 视图展示: 将筛选后的数据传递给 Blade 视图并正确渲染。

准备工作:模型与关系定义

为了充分利用 Laravel Eloquent 的强大功能,我们首先需要确保产品和分类之间建立了正确的模型和关系。

假设我们有以下数据库表结构:

  • products 表:
    • id (主键)
    • name (产品名称)
    • category_id (外键,关联 categories 表的 id)
    • created_at, updated_at
  • categories 表:
    • id (主键)
    • name (分类名称,例如 'Book', 'Shirt')
    • created_at, updated_at

基于此,我们需要定义 Product 和 Category Eloquent 模型,并建立它们之间的关系。

app/Models/Category.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

    /**
     * Get the products for the category.
     */
    public function products(): HasMany
    {
        return $this->hasMany(Product::class);
    }
}

app/Models/Product.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Product extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'category_id'];

    /**
     * Get the category that owns the product.
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(Category::class);
    }
}

通过以上定义,Product 模型可以通过 category 方法访问其所属的 Category 模型。

获取筛选条件:目标分类列表

在进行产品筛选之前,我们需要一个明确的“目标分类”列表。这个列表通常存储在数据库中,或者可以是一个硬编码的数组。根据原始问题描述,假设 categories 表(或另一个专门的配置表)提供了我们想要筛选的分类名称。

例如,如果我们的 categories 表中有 id:1, name:'Book' 和 id:2, name:'Shirt' 等记录,并且我们想筛选出所有属于“Book”和“Shirt”的产品,我们可以这样获取目标分类名称数组:

use App\Models\Category;

// 假设我们想要筛选的分类名称是 'Book' 和 'Shirt'
// 这可以是从另一个配置表、用户输入或硬编码获取
$targetCategoryNames = ['Book', 'Shirt'];

// 如果你需要从数据库动态获取这些名称,例如从一个特定的配置表
// $filterCategories = DB::table('filter_categories')->pluck('name')->toArray();
// $targetCategoryNames = $filterCategories;

// 或者如果 'categories' 表就是你的过滤来源,你只想筛选出其中一部分
// $targetCategoryNames = Category::whereIn('name', ['Book', 'Shirt'])->pluck('name')->toArray();

在接下来的示例中,我们将直接使用 $targetCategoryNames = ['Book', 'Shirt']; 作为示例。

AI Web Designer
AI Web Designer

AI网页设计师,快速生成个性化的网站设计

下载

解决方案一:使用 Eloquent whereHas 进行数据库层面过滤 (推荐)

whereHas 方法是 Eloquent 提供的强大功能,允许你根据关联模型上的条件来过滤父模型。这种方法会在数据库层面生成 SQL JOIN 或 EXISTS 子句,从而实现高效的数据过滤,尤其适用于处理大量数据。

原理:

  • whereHas('relationName', function ($query) { ... }):查询所有拥有至少一个满足回调函数中条件的关联模型实例的父模型。
  • 在回调函数内部,$query 对象代表关联模型的查询构建器。我们可以像对普通查询一样,使用 where、whereIn 等方法定义过滤条件。

ProductController.php 中的实现:

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use App\Models\Category; // 确保引入 Category 模型,如果需要从其获取过滤条件
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index(Request $request)
    {
        // 1. 定义目标分类名称列表
        // 假设这些是你想展示的分类,可以从配置、用户输入或数据库动态获取
        $targetCategoryNames = ['Book', 'Shirt']; 

        // 2. 使用 Eloquent whereHas 进行数据库层面过滤
        // 'category' 是 Product 模型中定义的关联方法名
        $filteredProducts = Product::whereHas('category', function ($query) use ($targetCategoryNames) {
            // 在关联的 categories 表中,查找 name 字段在 $targetCategoryNames 数组中的分类
            $query->whereIn('name', $targetCategoryNames);
        })->get(); // 执行查询并获取结果

        return view('products.index', compact('filteredProducts'));
    }
}

优点:

  • 性能优越: 过滤操作在数据库服务器上完成,避免了将所有数据加载到内存后再筛选的开销。对于大型数据集,性能优势显著。
  • 简洁明了: 代码表达力强,清晰地描述了“筛选出属于特定分类的产品”的意图。
  • 避免 N+1 问题: whereHas 本身不会导致 N+1 问题,因为它只用于过滤。如果你还需要在视图中显示分类名称,可以添加 with('category') 来预加载关联关系。

解决方案二:使用 Collection filter 进行内存过滤

如果数据集相对较小,或者你已经出于其他原因加载了所有产品及其关联分类,那么可以使用 Laravel Collection 的 filter 方法在 PHP 内存中进行筛选。

原理:

  • Collection::filter(function ($item) { ... }):遍历集合中的每个元素,对每个元素执行回调函数。如果回调函数返回 true,则该元素保留在新集合中;否则,该元素被移除。
  • in_array($needle, $haystack):PHP 内置函数,用于检查 $needle 是否存在于 $haystack 数组中。

ProductController.php 中的实现:

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use App\Models\Category;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index(Request $request)
    {
        // 1. 定义目标分类名称列表
        $targetCategoryNames = ['Book', 'Shirt'];

        // 2. 获取所有产品,并预加载其关联的分类(重要:避免 N+1 问题)
        $allProducts = Product::with('category')->get();

        // 3. 使用 Collection 的 filter 方法进行内存过滤
        $filteredProducts = $allProducts->filter(function (Product $product) use ($targetCategoryNames) {
            // 确保产品有分类,并且分类名称在目标列表中
            return $product->category && in_array($product->category->name, $targetCategoryNames);
        });

        // filter 方法会保留原始集合的键,如果需要从 0 开始的连续键,可以使用 values()
        $filteredProducts = $filteredProducts->values();

        return view('products.index', compact('filteredProducts'));
    }
}

优点:

  • 实现简单: 对于已经加载到内存中的数据,过滤逻辑直观。
  • 灵活性: 可以在回调函数中执行更复杂的 PHP 逻辑,而不仅仅是简单的数据库条件。

缺点:

  • 性能开销: 首先需要从数据库中获取所有产品及其关联分类,然后才在 PHP 内存中进行筛选。对于大数据集,这会导致大量的内存消耗和不必要的数据库查询,性能远低于 whereHas。
  • 潜在的 N+1 问题: 如果不使用 with('category') 预加载,在 filter 回调中每次访问 $product->category 都可能触发一次额外的数据库查询,导致 N+1 问题。

Blade 视图中的展示

无论你选择哪种筛选方法,最终控制器都会将一个包含 Product 模型实例的 Eloquent Collection 传递给 Blade 视图。在视图中,你可以像往常一样遍历这个集合并展示产品信息。

resources/views/products/index.blade.php:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>筛选后的产品列表</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        ul { list-style: none; padding: 0; }
        li { background-color: #f0f0f0; margin-bottom: 5px; padding: 10px; border-radius: 5px; }
        h1 { color: #333; }
        p { color: #666; }
    </style>
</head>
<body>
    <h1>筛选后的产品列表</h1>

    @if ($filteredProducts

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
laravel组件介绍
laravel组件介绍

laravel 提供了丰富的组件,包括身份验证、模板引擎、缓存、命令行工具、数据库交互、对象关系映射器、事件处理、文件操作、电子邮件发送、队列管理和数据验证。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

340

2024.04.09

laravel中间件介绍
laravel中间件介绍

laravel 中间件分为五种类型:全局、路由、组、终止和自定。想了解更多laravel中间件的相关内容,可以阅读本专题下面的文章。

293

2024.04.09

laravel使用的设计模式有哪些
laravel使用的设计模式有哪些

laravel使用的设计模式有:1、单例模式;2、工厂方法模式;3、建造者模式;4、适配器模式;5、装饰器模式;6、策略模式;7、观察者模式。想了解更多laravel的相关内容,可以阅读本专题下面的文章。

773

2024.04.09

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

385

2024.04.10

laravel入门教程
laravel入门教程

本专题整合了laravel入门教程,想了解更多详细内容,请阅读专题下面的文章。

141

2025.08.05

laravel实战教程
laravel实战教程

本专题整合了laravel实战教程,阅读专题下面的文章了解更多详细内容。

85

2025.08.05

laravel面试题
laravel面试题

本专题整合了laravel面试题相关内容,阅读专题下面的文章了解更多详细内容。

80

2025.08.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

571

2026.03.04

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号