spl_object_hash для php <5.2 (уникальный идентификатор для экземпляров объекта)
Вопрос
Я пытаюсь получить уникальные идентификаторы для экземпляров объектов в 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-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 ящика.
Другие советы
Однажды я написал вспомогательную функцию для 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];
}
}
Он возвращает целое число (обычно в диапазоне суб-100), которое уникально для любого объекта (см. этот ответ Для получения подробной информации о том, что вы видите).
PS Я использую эту реализацию в сценарии в реальном мире здесь
Бы uniqid () работать для своей задачи?