spl_object_hash لـ php <5.2 (معرف فريد لحالات الكائن)

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

  •  21-09-2019
  •  | 
  •  

سؤال

أحاول الحصول على معرفات فريدة لحالات الكائن في PHP 5+.

الوظيفة ، 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;
    }

يبدو أنه يمكن أن يكون أداءً رئيسياً في الأداء!

هل لدى أي شخص أي شيء؟

هل كانت مفيدة؟

المحلول

ركضت بضع اختبارات سريعة. أعتقد حقًا أنك ستكون أفضل حالًا في تخزين عمليات الاسترجاعات الحقيقية في وظيفة BIND () باستخدام bind('evt_name', array($obj, 'callback_function')). إذا كنت تريد تمامًا الذهاب إلى مسار spl_object_hash ، بدلاً من تخزين المراجع مع روابط الحدث ، فأنت تنظر إلى شيء من هذا القبيل:

تنفيذ معرف Var_dump / extract:

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-50x أسوأ من الوظيفة المرجعية المستندة إلى الفصل في جميع المجالات ، لذلك لا يستحق القلق.

مراجع المتجر عن طريق تنفيذ الفصل:

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.

نصائح أخرى

لقد كتبت ذات مرة وظيفة مساعد لـ 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 ، فلن تحتاج إلى تمرير المعلمة بالرجوع إليها.

هذا ما تريده.

لقد أصلحت خطأ محتمل للغاية وتبسيط الوظيفة من إجابة 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];
    }
}

إنه يعيد عددًا صحيحًا (عادة في نطاق Sub-100) ، وهو فريد من نوعه لأي كائن (انظر هذا الجواب للحصول على تفاصيل حول ما تراه).


ملاحظة: أستخدم هذا التنفيذ في سيناريو العالم الحقيقي هنا

سيكون uniqid () العمل من أجل مهمتك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top