5

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

それは主要なパフォーマンスバスターになる可能性があるようです!

誰かが何かを持っていますか?

4

4 に答える 4

4

いくつかの簡単なテストを実行しました。を使用して bind() 関数に実際のコールバックを格納する方がよいと本当に思いますbind('evt_name', array($obj, 'callback_function'))。イベントバインディングで参照を保存するのではなく、絶対に spl_object_hash ルートに行きたい場合は、次のようなものを見ています。

var_dump / 抽出およびハッシュ 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;
}

最終的には、次のような結果が得られます。要約: クラス ベースの参照実装は、n/50 クラス前後で最高のパフォーマンスを発揮します。最高の状態では、ベース実装のパフォーマンスの 1/3 を引き出すことができますが、var_dump通常ははるかに劣ります。

var_dump理想的ではありませんが、実装は許容できるようです。しかし、これらのルックアップをあまり行わなければ、ボトルネックにはなりません。特に PHP < 5.2 boxen のフォールバックとして。

于 2010-03-17T01:58:51.613 に答える
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 バージョンを使用している場合は、パラメーターを参照渡しする必要はありません。

于 2011-11-08T17:02:16.010 に答える
1

これはあなたが望むものです。

私は非常に可能性の高いバグを修正し、 bobthecow の回答(これも 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];
    }
}

任意のオブジェクトに固有の整数 (通常は 100 未満の範囲) を返します (表示される内容の詳細については、この回答を参照してください)。


PS私はこの実装を実際のシナリオで使用しています

于 2013-10-08T14:38:15.217 に答える
0

uniqid ()はあなたのタスクで機能しますか?

于 2010-02-23T03:48:35.830 に答える