如何实现Laravel Eloquent Cast:输出逗号小数+运算用点小数
Laravel Eloquent Cast 实现数值格式化与运算兼容
需求与问题
数据库存储点分隔小数(如1.1、1.19、2),需要实现Eloquent Cast类满足:
- 输出(echo/print)时返回逗号分隔小数(如1,10、1,19)
- 数学运算(求和、乘法等)正常执行(如
$sum = $data->level + $data->level得到2.29)
当前困境:
- 原Cast类输出正常,但运算时报错:
Unsupported operand types: App\Models\Casts\NumberFormat + App\Models\Casts\NumberFormat - 若get方法直接返回数值,运算正常但输出为点分隔小数
解决方案
通过PHP魔术方法让Cast实例同时支持字符串输出和数值运算:
- 保留
__toString方法处理格式化输出 - 利用
__float(PHP 8.0+)或__invoke方法让实例参与运算时自动转为浮点值
修改后的完整Cast类代码
namespace App\Models\Casts; use Illuminate\Contracts\Database\Eloquent\CastsAttributes; use Illuminate\Database\Eloquent\Model; class NumberFormat implements CastsAttributes { private float $rawValue; private string $formattedValue; public function get(Model $model, string $key, mixed $value, array $attributes) { $this->rawValue = (float)$value; $this->formattedValue = number_format($this->rawValue, 2, ',', ''); return $this; } public function set(Model $model, string $key, mixed $value, array $attributes) { // 将逗号分隔的数值转为点分隔,存入数据库 return is_string($value) ? str_replace(',', '.', $value) : $value; } public function __toString(): string { return $this->formattedValue; } public function __float(): float { return $this->rawValue; } // 兼容PHP 7.x版本,可选 public function __invoke(): float { return $this->rawValue; } }
关键说明
- get方法:同时存储原始浮点值和格式化后的字符串,兼顾两种场景需求
- __toString:输出时自动返回逗号分隔的格式化字符串
- __float:PHP 8.0及以上版本中,实例参与数值运算时会自动转为浮点值,解决运算类型错误
- 兼容PHP7.x:若项目版本低于8.0,可使用
__invoke方法,运算时调用$sum = $data->level() + $data->level(); - set方法:处理存储逻辑,确保前端传入的逗号分隔数值能正确转为数据库支持的点分隔格式
内容的提问来源于stack exchange,提问作者Ivan Nack
相关产品推荐
相关产品推荐

