
在 laravel 的闭包(如 `reduce`、`array_reduce`)中直接使用 `$this` 会报错“using $this when not in object context”,因其脱离了对象作用域;应改用 `parent::methodname()` 或将闭包转为 `use ($this)` 形式(php 7.4+),但后者不推荐。
该错误的根本原因在于:PHP 匿名函数默认不继承外部作用域中的 $this。即使你在 OrdersGraphs 实例方法中定义了闭包,该闭包本身是一个独立的函数对象,并不具备对当前对象实例的隐式引用。因此,$this->stringToFloat(...) 在闭包内部是非法的——PHP 此时根本不知道 $this 指向谁。
✅ 正确做法:使用 parent::stringToFloat()
由于 stringToFloat() 是定义在父类 Graph 中的 public 实例方法,且当前上下文是 OrdersGraphs 的实例方法(即 $this 确实存在),你只需在闭包外调用该方法,再将结果传入即可。但更简洁、语义更清晰的方式是——在闭包中显式通过 parent:: 调用父类方法(前提是方法非 static,且当前类继承自该父类):
$totalInData = $data->reduce(function ($carry, $item) {
return $carry + parent::stringToFloat($item->cogs); // ✅ 合法:parent:: 在继承链中解析为 Graph::stringToFloat
}, 0); // ⚠️ 别忘了提供初始值(如 0),否则 reduce 可能返回 null 导致类型错误⚠️ 注意事项:
- parent:: 只能在类方法内部(而非全局作用域或静态上下文)使用,且必须确保当前类确实继承自目标父类;
- parent::methodName() 调用的是父类中该方法的实现,若子类重写了该方法而你想调用父类原始逻辑,这正是其设计用途;
- 若你误将方法声明为 static(如 public static function stringToFloat()),则必须用 self:: 或 static:: 调用,但此时就失去了依赖实例状态的能力(如访问 $this->property),与原始设计意图相悖——你的 Graph 类方法无需静态化。
? 替代方案(不推荐,仅作技术说明):
PHP 7.4+ 支持在闭包中 use ($this),但强烈不建议:
$totalInData = $data->reduce(function ($carry, $item) use ($this) {
return $carry + $this->stringToFloat($item->cogs); // ❌ 危险!可能引发循环引用、内存泄漏,且违背封装原则
}, 0);此写法虽语法合法,但会使闭包持有对外部对象的强引用,干扰垃圾回收,且模糊了方法职责边界。
✅ 最佳实践总结:
- 保持工具方法为 public 实例方法(如你的 stringToFloat),体现其可能依赖未来扩展的实例状态;
- 在继承体系中,优先用 parent:: 显式调用父类逻辑,语义明确、安全可控;
- 避免无必要地将方法改为 static——除非它完全不依赖任何对象状态(纯函数式),否则会牺牲可测试性与可扩展性;
- 所有 reduce/map 等高阶函数调用务必指定初始值(如 0、[]),防止空集合时逻辑异常。
这样,你的 OrdersGraphs 不仅能复用 Graph 的通用能力,还能保持面向对象设计的清晰性与健壮性。










