
本教程详细介绍了如何在 lar*el 应用中,针对具有父子关系的数据库表(如 `posts` 和 `posts_tags`),同时进行多条件查询和过滤。我们将探讨如何利用 eloquent orm 的 `join` 方法实现跨表数据筛选,以及作为替代方案的 `wherehas` 方法,帮助开发者高效地构建复杂的搜索功能,提升数据检索的灵活性和准确性。
在构建复杂的 Web 应用程序时,经常需要根据来自多个相关表的数据进行过滤和搜索。例如,在一个内容管理系统中,您可能需要根据文章的发布年份(存储在父表 posts 中)和文章关联的标签(存储在子表 posts_tags 中)来搜索文章。本教程将指导您如何在 Lar*el 中高效地实现这种父子表联合查询与过滤。
首先,我们回顾一下示例中 Post 和 PostTag 模型之间的关系。
Post.php (父模型)
<?php
namespace App\Models\Posts;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $table="posts";
protected $guarded = [];
// 定义与 PostTag 的一对多关系
public function PostTags() {
return $this->hasMany('App\Models\Posts\PostTag');
}
}PostTag.php (子模型)
<?php
namespace App\Models\Posts;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class PostTag extends Model
{
use HasFactory;
protected $table="posts_tags";
protected $guarded = [];
// 定义与 Post 的反向一对多关系
public function GetPost() {
return $this->belongsTo('App\Models\Posts\Post');
}
}这里,Post 模型通过 hasMany 方法定义了它拥有多个 PostTag,而 PostTag 模型通过 belongsTo 方法定义了它属于一个 Post。这是 Lar*el 中标准的一对多关系定义。
用户通过一个包含年份和标签选择框的表单提交搜索请求。
搜索表单 (View)
<form action="{{ route('movies.movie_search') }}" method="GET">
@csrf
<select name="tag" class="select">
<option value="" selected="selected">@lang('movies.movie_all')</option>
@if ($tags)
@foreach ($tags AS $tag)
<option value="{{ $tag->id }}">{{ $tag->name }}</option>
@endforeach
@endif
</select>
<select name="year" class="select">
<option value="" selected="selected">@lang('public.public_year')</option>
@php
$date = date('Y');
for ($i = $date; $i > 1970; $i--) {
echo "<option value=".$i.">".$i."</option>";
}
@endphp
</select>
<button type="submit" name="" class="filter">@lang('public.public_filter')</button>
</form>路由定义 (web.php)
Route::prefix('/movies')->group(function (){
Route::get('/search', [MovieController::class, 'MoviesDataSearch'])->name('movies.movie_search');
});表单通过 GET 请求将 tag 和 year 参数发送到 movies.movie_search 路由,由 MovieController 的 MoviesDataSearch 方法处理。
LongShot
LongShot 是一款 AI 写作助手,可帮助您生成针对搜索引擎优化的内容博客。
77
查看详情
在控制器中,我们需要根据 Request 对象中传入的 year 和 tag 参数来构建查询。
当需要根据关联表中的字段进行过滤,并且可能需要从关联表中选择数据时,使用数据库 JOIN 操作是最直接有效的方式。
MovieController.php
<?php
namespace App\Http\Controllers\Movies;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Posts\Post; // 引入 Post 模型
use App\Models\Posts\PostTag; // 引入 PostTag 模型 (虽然在此方案中不直接使用,但仍需引入)
class MovieController extends Controller
{
public function MoviesDataSearch(Request $request) {
// 确保 $request 不为空,或根据业务逻辑处理无搜索条件的情况
// 这里的 empty($request) 判断通常不准确,应判断具体的搜索参数是否存在
if (empty($request->year) && empty($request->tag)) {
// 如果没有搜索条件,返回所有电影
return Post::where('post_type', "movie")
->where('is_delete', "0")
->orderBy('id', 'DESC')
->Paginate(12);
}
$query = Post::query(); // 初始化查询构建器
// 筛选基本条件
$query->where('posts.post_type', "movie")
->where('posts.is_delete', "0");
// 如果存在年份条件,则添加年份过滤
if ($request->filled('year')) {
// 注意:如果 year 是精确匹配,应使用 '=' 而非 'like'
// 如果需要模糊匹配,使用 'like'
$query->where('posts.year', $request->year); // 假设是精确匹配
// 如果是模糊匹配:$query->where('posts.year', 'like', '%'.$request->year.'%');
}
// 如果存在标签条件,则进行 JOIN 操作并添加标签过滤
if ($request->filled('tag')) {
$query->join('posts_tags', 'posts.id', '=', 'posts_tags.post_id');
// 注意:如果 tag_id 是精确匹配,应使用 '=' 而非 'like'
// 如果需要模糊匹配,使用 'like'
$query->where('posts_tags.tag_id', $request->tag); // 假设是精确匹配
// 如果是模糊匹配:$query->where('posts_tags.tag_id', 'like', '%'.$request->tag.'%');
}
// 为了避免在 JOIN 操作后出现重复的 Post 记录(如果一个 Post 有多个匹配的 PostTag),
// 并且只关心 Post 本身的数据,可以使用 distinct() 或 groupBy()
// 但如果只需要 Post 的数据,并且 PostTag 的过滤是排他性的,则可能不需要。
// 这里我们假设每个 Post 只需要被返回一次,且只关心 Post 自身的数据。
// 如果需要 PostTag 的数据,则需要指定 select 字段。
$query->select('posts.*'); // 明确选择 Post 表的所有字段,避免字段名冲突
$movies = $query->orderBy('posts.id', 'DESC')->Paginate(2);
// 将所有请求参数附加到分页链接,以便在切换页面时保留搜索条件
return $movies->appends($request->all());
}
}代码解析:
whereHas 是 Eloquent 提供的一种更“Eloquent”的方式来过滤基于关联模型的记录。它在内部通常会生成一个子查询,用于检查是否存在满足特定条件的关联记录。
<?php
namespace App\Http\Controllers\Movies;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Posts\Post;
class MovieController extends Controller
{
public function MoviesDataSearch(Request $request) {
if (empty($request->year) && empty($request->tag)) {
return Post::where('post_type', "movie")
->where('is_delete', "0")
->orderBy('id', 'DESC')
->Paginate(12);
}
$query = Post::where('post_type', "movie")
->where('is_delete', "0");
// 如果存在年份条件
if ($request->filled('year')) {
$query->where('year', $request->year);
}
// 如果存在标签条件,使用 whereHas
if ($request->filled('tag')) {
$query->whereHas('PostTags', function ($q) use ($request) {
$q->where('tag_id', $request->tag);
});
}
$movies = $query->orderBy('id', 'DESC')->Paginate(2);
return $movies->appends($request->all());
}
}代码解析:
在本教程的场景中,两种方法都能有效实现需求。如果仅仅是根据关联表的存在性进行过滤,whereHas 更加优雅。如果涉及到从关联表选择数据或更复杂的查询,join 可能是更好的选择。
通过掌握 join 和 whereHas 这两种强大的 Eloquent ORM 方法,您将能够灵活地处理 Lar*el 应用程序中各种复杂的父子表联合查询与过滤需求。选择哪种方法取决于您的具体需求、性能考量以及代码可读性的偏好。
以上就是Lar*el 中父子表联合查询与过滤:实现多条件搜索教程的详细内容,更多请关注php中文网其它相关文章!
# laravel
# 您的
# 这是
# 多条
# 多个
# 是否存在
# 分页
# 回调
# 代码可读性
# 表单提交
# 路由
# 回调函数
# app
# php
# 表单
# 营销推广规划模板
# 泰安seo课程
# 自助网站建设文章怎么写
# 知名seo优化有哪些
# 信阳网站推广有哪些
# 宁波海曙区seo地址
# 延川做网站优化的地方
# 零售智能营销推广系统
# 高明交通建设招聘网站
# 水杯的推广营销方案策划
# 面向对象
# 是在
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
J*aScript与HTML元素交互:图片点击事件与链接处理教程
163邮箱网页版官方登录入口 163邮箱网页版访问页面
《小宇宙》标记不友善评论方法
漫蛙官网(首页入口)_漫蛙漫画稳定访问教程分享
智慧职教mooc平台登录网址 智慧职教mooc官网直达
PySimpleGUI中实现键盘按键与按钮事件绑定教程
如何使用CSS Grid实现“大方块左侧,小方块右侧垂直堆叠”的水平布局
mysql中外键约束如何使用_mysql FOREIGN KEY操作
飞飞漫画漫画阅读官网_飞飞漫画漫画阅读官网进入阅读
京东物流快递破损了怎么办_京东快递破损理赔流程
J*aScript二进制处理_ArrayBuffer与Blob
《东方财富》条件单关闭方法
百度识图图像分析 百度识图识别平台
铁路12306官网登录入口 铁路12306在线购票官方平台
抖音如何进行蓝V认证 抖音企业号申请所需资料与流程
diskgenius分区工具如何设置Bios启动项
mysql如何限制远程访问_mysql远程访问限制方法
抖音作品被限流怎么办 抖音内容优化与流量恢复方法
163邮箱在线登录 163邮箱网页版在线入口
抖音视频如何添加标题?添加标题有哪些好处?
优化2xN网格最大路径和的动态规划算法实践
在PySimpleGUI中实现键盘按键绑定按钮事件
B站怎么快速升级 B站用户等级提升攻略【详解】
抖音评论无法发送如何修复 抖音评论功能操作指南
VS Code中的Tailwind CSS IntelliSense插件使用技巧
《雷电模拟器》自动点击设置方法
如何在mysql中使用索引提示_mysql索引提示优化方法
谷歌浏览器官方镜像获取方法_谷歌浏览器网页版入口极速直达
顺丰官方查单号入口 顺丰快递单号查询官网入口
人教版电子教材在线获取指南
《律学法考》查看学习数据方法
如何在Python中安全地将环境变量转换为整数并满足Mypy类型检查
在Spring Boot Thymeleaf中利用布尔属性实现容器的条件显示
获取WooCommerce产品在后台编辑页面的分类ID
yandex网页版直接登录 yandex官方入口平台访问方法
BunnyStream TUS视频上传指南:解决401认证错误与参数配置
51漫画网实时入口 51漫画网页版官方免费漫画入口
Lar*el 关联查询:同时筛选父表与子表数据的高效策略
《米姆米姆哈》米姆获取及技能攻略
Yandex俄罗斯搜索引擎官网入口 Yandex网页端直接访问
铁路12306买票怎么选双人铺 铁路12306卧铺分配规则说明
向日葵客户端怎么进行语音通话_向日葵客户端语音通话功能使用方法
在J*a里什么是行为抽象_抽象行为对代码复用的提升作用
Python测试中模块导入路径解析的最佳实践
《海底捞》点外卖方法
《杖剑传说》食谱大全
魔法祈幻界兑换码礼包大全
MySQL多重JOIN技巧:高效关联同一表获取多角色信息
掌握产品代码正则表达式:避免常见陷阱与精确匹配
《顺丰同城骑士》查看我的技能方法
2025-11-30
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。