I've learn a while ago on StackOverflow that we can get the "instance ID" of any resource, for instance:
var_dump(intval(curl_init())); // int(2) var_dump(intval(finfo_open())); // int(3) var_dump(intval(curl_init())); // int(4) var_dump(intval(finfo_open())); // int(5) var_dump(intval(curl_init())); // int(6)
I need something similar but applied to classes:
class foo { public function __construct() { ob_start(); var_dump($this); // object(foo)#INSTANCE_ID (0) { } echo preg_replace('~.+#(\d+).+~s', '$1', ob_get_clean()); } } $foo = new foo(); // 1 $foo2 = new foo(); // 2
The above works but I was hoping for a faster solution or, at least, one that didn't involve output buffers. Please note that this won't necessarily be used within the constructor or even inside the class itself!
spl_object_hash()
is not what I'm looking for because the two objects produce identical hashes
The question previously contained an incorrect example of spl_object_hash
output; ensuring that both objects exist at the same time produces hashes which are subtly different:
var_dump(spl_object_hash($foo)); // 0000000079e5f3b60000000042b31773 var_dump(spl_object_hash($foo2)); // 0000000079e5f3b50000000042b31773
Casting to int like resources doesn't seem to work for objects:
Notice: Object of class foo could not be converted to int.
Is there a quick way to grab the same output without using object properties?
Besides var_dump()
, I've discovered by trial and error that debug_zval_dump()
also outputs the object instance, unfortunately it also needs output buffering since it doesn't return the result.
spl_object_hash()
could help you out here. It
returns a unique identifier for the object
which is always the same for a given instance.
EDIT after OP comment:
You could implement such a behavior using a static class property, e.g:
class MyClass { private static $_initialized = false; public function __construct() { if (!self::$_initialized) { self::$_initialized = true; // your run-only-once code } } }
But actually this has nothing to with your original question.
Well, yes, with an extension.
Note that the handles used for objects that were, in the meantime, destroyed, can be reused.
Build with phpize && ./configure && make && make install
#ifndef PHP_EXTTEST_H # define PHP_EXTTEST_H # ifdef HAVE_CONFIG_H # include<config.h> # endif # include <php.h> extern zend_module_entry testext_module_entry; #define phpext_testext_ptr &testext_module_entry #endif
#include "testext.h" PHP_FUNCTION(get_object_id) { zval *obj; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) { return; } RETURN_LONG(Z_OBJ_HANDLE_P(obj)); } static zend_function_entry ext_functions[] = { PHP_FE(get_object_id, NULL) {NULL, NULL, NULL, 0, 0} }; zend_module_entry testext_module_entry = { STANDARD_MODULE_HEADER, "testext", ext_functions, /* Functions */ NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE(testext)
PHP_ARG_ENABLE(testext, [Whether to enable the "testext" extension], [ enable-testext Enable "testext" extension support]) if test $PHP_EXTTEST != "no"; then PHP_SUBST(EXTTEST_SHARED_LIBADD) PHP_NEW_EXTENSION(testext, testext.c, $ext_shared) fi
<?php $a = new stdclass(); $b = new stdclass(); var_dump(get_object_id($a)); var_dump(get_object_id($b));
int(1) int(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With