在Laravel项目开发中,经常需要处理模型字段的动态筛选需求,比如需要找出模型中所有字段名包含name的字段及其对应的键值对,这种场景在动态表单处理、通用数据导出等功能中非常常见。实现这个需求的核心是先获取模型的所有属性,再对属性键进行筛选,最后提取符合条件的键值对。

实现思路拆解
要实现动态查找包含name的字段键值对,整体可以分为三个步骤:
- 第一步,获取模型当前实例的所有原始属性,Laravel模型提供了
getAttributes()方法可以直接获取原始属性数组,避免获取访问器处理后的数据干扰筛选。 - 第二步,遍历属性数组的键名,筛选出包含name字符串的键名,这里可以使用PHP的
str_contains函数进行判断。 - 第三步,将筛选后的键名和对应的属性值组合成新的键值对数组,返回给调用方使用。
基础实现代码示例
我们可以在模型类中定义一个通用方法,方便后续复用:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
// 其他模型配置...
/**
* 动态查找包含name的字段键值对
* @return array
*/
public function getFieldsContainingName(): array
{
// 获取模型所有原始属性
$attributes = $this->getAttributes();
$result = [];
// 遍历属性筛选符合条件的键值对
foreach ($attributes as $key => $value) {
// 判断字段名是否包含name
if (str_contains($key, 'name')) {
$result[$key] = $value;
}
}
return $result;
}
}
使用示例
假设我们有一个User模型,包含id、username、nickname、email、age等字段,调用上述方法的效果如下:
<?php $user = User::find(1); // 假设该用户属性为: // [ // 'id' => 1, // 'username' => 'test_user', // 'nickname' => '测试用户', // 'email' => 'test@ipipp.com', // 'age' => 20 // ] $nameFields = $user->getFieldsContainingName(); // 返回结果: // [ // 'username' => 'test_user', // 'nickname' => '测试用户' // ]
进阶优化方案
如果需要更灵活的筛选规则,比如可以自定义要匹配的字符串,或者忽略大小写,可以对上述方法进行扩展:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class User extends Model
{
/**
* 动态查找包含指定关键词的字段键值对
* @param string $keyword 要匹配的关键词
* @param bool $ignoreCase 是否忽略大小写,默认true
* @return array
*/
public function getFieldsContainingKeyword(string $keyword, bool $ignoreCase = true): array
{
$attributes = $this->getAttributes();
$result = [];
foreach ($attributes as $key => $value) {
// 处理大小写忽略逻辑
$checkKey = $ignoreCase ? strtolower($key) : $key;
$checkKeyword = $ignoreCase ? strtolower($keyword) : $keyword;
if (str_contains($checkKey, $checkKeyword)) {
$result[$key] = $value;
}
}
return $result;
}
}
调用时如果需要查找包含name的字段,只需要传入name作为关键词即可,同时还支持查找其他关键词的字段,通用性更强。
注意事项
- 使用
getAttributes()方法获取的是模型的原始属性,不会触发访问器,如果需要获取访问器处理后的数据,可以替换为toArray()方法,但要注意toArray()会返回关联关系的处理数据,可能不符合预期。 - 如果模型使用了
$hidden属性隐藏了部分字段,getAttributes()方法仍然会返回这些隐藏字段的原始值,筛选时也会被包含在内,需要根据实际需求调整。 - 如果字段名是中文,
str_contains函数同样可以正常匹配,不需要额外处理编码问题。