用于PHP的spl\u对象\u哈希<;5.2(对象实例的唯一ID)

用于PHP的spl\u对象\u哈希<;5.2(对象实例的唯一ID),php,spl,Php,Spl,我试图在PHP5+中为对象实例获取唯一的ID 这个函数可以从PHP5.2中获得,但是我想知道是否有一个解决老PHP版本问题的方法 在php.net上的注释中有几个函数,但它们不适合我。第一个(简化): 不适用于本机对象(如DOMDocument),第二个: function spl_object_hash($object){ if (is_object($object)){ ob_start(); var_dump($object); $d

我试图在PHP5+中为对象实例获取唯一的ID

这个函数可以从PHP5.2中获得,但是我想知道是否有一个解决老PHP版本问题的方法

在php.net上的注释中有几个函数,但它们不适合我。第一个(简化):

不适用于本机对象(如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;
    }
看起来这可能是一个重大的性能破坏


有人有什么秘密吗?

可以完成你的任务吗?

我做了几个快速测试。我真的认为最好使用
bind('evt_name',array($obj,'callback_function'))在bind()函数中存储真正的回调。
。如果您绝对希望使用spl_object_散列路径,而不是使用事件绑定存储引用,那么您将看到以下内容:

变量转储/提取和哈希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;
}
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;
}
一个朴素的引用实现:

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;
}
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;
}
这个函数基本上比基于类的引用函数差5-50倍,所以不值得担心

按类实现的存储引用:

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;
}
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;
}
而你最终得到的是。摘要:基于类的引用实现在n/50个类左右表现最好——在最好的情况下,它设法使基于
var\u dump
的实现的性能降低了1/3,而且通常要差得多


var\u dump
实现似乎是可以接受的,但并不理想。但是如果你没有做太多这样的查找,它不会成为你的瓶颈。特别是作为PHP<5.2 boxen的后备方法。

我曾经为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;
}
/**
*获取对象哈希
*
*返回每个对象的唯一哈希值。
*
*服务器上wordpress分期付款的代理功能
*PHP版本<5.2.0。
*
*@自3.0.2
*@note因版本3.2.0(PHP5.2要求)而被弃用
*@param object$object
*@返回字符串唯一对象哈希
*/
函数wp_object_hash(&$object){
静态$prefix,$count=0,$property='\uuuuuuwpookbjhash\uuuuuuuuu',$spl\u函数存在;
isset($spl_function_exists)| |$spl_function_exists=function_exists('spl_object_hash');
//首选spl\u对象\u哈希(如果可用)
如果($spl\u函数\u存在)
返回spl\u object\u散列($object);
//验证输入
如果(!is_object($object)){
trigger_error(_函数__.''()期望参数1为object,E_USER_警告);
返回null;
}
//设置前缀和计数器以生成对象哈希,如果未设置,则将其设置为对象
isset($prefix)| |($prefix=uniqid(“”))&&$property.=$prefix.| |;
isset($object->$property)| |($object->$property=sprintf(“%s-%08d”,$prefix,++$count));
返回$object->$property;
}

如果您使用的是PHP5版本,则不需要通过引用传递参数。

这就是您想要的。

我已经修复了一个非常可能的bug,并将函数从(也是从php.net借用的)简化为:

它返回一个整数(通常在小于100的范围内),该整数对于任何对象都是唯一的(有关所看到的内容的详细信息,请参阅)



另外,我在真实场景中使用此实现

您为什么需要它?也许真正的解决方案是你不需要这个——这可能表明你的设计中存在一些问题?我正在开发一个CMS,正在构建一个“事件”系统。可以使用以下代码触发事件:
trigger('evt_name',new Event())
。CMS插件可以使用
bind('evt\u name','callback\u function')
与系统事件“绑定”。我想做的是向这两个函数添加另一个参数,它接受事件应该绑定到的实例,但要存储事件数据(在对象本身之外),我需要将其转换为一个唯一的字符串,用作数组键。你的想法是什么?我对此没有真正的答案,但我认为了解更多可能会有所帮助(即使不是我^^)——不管怎样,我从来没有觉得需要为一个对象获取任何类型的“唯一ID”;;也许您只能在某个地方存储对该对象的引用?我可以存储对实例的引用,但这需要在每次触发事件时进行大量数组迭代(以检查每个绑定是否附加到触发事件的对象)。我知道还有其他方法,但我还是想知道是否有更好的方法来模拟
spl\u object\u hash()
。我也没有一个明确的答案,但它不是可以归结为一个简单的数组($obj,$data),其中键是不相关的吗?哇,谢谢,我已经放弃了得到答案!我需要稍微消化一下你的代码(尽管稍后我还在工作;p),但我会给你回复的。我正在编写的代码将是分布式系统的一部分,我希望支持php5