PHP单例返回对象spl_object_hash值不同但spl_object_id一致问题
PHP单例模式下spl_object_hash跨请求不一致问题解答
你遇到的现象是PHP的运行机制和两个函数的实现差异导致的,属于正常情况,和你的单例实现本身没有关系:
- 首先明确PHP的单例生效范围:PHP是无状态的脚本语言,所有静态属性、对象的生命周期仅局限在单次请求内,请求处理完成后所有资源都会被销毁。你如果是每次刷新页面/发新请求测试,每次都会重新初始化
TestController::$test_obj,本质上每次创建的都是新的Test对象,PHP原生不支持跨请求的单例,跨请求的全局单例需要借助APCu、Redis等外部存储实现。 - 两个函数的实现差异:
spl_object_id()仅返回对象在当前进程内存中的整数句柄序号,每次请求创建对象时如果刚好占用同一个序号槽位,就会出现跨请求返回相同ID的情况,这只是内存分配的巧合,不是单例跨请求生效了。spl_object_hash()是基于对象内存地址、当前进程随机因子等多个参数生成的唯一字符串,就算不同请求的对象ID一致,生成的哈希值也必然不同。
单例正确性验证方法
你可以在单次请求内多次获取实例验证单例是否生效,测试代码如下:
namespace App\Http\Controllers; class MainController extends Controller { public function index() { $test_obj1 = TestController::get(); $test_obj2 = TestController::get(); // 同一次请求内两次获取的实例哈希完全一致 var_dump(spl_object_hash($test_obj1) === spl_object_hash($test_obj2)); // 输出 bool(true) } }
额外注意
你当前的单例实现是管控Test类的实例代理,如果你要实现TestController本身的单例,需要将get方法中的实例化逻辑改为new self()。同时为了避免外部通过克隆、反序列化创建新实例破坏单例,建议补充两个私有方法:
private function __clone() {} private function __wakeup() {}
内容的提问来源于stack exchange,提问作者The Odd Developer
相关产品推荐
相关产品推荐

