Laravel中toArray()方法使用驼峰变量
前言
不知道大家在用Laravel开发过程中有没有遇到过模型查询时,with中使用驼峰命名变量名,但是使用toArray方法后,变量名变成了蛇形命名;
比如说这样的一条查询语句:
WorkflowModel::query()->with(['workflowsInfo'])->get()->toArray();

查询出来的结果可能就是这样的:

查询出来关联表的结果key变成了workflows_info这种蛇形命名方式 当然直接这样使用也是没有问题的,但是如果有需要比如说想直接使用key为workflowsInfo的情况,那有没有办法能处理呢?
使用的版本:
- PHP: 8.1.13
- Laravel: 10.13.5
源码分析
通过查看laravel源码 web/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1636
public function toArray()
{
return array_merge($this->attributesToArray(), $this->relationsToArray());
}
然后查看relationsToArray方法;
...
public static $snakeAttributes = true;
...
public function relationsToArray()
{
$attributes = [];
foreach ($this->getArrayableRelations() as $key => $value) {
// If the values implement the Arrayable interface we can just call this
// toArray method on the instances which will convert both models and
// collections to their proper array form and we'll set the values.
if ($value instanceof Arrayable) {
$relation = $value->toArray();
}
// If the value is null, we'll still go ahead and set it in this list of
// attributes, since null is used to represent empty relationships if
// it has a has one or belongs to type relationships on the models.
elseif (is_null($value)) {
$relation = $value;
}
// If the relationships snake-casing is enabled, we will snake case this
// key so that the relation attribute is snake cased in this returned
// array to the developers, making this consistent with attributes.
if (static::$snakeAttributes) {
$key = Str::snake($key);
}
// If the relation value has been set, we will set it on this attributes
// list for returning. If it was not arrayable or null, we'll not set
// the value on the array because it is some type of invalid value.
if (isset($relation) || is_null($value)) {
$attributes[$key] = $relation;
}
unset($relation);
}
return $attributes;
}
...
从代码中可以看到有个公共的变量,只要将这个公共的变量设置为false,就可以不用蛇形变量,保持原有的变量名;
所以这里给出下面两种方案来处理:
方案一
使用默认不转变的方法,来实现:
...
class WorkflowModel extends BaseModel
{
use HasDateTimeFormatter;
use SoftDeletes;
protected $table = 'workflows';
public static $snakeAttributes = false;
...
}

方案二
也可以使用静态方法设置的方式来改变$snakeAttributes的变量
...
class WorkflowModel extends BaseModel
{
use HasDateTimeFormatter;
use SoftDeletes;
protected $table = 'workflows';
public static function setNotSnakeAttributes(): Builder
{
parent::$snakeAttributes = false;
return static::query();
}
...
}
WorkflowModel::setNotSnakeAttributes()->with(['workflowsInfo'])->get()->toArray();

总结
以上就是暂时想到的两种方案,大家如果有更好的想法,可以留言一起讨论。
通过分析Laravel源码,我们发现了$snakeAttributes这个静态属性控制着关联关系在toArray()方法中的命名方式。通过设置这个属性为false,我们可以保持原有的驼峰命名方式,避免自动转换为蛇形命名。
这两种方案各有优势:
- 方案一:简单直接,在模型中直接设置静态属性
- 方案二:更加灵活,可以通过静态方法动态控制
选择哪种方案取决于你的具体需求和项目架构。