使用 Eloquent ORM 使用 with 模型关联查询,如何处理select不同模型的字段(字段名可能相同)

本文介绍了一种使用关联模型查询特定用户的所有评论及其关联文章标题的方法。通过定义模型间的关系,可以实现一次查询获取所需信息,避免多次数据库访问。

遇到一个问题,就是articlesarticle_comments两个数据模型
现在要查出来某个用户的评论列表(列表包含 评论内容article_comments.content、评论时间article_comments.created_at、评论所属的文章articles.title)。
我首先需要根据article_comments中的user_id查询出来对应的评论列表,然后根据评论列表中的article_id,然后找到对应文章标题。

一. 关联模型(一对多)

  • articles 文章模型
// 核心方法
public function comments()
{
  return $this->hasMany('App\Models\ArticleComment')->orderBy('id', 'desc');
}
  • article_comments 评论模型
// 核心方法
public function article()
{
	return $this->belongsTo('App\Models\Article');
}

二. 获取某个用户的评论列表

// DB操作,主要是想打印一下sql
use Illuminate\Support\Facades\DB;

 public function comments($id)
 {
	 $user = \App\User::find($id);
	 if(empty($user)) {
		 echo '用户不存在';
		 exit;
	 }

	DB::connection()->enableQueryLog(); // 开启查询日志
    
	$commentList = ArticleComment::with(['article'=>function($query){
	     // 采用闭包进行处理,select出来想要的字段,但是必须包含关联外键 id
	     return $query->select('title as article_title', 'id');
	}])
	->where('user_id', $id)
	// 这里select出来评论模型的字段,但是也必须要包含外键 article_id
	->select('content', 'created_at','user_id','id','article_id')
	->orderBy('id','desc')
	->get();

    // 这个地方可以打印sql,挺不错的,记录一下
	foreach (DB::getQueryLog() as $sql) {
	    dump($sql['query']);
	}

	dd($commentList);
	exit;
}

最后注意:如果想要指定字段,使用 select 时,一定要写两个表的关联字段,不然是查不到关联关系的。

<think> 我们正在处理一个关于PHP链式查询时排除字段的问题。根据用户提供的引用,我们可以总结出以下信息: 引用[1]提到在QuerySet中有一个`exclude(*fields)`方法,用于从结果中排除某些字段。但请注意,这个引用似乎描述的是Django ORM或其他类似ORM的语法,而不是PHP。 引用[2]提到在ThinkPHP 6.0中,可以使用`withoutField()`方法进行字段排除,示例代码为: Db::table('students')->withoutField('details')->select() 引用[3]则提到了ThinkPHP 6.0的链式查询方法,特别是`order`方法,但并未直接涉及字段排除。 用户明确表示:“我想查找PHP链式查询时排除字段的方法”,并且引用了ThinkPHP 6.0的方法(withoutField),因此我们可以推测用户是在使用ThinkPHP框架。 因此,我们可以得出结论:在ThinkPHP 6.0中,排除字段的方法是使用`withoutField`方法。该方法可以链式调用,并且可以传递一个或多个字段名作为参数,以排除这些字段。 示例: // 排除单个字段 Db::table('students')->withoutField('details')->select(); // 排除多个字段,用逗号分隔或数组 Db::table('students')->withoutField('details,create_time')->select(); 或 Db::table('students')->withoutField(['details','create_time'])->select(); 需要注意的是,`withoutField`方法必须在`select`方法之前调用,因为它是链式查询的一部分。 另外,引用[1]中还提到了`only(*fields)`方法,它类似于`withoutField`的反操作,即只选择某些字段。在ThinkPHP中,对应的方法是`field`方法,如果传入字段名列表则表示只选择这些字段。 例如,只选择'name'和'age'字段: Db::table('students')->field('name, age')->select(); 因此,排除字段和只选择某些字段是两种不同的操作,用户可以根据需要选择使用。 下面我们以ThinkPHP 6.0为例,给出一个完整的示例代码: ```php use think\facade\Db; // 排除单个字段 $result1 = Db::table('students')->withoutField('details')->select(); // 排除多个字段 $result2 = Db::table('students')->withoutField('details,create_time')->select(); // 或者 $result3 = Db::table('students')->withoutField(['details','create_time'])->select(); // 如果同时需要指定其他条件 $result4 = Db::table('students') ->where('score', '>', 80) ->withoutField('details') ->order('id', 'desc') ->select(); ``` 注意:`withoutField`方法在ThinkPHP 6.0中可用,如果你使用的是其他版本的ThinkPHP,请查阅相应版本的文档。另外,如果是其他PHP框架(如Laravel),则排除字段的方法可能不同。例如在Laravel中,可以使用`select`方法并显式指定要选择的字段,或者使用`makeHidden`方法在模型实例中隐藏属性(但这发生在查询之后)。 由于用户的问题明确指向了排除字段,并且引用中出现了ThinkPHP的`withoutField`方法,因此我们主要围绕ThinkPHP来回答。 如果用户使用的是其他框架或原生PHP可能需要不同的方法。 根据用户的问题和引用,我们给出针对ThinkPHP 6.0的排除字段方法。 §§相关问题§§ 1. 在ThinkPHP 6.0中,如何同时排除多个字段? 2. 除了`withoutField`方法,ThinkPHP 6.0还有哪些常用的链式操作方法? 3. 在Laravel框架中如何实现查询时排除特定字段? </think> 基于提供的引用信息和PHP链式查询需求,以下是排除字段的具体方法及说明: ### PHP链式查询排除字段的方法 1. **ThinkPHP 6.0 专属方法** 使用 `withoutField()` 方法排除指定字段: ```php // 排除单个字段 Db::table('students')->withoutField('details')->select(); // 排除多个字段(数组形式) Db::table('students')->withoutField(['details', 'create_time'])->select(); ``` - **说明**:直接链式调用 `withoutField()`,参数可以是字段名字符串或字段名数组[^2]。 2. **通用字段选择法** 通过 `field()` 方法显式指定**需要保留**的字段,间接排除其他字段: ```php // 仅保留 name 和 age 字段(自动排除其他字段) Db::table('students')->field('name, age')->select(); ``` - **优势**:适用于所有支持链式调用的PHP ORM(如Laravel的Eloquent、ThinkPHP等)。 3. **结果集后处理(不推荐)** 若ORM不支持排除字段,可在查询后移除字段: ```php $result = Db::table('students')->select()->map(function($item) { unset($item['details']); return $item; }); ``` - **缺点**:效率较低,适合少量数据[^1]。 --- ### 关键区别 | **方法** | 适用场景 | 性能 | 示例 | |------------------|---------------------------|--------|--------------------------| | `withoutField()` | ThinkPHP 6.0+ | ★★★ | `->withoutField('email')`| | `field()` | 所有ORM(通用) | ★★★★ | `->field('name, age')` | | 结果集后处理 | 无法链式排除时 | ★☆ | `unset($item['field'])` | > **最佳实践**:优先使用ORM内置的字段排除/选择方法(如ThinkPHP的`withoutField()`或Laravel的`select()`),避免全字段查询+后处理[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值