You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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;
    }
}

关键说明

  1. get方法:同时存储原始浮点值和格式化后的字符串,兼顾两种场景需求
  2. __toString:输出时自动返回逗号分隔的格式化字符串
  3. __float:PHP 8.0及以上版本中,实例参与数值运算时会自动转为浮点值,解决运算类型错误
  4. 兼容PHP7.x:若项目版本低于8.0,可使用__invoke方法,运算时调用$sum = $data->level() + $data->level();
  5. set方法:处理存储逻辑,确保前端传入的逗号分隔数值能正确转为数据库支持的点分隔格式

内容的提问来源于stack exchange,提问作者Ivan Nack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:14:57