spl_object_hash para php <5.2 (ID exclusivo para instâncias de objeto)

StackOverflow https://stackoverflow.com/questions/2299463

  •  21-09-2019
  •  | 
  •  

Pergunta

Estou tentando obter IDs exclusivos para instâncias de objetos no Php 5+.

A função, spl_object_hash() está disponível no Php 5.2, mas estou me perguntando se há uma solução alternativa para versões PHP mais antigas.

Existem algumas funções nos comentários no Php.net, mas eles não estão trabalhando para mim. O primeiro (simplificado):

function spl_object_hash($object){
    if (is_object($object)){
        return md5((string)$object);
        }
    return null;
    }

não funciona com objetos nativos (como DomDocument) e o segundo:

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;
    }

Parece que poderia ser um grande buster de desempenho!

Alguém tem alguma coisa na manga?

Foi útil?

Solução

Eu fiz alguns testes rápidos. Eu realmente acho que você seria melhor armazenar retornos de chamada reais em sua função bind () usando bind('evt_name', array($obj, 'callback_function')). Se você absolutamente deseja seguir a rota spl_object_hash, em vez de armazenar referências com as ligações de eventos, você está olhando para algo assim:

Uma implementação Var_Dump / Extract e 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;
}

Uma implementação ingênua de referências:

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;
}

Este era basicamente 5-50x pior do que a função de referência baseada em classe, por isso não vale a pena se preocupar.

Uma loja referências por implementação de classe:

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;
}

E você acaba com resultados que se parecem com isso. Resumo: A implementação de referências baseadas em classe tem um desempenho melhor em torno de N/50 Classes-da sua melhor, ele consegue fazer 1/3 do desempenho do var_dump implementação baseada, e geralmente é Muito de pior.

o var_dump A implementação parece ser tolerável, embora não seja ideal. Mas se você não está fazendo muitas dessas pesquisas, não será um gargalo para você. Especialmente como um fallback para PHP <5,2 Boxen.

Outras dicas

Certa vez, escrevi uma função auxiliar para o WordPress que oferece um hash exclusivo por objeto, ele funciona com um contador e armazena o hash por propriedade de classe pública se ele tiver sido atribuído a um objeto. O exemplo a seguir demonstra o seguinte:

/**
 * 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;
}

Se você estiver usando uma versão PHP 5, não precisará passar no parâmetro por referência.

Isso é o que você quer.

Corrigi um bug muito provável e simplifiquei a função de Bobthecow Resposta (que também é emprestado de Php.net) para este:

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];
    }
}

Ele retorna um número inteiro (geralmente na faixa sub-100), que é único para qualquer objeto (ver esta resposta Para detalhes sobre o que você está vendo).


PS eu uso esta implementação em um cenário do mundo real aqui

Gostaria Uniqid () trabalhar para sua tarefa?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top