2010-02-19 8 views
5

मैं PHP 5+ में ऑब्जेक्ट इंस्टेंस के लिए अद्वितीय आईडी प्राप्त करने का प्रयास कर रहा हूं।spl_object_hash <5.2 (ऑब्जेक्ट इंस्टेंस के लिए अद्वितीय आईडी)

फ़ंक्शन, 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

आपको इसकी आवश्यकता क्यों है? हो सकता है कि वास्तविक समाधान आपके लिए आवश्यक न हो - जो आपके डिजाइन में कुछ समस्या का संकेत दे सकता है? –

+0

मैं एक सीएमएस पर काम कर रहा हूं और एक 'घटना' प्रणाली का निर्माण कर रहा हूं। निम्नलिखित कोड का उपयोग करके ईवेंट ट्रिगर किया जा सकता है: 'ट्रिगर (' evt_name ', नया इवेंट()) '। सीएमएस प्लगइन्स 'बाइंड (' evt_name ',' callback_function ') का उपयोग कर सिस्टम इवेंट्स को' बाध्य 'कर सकते हैं। मैं जो करना चाहता हूं वह उन दोनों कार्यों में एक और तर्क जोड़ता है जो घटना को स्वीकार करते हैं कि ईवेंट को बाध्य किया जाना चाहिए, लेकिन ईवेंट डेटा (ऑब्जेक्ट के बाहर) को स्टोर करने के लिए मुझे इसे एक अद्वितीय स्ट्रिंग में बदलने की आवश्यकता है सरणी कुंजी आपके क्या विचार हैं? – Rowan

+0

मेरे पास वास्तव में इसका कोई जवाब नहीं है, लेकिन मुझे और जानने में मदद मिल सकती है * (यहां तक ​​कि अगर मुझे ^^ नहीं) * - कोई फर्क नहीं पड़ता कि, हालांकि, मुझे कभी भी किसी भी प्रकार की " एक वस्तु के लिए अद्वितीय आईडी "; हो सकता है कि आप केवल ऑब्जेक्ट के संदर्भ को स्टोर कर सकें? –

उत्तर

4

मैंने कुछ त्वरित परीक्षण चलाए। मुझे सच में लगता है कि bind('evt_name', array($obj, 'callback_function')) का उपयोग करके आप अपने बाइंड() फ़ंक्शन में असली कॉलबैक संग्रहीत करना बेहतर होगा।

एक var_dump/निकालने और हैश आईडी कार्यान्वयन:

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

आप पूरी तरह नहीं बल्कि घटना बाइंडिंग के साथ संदर्भ भंडारण से spl_object_hash करना चाहते हैं, चाहते हैं, आप कुछ इस तरह देख रहे हैं एक अनुभवहीन संदर्भ कार्यान्वयन:

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 बदतर था rd, तो इसके बारे में चिंता करने लायक नहीं है।

एक दुकान संदर्भ वर्ग कार्यान्वयन द्वारा:

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 साथ खत्म। सारांश: कक्षा आधारित संदर्भ कार्यान्वयन एन/50 कक्षाओं के आसपास सबसे अच्छा प्रदर्शन करता है - यह सर्वोत्तम रूप से var_dump आधारित कार्यान्वयन के प्रदर्शन को 1/3 खींचने का प्रबंधन करता है, और आमतौर पर अधिक खराब होता है।

var_dump कार्यान्वयन सहनशील प्रतीत होता है, हालांकि आदर्श नहीं है। लेकिन अगर आप इन लुकअप में से बहुत कुछ नहीं कर रहे हैं, तो यह आपके लिए बाधा नहीं होगी। विशेष रूप से PHP < 5.2 बॉक्सन के लिए फ़ॉलबैक के रूप में।

+0

वाह धन्यवाद, मैंने दिया था जवाब पाने पर! मुझे आपके कोड को थोड़ी-थोड़ी पचाने की ज़रूरत है (बाद में, मैं काम पर हूं; पी) लेकिन मैं आपसे वापस आऊंगा। जो कोड मैं लिख रहा हूं वह एक वितरित सिस्टम का हिस्सा होगा, और मैं php5 <5.2 का समर्थन करना चाहता हूं लेकिन उम्मीद है कि अधिकांश समय 5.2 उपलब्ध होगा। – Rowan

0

uniqid() आपके काम के लिए काम करेगा?

1

मैंने एक बार वर्डप्रेस के लिए एक सहायक फ़ंक्शन लिखा है जो प्रति ऑब्जेक्ट एक अद्वितीय हैश प्रदान करता है, यह एक काउंटर के साथ काम करता है और यदि किसी ऑब्जेक्ट को असाइन किया गया है तो उसे सार्वजनिक वर्ग संपत्ति के रूप में हैश प्रति स्टोर करता है। निम्नलिखित उदाहरण दर्शाता यह:

/** 
* 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 संस्करण का उपयोग कर रहे हैं, तो आप संदर्भ द्वारा पैरामीटर पारित करने के लिए की जरूरत नहीं है।

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

यह (एक पूर्णांक रिटर्न आमतौर पर उप-100 में रेंज), जो किसी भी ऑब्जेक्ट के लिए अद्वितीय है (आप जो देख रहे हैं उसके विवरण के लिए this answer देखें)।


पीएस मैं इस कार्यान्वयन को वास्तविक दुनिया परिदृश्य में उपयोग करता हूं here