Laravel MongoDB中整数、浮点数及布尔字段存为字符串如何解决?
解决Laravel中MongoDB字段数据类型存储错误问题
问题概述
在Laravel项目中使用MongoDB时,age(整数)、height/weight(浮点数)、concluded(布尔值)字段被存储为带引号的字符串类型,而非预期的对应原生数据类型。
当前存储结果
{ "_id": { "$oid": "64b41ba740f8fc543547b2d3" }, "name": "Michael", "age": "20", "height": "1.89", "weight": "78.79", "begin": "2023-07-16", "finish": "2023-07-28", "concluded": "true", "updated_at": { "$date": "2023-07-16T16:33:22.423Z" }, "created_at": { "$date": "2023-07-16T16:32:39.375Z" } }
预期存储结果
{ "_id": { "$oid": "64b41ba740f8fc543547b2d3" }, "name": "Michael", "age": 20, "height": 1.89, "weight": 78.79, "begin": "2023-07-16", "finish": "2023-07-28", "concluded": true, "updated_at": { "$date": "2023-07-16T16:33:22.423Z" }, "created_at": { "$date": "2023-07-16T16:32:39.375Z" } }
相关代码文件
迁移文件 2023_07_08_114314_create_persons_table.php
public function up() { Schema::create('persons', function (Blueprint $collection) { $collection->string('name'); $collection->integer('age'); $collection->double('height'); $collection->double('weight'); $collection->date('begin'); $collection->date('finish'); $collection->boolean('concluded')->default(false); $collection->timestamps(); $collection->softDeletes(); }); }
模型 PersonModel.php
class PersonModel extends Model { use HasFactory, SoftDeletes; protected $connection = 'mongodb'; protected $collection = 'persons'; protected $primary_key = '_id'; protected $fillable = [ 'name', 'age', 'height', 'weight', 'begin', 'finish', 'concluded', ]; }
控制器 PersonController.php
public function store(PersonRequest $request) { PersonModel::create(array_map('trim', $request->validated())); Log::channel('daily')->info("$request->name was added in system."); return redirect('/')->with('success_store', "$request->name was added in system."); }
解决方案
问题根源:HTTP请求传递的所有参数默认都是字符串类型,即便迁移文件定义了字段类型,Laravel MongoDB不会自动进行类型转换,需要显式指定字段的类型转换规则。
方案1:模型中添加$casts属性(推荐)
在PersonModel中添加$casts数组,明确指定每个字段的目标数据类型,Laravel会自动在存储和读取时完成类型转换:
class PersonModel extends Model { use HasFactory, SoftDeletes; protected $connection = 'mongodb'; protected $collection = 'persons'; protected $primaryKey = '_id'; // 修正:Laravel规范为驼峰式$primaryKey,原属性名错误 protected $fillable = [ 'name', 'age', 'height', 'weight', 'begin', 'finish', 'concluded', ]; // 添加类型转换规则 protected $casts = [ 'age' => 'integer', 'height' => 'float', 'weight' => 'float', 'concluded' => 'boolean', 'begin' => 'date', 'finish' => 'date' ]; }
方案2:控制器中手动转换数据类型
在创建模型实例前,手动将字符串转换为对应数据类型:
public function store(PersonRequest $request) { $data = array_map('trim', $request->validated()); // 手动转换类型 $data['age'] = (int)$data['age']; $data['height'] = (float)$data['height']; $data['weight'] = (float)$data['weight']; // 兼容字符串格式的布尔值转换 $data['concluded'] = filter_var($data['concluded'], FILTER_VALIDATE_BOOLEAN); PersonModel::create($data); Log::channel('daily')->info("$request->name was added in system."); return redirect('/')->with('success_store', "$request->name was added in system."); }
方案3:在请求验证类中转换类型
在PersonRequest类中添加prepareForValidation方法,在验证前完成类型转换:
class PersonRequest extends FormRequest { // ... 其他规则方法 protected function prepareForValidation() { $this->merge([ 'age' => (int)$this->age, 'height' => (float)$this->height, 'weight' => (float)$this->weight, 'concluded' => filter_var($this->concluded, FILTER_VALIDATE_BOOLEAN), ]); } }
注意:方案1是最简洁且符合Laravel最佳实践的方式,推荐优先使用。同时修正模型中的
$primary_key为$primaryKey,避免潜在的主键识别问题。
内容的提问来源于stack exchange,提问作者user22236733
相关产品推荐
相关产品推荐

