I'm working on a data serialization routine wherein I must iterate through
an object's properties while distinguishing between "sealed" properties
(i.e., those specified by class definitions) and "dynamic" properties"
(i.e., those assigned ad-hoc to some object that are not party of any class
definition).
I found the source of the php function get_object_vars()
:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
However, I am still pretty confused. PHP source is full of macros and has
basically no comments. Hoping for some tips to keep me on the right track.
I'm pretty sure I can get something kludgy working, but I want my code to
be orthodox and work well.
QUESTIONS
-
Sadly, this approach is unable to distinguish "sealed" properties from
dynamic ones. If anyone can refer me to some source (or outline a general
approach) which can first iterate sealed properties and then iterate only
dynamic ones, that would be extremely helpful. -
What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_P -
Am I correct in understanding that zend_check_property_access simply
checks if the property in question is availabe in the scope in which this
function call gets executed? Is this the canonical/orthodox way to make
this check? -
What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later? -
Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection? -
An IS_INTERNED check is added in php 5.6 and yet the macro for
IS_INTERNED is zero. What's that all about? -
The code looks quite different between the different versions:
5.3 - http://lxr.php.net/xref/PHP_5_3/Zend/zend_builtin_functions.c#950
5.5 - http://lxr.php.net/xref/PHP_5_5/Zend/zend_builtin_functions.c#982
5.6 - http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
From what I can tell there is at least one difference between 5.3 and 5.6
-- zend_unmangle_property_name_ex does not exist before 5.5. Can anyone
recommend how to make code that'll work in 5.3-5.6? Also, with 7 coming out
I'd like it work there too.
Any answers or assistance would be greatly appreciated.
I'm working on a data serialization routine wherein I must iterate through
an object's properties while distinguishing between "sealed" properties
(i.e., those specified by class definitions) and "dynamic" properties"
(i.e., those assigned ad-hoc to some object that are not party of any class
definition).I found the source of the php function
get_object_vars()
:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
However, I am still pretty confused. PHP source is full of macros and has
basically no comments. Hoping for some tips to keep me on the right track.
I'm pretty sure I can get something kludgy working, but I want my code to
be orthodox and work well.QUESTIONS
Sadly, this approach is unable to distinguish "sealed" properties from
dynamic ones. If anyone can refer me to some source (or outline a general
approach) which can first iterate sealed properties and then iterate only
dynamic ones, that would be extremely helpful.What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_PAm I correct in understanding that zend_check_property_access simply
checks if the property in question is availabe in the scope in which this
function call gets executed? Is this the canonical/orthodox way to make
this check?What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later?Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection?An IS_INTERNED check is added in php 5.6 and yet the macro for
IS_INTERNED is zero. What's that all about?The code looks quite different between the different versions:
5.3 - http://lxr.php.net/xref/PHP_5_3/Zend/zend_builtin_functions.c#950
5.5 - http://lxr.php.net/xref/PHP_5_5/Zend/zend_builtin_functions.c#982
5.6 - http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
From what I can tell there is at least one difference between 5.3 and 5.6
-- zend_unmangle_property_name_ex does not exist before 5.5. Can anyone
recommend how to make code that'll work in 5.3-5.6? Also, with 7 coming out
I'd like it work there too.Any answers or assistance would be greatly appreciated.
Hey,
- 'Default Properties' or properties stored on the class (not object)
can be found on the zend_class_entry[0], they are just accessed by offset [1]
This isn't a stable/public API, but good for a cool hack!
-
Never used this, but it seems to be to confirm that a mangled prop name matches a
zend_property_info * -
[2] Is some good reading on property name mangling
-
[3] Pretty much! Refcount is just to keep track of when a zval can be destroyed
Hopefully the more educated members of the list can follow up and fix my errors, but for now that
will at least get you going/able to dive deeper.
[0] http://lxr.php.net/xref/PHP_5_6/Zend/zend.h#488
[1] http://lxr.php.net/xref/PHP_5_6/ext/reflection/php_reflection.c#3410
[2] http://www.phpinternalsbook.com/classes_objects/internal_structures_and_implementation.html
[3] http://www.phpinternalsbook.com/zvals/memory_management.html
Thank you, Sean. Still looking for a couple of answers...
- 'Default Properties' or properties stored on the class (not object)
can be found on the zend_class_entry[0], they are just accessed by offset
[1]
This isn't a stable/public API, but good for a cool hack!
I'm afraid I don't follow. Could you elaborate? I've seen one way to get
'default properties' from a zend_class_entry object:
zendClassEntry->default_properties;
This gets us a list of default properties. I've also seen
zendClassEntry->properties_info;
Which, if I'm not mistaken, involves more elaborate parsing logic but also
tells you whether properties are accessible.
Seems like numerous ways to skin a cat. What is the orthodox approach here?
Also, what do you suggest to distinguish 'sealed' (i.e., default)
properties from dynamic ones? Is there some counterpart to
default_properties that returns non_default_properties -- i.e., just the
dynamic ones? Or should I just get all of the object's properties and check
each key to see if it's one of the default_properties by searching a
HashTable of these default properties?
- Never used this, but it seems to be to confirm that a mangled prop
name matches a zend_property_info *
Not sure I follow. We create a separate zobj of type zend_object using the
function:
zobj = zend_objects_get_address(obj TSRMLS_CC);
And then use zobj to check access:
if (zend_check_property_access(zobj, key, key_len-1 TSRMLS_CC) ==
SUCCESS) {
I find it odd that our native zval type would not encompass member
accessibility. I'm wondering if zend_object might be some kind of
historical add-on concept to expand very old PHP functionality or if
there's some reason for this distinct object type.
I'm working on a data serialization routine wherein I must iterate
through
an object's properties while distinguishing between "sealed" properties
(i.e., those specified by class definitions) and "dynamic" properties"
(i.e., those assigned ad-hoc to some object that are not party of any
class
definition).I found the source of the php function
get_object_vars()
:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
However, I am still pretty confused. PHP source is full of macros and
has
basically no comments. Hoping for some tips to keep me on the right
track.
I'm pretty sure I can get something kludgy working, but I want my code to
be orthodox and work well.QUESTIONS
Sadly, this approach is unable to distinguish "sealed" properties from
dynamic ones. If anyone can refer me to some source (or outline a general
approach) which can first iterate sealed properties and then iterate only
dynamic ones, that would be extremely helpful.What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_PAm I correct in understanding that zend_check_property_access simply
checks if the property in question is availabe in the scope in which this
function call gets executed? Is this the canonical/orthodox way to make
this check?What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later?Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection?An IS_INTERNED check is added in php 5.6 and yet the macro for
IS_INTERNED is zero. What's that all about?The code looks quite different between the different versions:
5.3 - http://lxr.php.net/xref/PHP_5_3/Zend/zend_builtin_functions.c#950
5.5 - http://lxr.php.net/xref/PHP_5_5/Zend/zend_builtin_functions.c#982
5.6 - http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
From what I can tell there is at least one difference between 5.3 and 5.6
-- zend_unmangle_property_name_ex does not exist before 5.5. Can anyone
recommend how to make code that'll work in 5.3-5.6? Also, with 7 coming
out
I'd like it work there too.Any answers or assistance would be greatly appreciated.
Hey,
- 'Default Properties' or properties stored on the class (not object)
can be found on the zend_class_entry[0], they are just accessed by offset
[1]This isn't a stable/public API, but good for a cool hack!
Never used this, but it seems to be to confirm that a mangled prop name
matches a
zend_property_info *[2] Is some good reading on property name mangling
[3] Pretty much! Refcount is just to keep track of when a zval can be
destroyedHopefully the more educated members of the list can follow up and fix my
errors, but for now that
will at least get you going/able to dive deeper.[0] http://lxr.php.net/xref/PHP_5_6/Zend/zend.h#488
[1] http://lxr.php.net/xref/PHP_5_6/ext/reflection/php_reflection.c#3410
[2]
http://www.phpinternalsbook.com/classes_objects/internal_structures_and_implementation.html
[3] http://www.phpinternalsbook.com/zvals/memory_management.html
Hi,
Hope this can help.
Le 22/09/2015 20:16, j adams a écrit :
I'm working on a data serialization routine wherein I must iterate through
an object's properties while distinguishing between "sealed" properties
(i.e., those specified by class definitions) and "dynamic" properties"
(i.e., those assigned ad-hoc to some object that are not party of any class
definition).I found the source of the php function
get_object_vars()
:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
However, I am still pretty confused. PHP source is full of macros and has
basically no comments.
Welcome to the jungle
- What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_P
PHP uses an object store. This allows handling objects by reference.
Every object instance is defined by a numeric handle (an offset in the
object store). Object zvals contain the object handle. The object
address is obtained through the object store. Look
http://lxr.php.net/xref/PHP_5_6/Zend/zend_objects_API.c#274
Z_OBJ_HT() is used to call an object's handlers. This information is
also present in the zend_object but, for a better performance AFAIK,
also made available in the zval struct.
- Am I correct in understanding that zend_check_property_access simply
checks if the property in question is availabe in the scope in which this
function call gets executed?
Yes
- What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later?
Properties are stored using 'mangled' names. The format of a mangled
name is '<NULL><class name><NULL><property name><NULL>', where <NULL> is
a null byte. Class name and property name are 'decoded' by
zend_unmangle_property_name(). Look
http://lxr.php.net/xref/PHP_5_6/Zend/zend_compile.c#5373
- Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection?
This is reference counting. Incremented because a reference to the
'value' zval is added to the result array.
- The code looks quite different between the different versions:
5.3 - http://lxr.php.net/xref/PHP_5_3/Zend/zend_builtin_functions.c#950
5.5 - http://lxr.php.net/xref/PHP_5_5/Zend/zend_builtin_functions.c#982
5.6 - http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
From what I can tell there is at least one difference between 5.3 and 5.6
-- zend_unmangle_property_name_ex does not exist before 5.5. Can anyone
recommend how to make code that'll work in 5.3-5.6? Also, with 7 coming out
I'd like it work there too.
Making code working with 5.3-5.6 is quite easy with a pair of ifdef.
Unfortunately, writing code to compile on PHP 5 & 7 is complex. It seems
most people porting extensions to PHP 7 finally duplicated most, if not
all of their code.
Regards
François
Welcome to the jungle
Thank you, Francois. Malheuresement, plus de questions...
PHP uses an object store.
Am I correct in understanding that the object store is a global data
structure? Wouldn't this tend to discourage any attempts at
multithreading/multiprocessing within one's PHP script--unless the object
store is protected by a lock...
It would appear that for some zend_object ,zobj, that if the object has any
dynamic properties at all then zobj->properties will be defined a HashTable
that contains not just the dynamic properties, but all the default object
properties (i.e., those defined explicitly by the class) as well. At least
that appears to be the case from my code below.
Is there not any way to first iterate through the default properties and
then iterate through only the dynamic properties ? If so, please
advise? If not, it sounds like I must iterate through all properties and
check each property's key to see if it's included among the default
properties.
Also -- and this is very important:
-
Will this code ALWAYS return the properties in the same sequence? E.g.,
if I am iterating through N objects of type MyClass, will each instance
iterate the properties in the same order? -
Will this code ALWAYS iterate over default properties (i.e., "sealed"
properties, those explicitly defined by class definitinos) FIRST and then
iterate any dynamically assigned properties?
These questions are very important for my serialization algorithm.zobj = zend_objects_get_address(*val TSRMLS_CC); if (!zobj->properties) { php_printf("***No dynamic properties!\n"); } else { php_printf("***we got dynamic properties...sadly, this will
also iterate through default properties too\n");
zend_hash_internal_pointer_reset_ex(zobj->properties, &pos);
while (zend_hash_get_current_data_ex(zobj->properties,
(void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(zobj->properties,
&key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (zend_check_property_access(zobj, key, key_len-1
TSRMLS_CC) == SUCCESS) {
zend_unmangle_property_name(key, key_len - 1,
&class_name, &prop_name);
php_printf("dynamic property is %s, key_len is
%d\n", prop_name, key_len);
}
}
zend_hash_move_forward_ex(zobj->properties, &pos);
}
}
On Tue, Sep 22, 2015 at 5:42 PM, François Laupretre francois@php.net
wrote:
Hi,
Hope this can help.
Le 22/09/2015 20:16, j adams a écrit :
I'm working on a data serialization routine wherein I must iterate through
an object's properties while distinguishing between "sealed" properties
(i.e., those specified by class definitions) and "dynamic" properties"
(i.e., those assigned ad-hoc to some object that are not party of any
class
definition).I found the source of the php function
get_object_vars()
:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
However, I am still pretty confused. PHP source is full of macros and
has
basically no comments.Welcome to the jungle
- What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_P
PHP uses an object store. This allows handling objects by reference. Every
object instance is defined by a numeric handle (an offset in the object
store). Object zvals contain the object handle. The object address is
obtained through the object store. Look
http://lxr.php.net/xref/PHP_5_6/Zend/zend_objects_API.c#274Z_OBJ_HT() is used to call an object's handlers. This information is also
present in the zend_object but, for a better performance AFAIK, also made
available in the zval struct.
- Am I correct in understanding that zend_check_property_access simply
checks if the property in question is availabe in the scope in which this
function call gets executed?Yes
- What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later?Properties are stored using 'mangled' names. The format of a mangled name
is '<NULL><class name><NULL><property name><NULL>', where <NULL> is a null
byte. Class name and property name are 'decoded' by
zend_unmangle_property_name(). Look
http://lxr.php.net/xref/PHP_5_6/Zend/zend_compile.c#5373
- Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection?
This is reference counting. Incremented because a reference to the 'value'
zval is added to the result array.
- The code looks quite different between the different versions:
5.3 - http://lxr.php.net/xref/PHP_5_3/Zend/zend_builtin_functions.c#950
5.5 - http://lxr.php.net/xref/PHP_5_5/Zend/zend_builtin_functions.c#982
5.6 - http://lxr.php.net/xref/PHP_5_6/Zend/zend_builtin_functions.c#985
From what I can tell there is at least one difference between 5.3 and 5.6
-- zend_unmangle_property_name_ex does not exist before 5.5. Can anyone
recommend how to make code that'll work in 5.3-5.6? Also, with 7 coming
out
I'd like it work there too.Making code working with 5.3-5.6 is quite easy with a pair of ifdef.
Unfortunately, writing code to compile on PHP 5 & 7 is complex. It seems
most people porting extensions to PHP 7 finally duplicated most, if not all
of their code.Regards
François
PHP uses an object store.
Am I correct in understanding that the object store is a global data
structure? Wouldn't this tend to discourage any attempts at
multithreading/multiprocessing within one's PHP script--unless the
object
store is protected by a lock...
PHP is inherently single-threaded as far as the user is concerned. There are many things which would break if you changed that.
The only way I know of to write multi-threaded PHP is using the pthreads extension, which comes with some rather large caveats, and uses specific objects to communicate between threads.
Regards,
Rowan Collins
[IMSoP]
Not my intention to be combative, but what about http://php.net/pcntl_fork
? I've used that before in a robust distributed application that runs
without any intervention for months. It's my understanding that PHP is
thread safe, but not itself multithreaded. I believe there are some
extensions which aren't thread safe. Also correct me if I'm wrong but
Apache 2 should be run in it's prefork mode when using PHP.
Also, any thoughts on my other questions? Sorry if I'm pressing my luck but
they are far more pressing for me currently:
- Is there not any way to first iterate through the default properties and
then iterate through only the dynamic properties ?
zend_object->properties appears to contain ALL properties if the object has
a single dynamically-assigned property. If so, please advise? If not, it
sounds like I must iterate through all properties and check each property's
key to see if it's included among the default properties. Please confirm? - Will this code ALWAYS return the properties in the same sequence? E.g.,
if I am iterating through N objects of type MyClass, will each instance
iterate the properties in the same order? - Will this code ALWAYS iterate over default properties (i.e., "sealed"
properties, those explicitly defined by class definitinos) FIRST and then
iterate any dynamically assigned properties?
These questions are very important for my serialization algorithm.
CODE:
zobj = zend_objects_get_address(*val TSRMLS_CC);
if (!zobj->properties) {
php_printf("***No dynamic properties!\n");
} else {
php_printf("***we got dynamic properties...sadly, this will
also iterate through default properties too\n");
zend_hash_internal_pointer_reset_ex(zobj->properties, &pos);
while (zend_hash_get_current_data_ex(zobj->properties,
(void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(zobj->properties,
&key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (zend_check_property_access(zobj, key, key_len-1
TSRMLS_CC) == SUCCESS) {
zend_unmangle_property_name(key, key_len - 1,
&class_name, &prop_name);
php_printf("dynamic property is %s, key_len is
%d\n", prop_name, key_len);
}
}
zend_hash_move_forward_ex(zobj->properties, &pos);
}
}
On Wed, Sep 23, 2015 at 1:33 PM, Rowan Collins rowan.collins@gmail.com
wrote:
PHP uses an object store.
Am I correct in understanding that the object store is a global data
structure? Wouldn't this tend to discourage any attempts at
multithreading/multiprocessing within one's PHP script--unless the
object
store is protected by a lock...PHP is inherently single-threaded as far as the user is concerned. There
are many things which would break if you changed that.The only way I know of to write multi-threaded PHP is using the pthreads
extension, which comes with some rather large caveats, and uses specific
objects to communicate between threads.Regards,
Rowan Collins
[IMSoP]
Not my intention to be combative, but what about http://php.net/pcntl_fork
? I've used that before in a robust distributed application that runs
without any intervention for months. It's my understanding that PHP is
thread safe, but not itself multithreaded. I believe there are some
extensions which aren't thread safe. Also correct me if I'm wrong but
Apache 2 should be run in it's prefork mode when using PHP.Also, any thoughts on my other questions? Sorry if I'm pressing my luck but
they are far more pressing for me currently:
- Is there not any way to first iterate through the default properties and
then iterate through only the dynamic properties ?
zend_object->properties appears to contain ALL properties if the object has
a single dynamically-assigned property. If so, please advise? If not, it
sounds like I must iterate through all properties and check each property's
key to see if it's included among the default properties. Please confirm?- Will this code ALWAYS return the properties in the same sequence? E.g.,
if I am iterating through N objects of type MyClass, will each instance
iterate the properties in the same order?- Will this code ALWAYS iterate over default properties (i.e., "sealed"
properties, those explicitly defined by class definitinos) FIRST and then
iterate any dynamically assigned properties?
These questions are very important for my serialization algorithm.CODE:
zobj = zend_objects_get_address(*val TSRMLS_CC); if (!zobj->properties) { php_printf("***No dynamic properties!\n"); } else { php_printf("***we got dynamic properties...sadly, this will
also iterate through default properties too\n");
zend_hash_internal_pointer_reset_ex(zobj->properties, &pos);
while (zend_hash_get_current_data_ex(zobj->properties,
(void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(zobj->properties,
&key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (zend_check_property_access(zobj, key, key_len-1
TSRMLS_CC) == SUCCESS) {zend_unmangle_property_name(key, key_len - 1,
&class_name, &prop_name);
php_printf("dynamic property is %s, key_len is
%d\n", prop_name, key_len);
}
}
zend_hash_move_forward_ex(zobj->properties, &pos);
}
}On Wed, Sep 23, 2015 at 1:33 PM, Rowan Collins rowan.collins@gmail.com
wrote:PHP uses an object store.
Am I correct in understanding that the object store is a global data
structure? Wouldn't this tend to discourage any attempts at
multithreading/multiprocessing within one's PHP script--unless the
object
store is protected by a lock...PHP is inherently single-threaded as far as the user is concerned. There
are many things which would break if you changed that.The only way I know of to write multi-threaded PHP is using the pthreads
extension, which comes with some rather large caveats, and uses specific
objects to communicate between threads.Regards,
Rowan Collins
[IMSoP]--
In PHP7 this is how you can all the default properties (defined on the
class) you will have to adjust. This is breaking public APIs, but just
to illustrate how to get you closer.
You should then be able to determine if a property is defined on the class or object this way.
Just build some sort of lookup table via looping over them below.
zend_class_entry *ce = Z_OBJCE_P(obj_zval);
zend_property_info *prop;
zval *val;
int prop_count = 0;
const char *class_name, *prop_name;
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
val = &ce->default_properties_table[prop_count];
zend_unmangle_property_name(prop->name, &class_name, &prop_name);
prop_count++;
fprintf(stdout, "%s \n", prop_name);
php_var_dump(val, 1);
} ZEND_HASH_FOREACH_END();
</code>
Which will give you the following
<script> <?php class SeanTest { public $defaultPropertyPublic = 'publicDefaultProp'; private $defaultPropertyPrivate = 'privateDefaultProp'; protected $defaultPropertyProtected = 12; } $foo = new SeanTest(); $foo->runtimeProperty = 3; print_properties($foo); </script> <output> defaultPropertyPublic string(17) "publicDefaultProp" defaultPropertyPrivate string(18) "privateDefaultProp" defaultPropertyProtected Int(12) </outputThank you for this, Sean! I'm making headway for php 5.5/5.6. This should
come in handy when/if I get around to PHP 7.
Not my intention to be combative, but what about
http://php.net/pcntl_fork
? I've used that before in a robust distributed application that runs
without any intervention for months. It's my understanding that PHP is
thread safe, but not itself multithreaded. I believe there are some
extensions which aren't thread safe. Also correct me if I'm wrong but
Apache 2 should be run in it's prefork mode when using PHP.Also, any thoughts on my other questions? Sorry if I'm pressing my luck
but
they are far more pressing for me currently:
- Is there not any way to first iterate through the default properties
and
then iterate through only the dynamic properties ?
zend_object->properties appears to contain ALL properties if the object
has
a single dynamically-assigned property. If so, please advise? If not,
it
sounds like I must iterate through all properties and check each
property's
key to see if it's included among the default properties. Please confirm?- Will this code ALWAYS return the properties in the same sequence?
E.g.,
if I am iterating through N objects of type MyClass, will each instance
iterate the properties in the same order?- Will this code ALWAYS iterate over default properties (i.e., "sealed"
properties, those explicitly defined by class definitinos) FIRST and then
iterate any dynamically assigned properties?
These questions are very important for my serialization algorithm.CODE:
zobj = zend_objects_get_address(*val TSRMLS_CC); if (!zobj->properties) { php_printf("***No dynamic properties!\n"); } else { php_printf("***we got dynamic properties...sadly, this
will
also iterate through default properties too\n");
zend_hash_internal_pointer_reset_ex(zobj->properties,
&pos);
while (zend_hash_get_current_data_ex(zobj->properties,
(void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(zobj->properties,
&key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (zend_check_property_access(zobj, key,
key_len-1
TSRMLS_CC) == SUCCESS) {zend_unmangle_property_name(key, key_len - 1,
&class_name, &prop_name);
php_printf("dynamic property is %s, key_len
is
%d\n", prop_name, key_len);
}
}
zend_hash_move_forward_ex(zobj->properties, &pos);
}
}On Wed, Sep 23, 2015 at 1:33 PM, Rowan Collins rowan.collins@gmail.com
wrote:On 23 September 2015 20:48:33 BST, j adams zardozrocks@gmail.com
wrote:PHP uses an object store.
Am I correct in understanding that the object store is a global data
structure? Wouldn't this tend to discourage any attempts at
multithreading/multiprocessing within one's PHP script--unless the
object
store is protected by a lock...PHP is inherently single-threaded as far as the user is concerned.
There
are many things which would break if you changed that.The only way I know of to write multi-threaded PHP is using the
pthreads
extension, which comes with some rather large caveats, and uses
specific
objects to communicate between threads.Regards,
Rowan Collins
[IMSoP]--
In PHP7 this is how you can all the default properties (defined on the
class) you will have to adjust. This is breaking public APIs, but just
to illustrate how to get you closer.You should then be able to determine if a property is defined on the class
<code> PHP_FUNCTION(print_properties) { zval *obj_zval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &obj_zval) == FAILURE) { RETURN_FALSE; }
or object this way.
Just build some sort of lookup table via looping over them below.</code>zend_class_entry *ce = Z_OBJCE_P(obj_zval); zend_property_info *prop; zval *val; int prop_count = 0; const char *class_name, *prop_name; ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) { val = &ce->default_properties_table[prop_count]; zend_unmangle_property_name(prop->name, &class_name, &prop_name); prop_count++; fprintf(stdout, "%s \n", prop_name); php_var_dump(val, 1); } ZEND_HASH_FOREACH_END();
Which will give you the following
<script> <?php class SeanTest { public $defaultPropertyPublic = 'publicDefaultProp'; private $defaultPropertyPrivate = 'privateDefaultProp'; protected $defaultPropertyProtected = 12; } $foo = new SeanTest(); $foo->runtimeProperty = 3; print_properties($foo); </script> <output> defaultPropertyPublic string(17) "publicDefaultProp" defaultPropertyPrivate string(18) "privateDefaultProp" defaultPropertyProtected Int(12) </output
Not my intention to be combative, but what abouthttp://php.net/pcntl_fork
? I've used that before in a robust distributed application that runs
without any intervention for months. It's my understanding that PHP is
thread safe, but not itself multithreaded. I believe there are some
extensions which aren't thread safe. Also correct me if I'm wrong but
Apache 2 should be run in it's prefork mode when using PHP.
Process forking is very different from multi-threading. Your original
question was whether a central object store could cause problems, but as
I understand it a forked process shares no memory with its parent, so
that's not a problem.
The internal thread safety mode ("ZTS") does indeed have to duplicate
the object store for each thread, though. The general idea (in Zend
Engine 2 / PHP 5, at least) being that a structure is passed around via
TSRM* macros and ultimately used by the EG macro in place of a true
global: http://lxr.php.net/xref/PHP_5_6/Zend/zend_globals_macros.h#45
All of this is something of an aside from what you really wanted to
know, though. :)
Regards,
--
Rowan Collins
[IMSoP]
Thanks, Rowan, for the clarification! And no, this is not my primary
question. At the risk of irritating everyone, here are the questions I need
answered:
- Is there not any way to first iterate through the default properties and
then iterate through only the dynamic properties ?
zend_object->properties appears to contain ALL properties if the object has
a single dynamically-assigned property. If so, please advise? If not,
please confirm? - Will the code below ALWAYS return the properties in the same sequence?
E.g., if I am iterating through N objects of type MyClass, will each
instance iterate the properties in the same order? - Will the code below ALWAYS iterate over default properties (i.e.,
"sealed" properties, those explicitly defined by class definitinos) FIRST
and then iterate any dynamically assigned properties?
CODE:
zobj = zend_objects_get_address(*val TSRMLS_CC);
if (!zobj->properties) {
php_printf("***No dynamic properties!\n");
} else {
php_printf("***we got dynamic properties...sadly, this will
also iterate through default properties too\n");
zend_hash_internal_pointer_reset_ex(zobj->properties, &pos);
while (zend_hash_get_current_data_ex(zobj->properties,
(void **) &value, &pos) == SUCCESS) {
if (zend_hash_get_current_key_ex(zobj->properties,
&key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
if (zend_check_property_access(zobj, key, key_len-1
TSRMLS_CC) == SUCCESS) {
zend_unmangle_property_name(key, key_len - 1,
&class_name, &prop_name);
php_printf("dynamic property is %s, key_len is
%d\n", prop_name, key_len);
}
}
zend_hash_move_forward_ex(zobj->properties, &pos);
}
}
On Thu, Sep 24, 2015 at 1:34 PM, Rowan Collins rowan.collins@gmail.com
wrote:
Not my intention to be combative, but what abouthttp://php.net/pcntl_fork
? I've used that before in a robust distributed application that runs
without any intervention for months. It's my understanding that PHP is
thread safe, but not itself multithreaded. I believe there are some
extensions which aren't thread safe. Also correct me if I'm wrong but
Apache 2 should be run in it's prefork mode when using PHP.Process forking is very different from multi-threading. Your original
question was whether a central object store could cause problems, but as I
understand it a forked process shares no memory with its parent, so that's
not a problem.The internal thread safety mode ("ZTS") does indeed have to duplicate the
object store for each thread, though. The general idea (in Zend Engine 2 /
PHP 5, at least) being that a structure is passed around via TSRM* macros
and ultimately used by the EG macro in place of a true global:
http://lxr.php.net/xref/PHP_5_6/Zend/zend_globals_macros.h#45All of this is something of an aside from what you really wanted to know,
though. :)Regards,
--
Rowan Collins
[IMSoP]