我正在尝试在PHP 5 +中获取对象实例的唯一ID。
函数spl_object_hash()
可以从PHP 5.2获得,但我想知道是否有旧的PHP版本的解决方法。
php.net上的评论中有几个功能,但它们对我不起作用。第一个(简化):
function spl_object_hash($object){
if (is_object($object)){
return md5((string)$object);
}
return null;
}
不适用于本机对象(例如DOMDocument),第二条:
function spl_object_hash($object){
if (is_object($object)){
ob_start();
var_dump($object);
$dump = ob_get_contents();
ob_end_clean();
if (preg_match('/^object\(([a-z0-9_]+)\)\#(\d)+/i', $dump, $match)) {
return md5($match[1] . $match[2]);
}
}
return null;
}
看起来它可能是一个主要的性能破坏者!
有人有任何东西吗?
答案 0 :(得分:4)
我跑了几个快速测试。我真的认为你最好使用bind('evt_name', array($obj, 'callback_function'))
在bind()函数中存储真正的回调。如果您绝对想要使用spl_object_hash路由,而不是使用事件绑定存储引用,那么您正在查看类似这样的内容:
var_dump / extract和hash id实现:
function spl_object_hash_var_dump($object){
if (is_object($object)){
ob_start();
var_dump($object);
$dump = ob_get_contents();
ob_end_clean();
if (preg_match('/^object\(([a-z0-9_]+)\)\#(\d)+/i', $dump, $match)) {
return md5($match[1] . $match[2]);
}
}
return null;
}
一个天真的参考实现:
function spl_object_dumb_references(&$object) {
static $hashes;
if (!isset($hashes)) $hashes = array();
// find existing instance
foreach ($hashes as $hash => $o) {
if ($object === $o) return $hash;
}
$hash = md5(uniqid());
while (array_key_exists($hash, $hashes)) {
$hash = md5(uniqid());
}
$hashes[$hash] = $object;
return $hash;
}
这个基本上比基于类的参考函数差5-50倍,所以不值得担心。
按类实现引用的商店:
function spl_object_hash_references(&$object) {
static $hashes;
if (!isset($hashes)) $hashes = array();
$class_name = get_class($object);
if (!array_key_exists($class_name, $hashes)) {
$hashes[$class_name] = array();
}
// find existing instance
foreach ($hashes[$class_name] as $hash => $o) {
if ($object === $o) return $hash;
}
$hash = md5(uniqid($class_name));
while (array_key_exists($hash, $hashes[$class_name])) {
$hash = md5(uniqid($class_name));
}
$hashes[$class_name][$hash] = $object;
return $hash;
}
你最终得到了results that look like this。总结:基于类的引用实现在n / 50个类中表现最佳 - 在最好的情况下,它设法将基于var_dump
的实现的性能提高了1/3,并且它通常很多更糟。
var_dump
实施似乎是可以忍受的,尽管并不理想。但是如果你没有做太多这些查找,那么它就不会成为你的瓶颈。特别是作为PHP的后备< 5.2 boxen。
答案 1 :(得分:1)
我曾经为wordpress编写了一个辅助函数,它为每个对象提供一个唯一的哈希值,它与一个计数器一起工作,如果已经将哈希值分配给一个对象,则将其作为公共类属性存储。以下示例演示了这一点:
/**
* get object hash
*
* Returns a unique hash per object.
*
* Proxy function for wordpress installments on servers
* with a PHP version < 5.2.0.
*
* @since 3.0.2
* @note Become deprecated with version 3.2.0 (PHP 5.2 requirements)
* @param object $object
* @return string unique object hash
*/
function wp_object_hash( &$object ) {
static $prefix, $count = 0, $property = '__wphookobjhash__', $spl_function_exists;
isset( $spl_function_exists ) || $spl_function_exists = function_exists( 'spl_object_hash' );
// prefer spl_object_hash if available
if ( $spl_function_exists )
return spl_object_hash( $object );
// validate input
if ( !is_object( $object ) ) {
trigger_error( __FUNCTION__ . '() expects parameter 1 to be object', E_USER_WARNING );
return null;
}
// setup prefix and counter to generate object hash, set it to object if not set
isset( $prefix ) || ( ( $prefix = uniqid( '' ) ) && $property .= $prefix . '__' );
isset( $object->$property ) || ( $object->$property = sprintf( '%s-%08d', $prefix , ++$count ) );
return $object->$property;
}
如果您使用的是PHP 5版本,则无需通过引用传递参数。
答案 2 :(得分:1)
这就是你想要的。
我修复了一个非常可能的错误,并将bobthecow answer(也是从php.net借来的)的函数简化为:
if ( !function_exists( 'spl_object_hash' ) ) {
function spl_object_hash( $object )
{
ob_start();
var_dump( $object );
preg_match( '[#(\d+)]', ob_get_clean(), $match );
return $match[1];
}
}
它返回一个整数(通常在sub-100范围内),这对于任何对象都是唯一的(有关您所看到的内容的详细信息,请参阅this answer。)
P.S。我在真实场景here
中使用此实现答案 3 :(得分:0)
uniqid()会为您的任务工作吗?