# Data serialization of objects, want to iterate 'sealed' properties then dynamic ones

- Thread: https://externals.io/message/88415
- Original archive: https://news-web.php.net/php.internals/88415
- Started by j adams on 2015-09-22T18:16:46+00:00
- Messages: 11
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #88415 — j adams — 2015-09-22T18:16:46+00:00

URL: https://externals.io/message/88415#88415

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
1) 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.

2) What does zend_objects_get_address do? This reference looks very
different than the usual macro, e.g. Z_OBJ_HT_P

3) 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?

4) What does zend_unmangle_property_name do? Why is this function changed
to zend_unmangle_property_name_ex in 5.5 and later?

5) Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
prevent garbage collection?

6) An IS_INTERNED check is added in php 5.6 and yet the macro for
IS_INTERNED is zero. What's that all about?

7) 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.

---

## #88421 — Sean DuBois — 2015-09-22T19:32:33+00:00

URL: https://externals.io/message/88415#88421 · In reply to: #88415

> 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
> 1) 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.
>
> 2) What does zend_objects_get_address do? This reference looks very
> different than the usual macro, e.g. Z_OBJ_HT_P
>
> 3) 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?
>
> 4) What does zend_unmangle_property_name do? Why is this function changed
> to zend_unmangle_property_name_ex in 5.5 and later?
>
> 5) Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
> prevent garbage collection?
>
> 6) An IS_INTERNED check is added in php 5.6 and yet the macro for
> IS_INTERNED is zero. What's that all about?
>
> 7) 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,

1) '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!

3) Never used this, but it seems to be to confirm that a mangled prop name matches a
zend_property_info *

4) [2] Is some good reading on property name mangling

5) [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

---

## #88422 — j adams — 2015-09-22T19:53:07+00:00

URL: https://externals.io/message/88415#88422 · In reply to: #88421

Thank you, Sean. Still looking for a couple of answers...

> 1) '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?


> 3) 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.





> 
> > […]
> through
> > […]
> class
> > […]
> has
> > […]
> track.
> > […]
> out
> > […]
> Hey,
>
> 1) '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!
>
> 3) Never used this, but it seems to be to confirm that a mangled prop name
> matches a
> zend_property_info *
>
> 4) [2] Is some good reading on property name mangling
>
> 5) [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

---

## #88426 — francois@php.net — 2015-09-23T00:42:50+00:00

URL: https://externals.io/message/88415#88426 · In reply to: #88415

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

> 2) 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.

> 3) 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

>
> 4) 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

> 5) 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.

> 7) 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

---

## #88451 — j adams — 2015-09-23T19:48:33+00:00

URL: https://externals.io/message/88415#88451 · In reply to: #88426

> 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:
1) 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?
2) 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 :
>
> > […]
>
> Welcome to the jungle
>
> 2) What does zend_objects_get_address do? This reference looks very
> > […]
>
> 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.
>
> 3) Am I correct in understanding that zend_check_property_access simply
> > […]
>
> Yes
>
>
> > […]
>
> 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
>
> 5) Why do we call Z_ADDREF_PP(value) here? Is this reference counting to
> > […]
>
> This is reference counting. Incremented because a reference to the 'value'
> zval is added to the result array.
>
> 7) The code looks quite different between the different versions:
> > […]
>
> 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

---

## #88455 — Rowan Collins — 2015-09-23T20:33:15+00:00

URL: https://externals.io/message/88415#88455 · In reply to: #88451

> > […]
>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]

---

## #88457 — j adams — 2015-09-23T21:16:39+00:00

URL: https://externals.io/message/88415#88457 · In reply to: #88455

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:
1) 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?
2) 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?
3) 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 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]

---

## #88459 — Sean DuBois — 2015-09-23T22:35:56+00:00

URL: https://externals.io/message/88415#88459 · In reply to: #88457

> 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:
> 1) 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?
> 2) 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?
> 3) 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:
>
> > […]

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.


<code>
PHP_FUNCTION(print_properties)
{
    zval *obj_zval;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &obj_zval) == FAILURE) {
        RETURN_FALSE;
    }

    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)
</output

---

## #88481 — Rowan Collins — 2015-09-24T20:34:20+00:00

URL: https://externals.io/message/88415#88481 · In reply to: #88457

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

---

## #88485 — j adams — 2015-09-24T20:49:47+00:00

URL: https://externals.io/message/88415#88485 · In reply to: #88481

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:

1) 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?
2) 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?
3) 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:

> 
>
> > […]
>
> 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]

---

## #88487 — j adams — 2015-09-24T20:51:46+00:00

URL: https://externals.io/message/88415#88487 · In reply to: #88459

Thank 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.



> 
> > […]
> http://php.net/pcntl_fork
> > […]
> but
> > […]
> and
> > […]
> has
> > […]
> it
> > […]
> property's
> > […]
> E.g.,
> > […]
> will
> > […]
> &pos);
> > […]
> key_len-1
> > […]
> is
> > […]
> wrote:
> > […]
> There
> > […]
> pthreads
> > […]
> specific
> > […]
>
> 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.
>
>
> <code>
> PHP_FUNCTION(print_properties)
> {
>     zval *obj_zval;
>     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &obj_zval)
> == FAILURE) {
>         RETURN_FALSE;
>     }
>
>     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)
> </output
