Lo Zend Engine permette di operare anche con tipi di dato che verranno esposti come oggetti quando la nostra estensione verrà utilizzata. Il motore di PHP rappresenta internamente gli oggetti sfruttando le HashTable, allo stesso modo di come vengono salvati gli array (da PHP 5, con l'introduzione dello Zend Engine 2, gli oggetti hanno una rappresentazione differente in memoria, molto più efficiente; per la loro gestione possono comunque essere sfruttate le stesse API che vedremo in questo paragrafo). È possibile quindi sfruttare le stesse API messe a disposizione per gli array anche sugli oggetti. Viene fornito comunque un set di API atte ad aggiungere proprietà ad un oggetto; queste proprietà possono contenere qualsiasi tipo di dato ed in base a questo dovranno essere utilizzate delle funzioni differenti per manipolare l'oggetto.
Un breve esempio:
PHP_FUNCTION(test_object)
{
zval* array;
zval* obj2;
MAKE_STD_ZVAL(array);
MAKE_STD_ZVAL(obj2);
object_init(return_value);
object_init(obj2);
array_init(array);
add_property_long(return_value, "prop_long_1", 100);
add_property_long(return_value, "prop_long_2", 50);
add_property_long(return_value, "prop_long_3", 300);
add_property_bool(return_value, "prop_bool", 1);
add_property_double(return_value, "prop_double", 2.342534);
add_property_string(return_value, "prop_string", "Stringa di prova", 1);
add_property_long(obj2, "prop_long", 1);
add_property_double(obj2, "prop_double", 1.432043);
add_property_string(obj2, "prop_string", "Stringa oggetto figlio", 1);
add_property_zval(return_value, "prop_object", obj2);
add_next_index_long(array, 1);
add_next_index_string(array, "Stringa nell'array", 1);
add_property_zval(return_value, "prop_array", array);
}
Il codice precedente si occupa di creare una funzione che restituisce un oggetto al chiamante. Questo oggetto, se stampato con la funzione print_r, restituirà questa struttura:
stdClass Object
(
[prop_long_1] => 100
[prop_long_2] => 50
[prop_long_3] => 300
[prop_bool] => 1
[prop_double] => 2.342534
[prop_string] => Stringa di prova
[prop_object] => stdClass Object
(
[prop_long] => 1
[prop_double] => 1.432043
[prop_string] => Stringa oggetto figlio
)
[prop_array] => Array
(
[0] => 1
[1] => Stringa nell'array
)
)
Come possiamo notare dal codice utilizzato per definire la semplice funzione d'esempio, l'aggiunta di una proprietà ad un oggetto viene effettuata utilizzando le seguenti funzioni
add_property_long(zval*, char*, long);
add_property_bool(zval*, char*, int);
add_property_resource(zval*, char*, long);
add_property_string(zval*, char*, char*, int);
add_property_stringl(zval*, char*, char*, int, int);
add_property_zval(zval*, char*, zval*);
add_property_double(zval*, char*, double);
add_property_unset(zval*, char*);
Tutte le funzioni qui definite accettano come primo parametro un riferimento all'oggetto sul quale operare, e come secondo parametro una stringa rappresentante il nome della proprietà da aggiungere. I restanti parametri definiscono il valore da associare alla proprietà, e variano in base al tipo di dato. Seguono comunque le stesse regole utilizzate dalla funzioni add_next_index_* descritte nel paragrafo precedente.
Come già indicato, le operazioni di ricerca e di interrogazione dell'oggetto possono essere effettuate come se questi fosse un array. Vediamo un semplice esempio che modifica leggermente la funzione test_zend_hash definita precedentemente al fine di permetterle di operare su un oggetto:
PHP_FUNCTION(test_zend_hash_object)
{
zval* object;
int argc;
zval* obj_copy;
zval** item;
char buffer[512];
char* key;
int index;
MAKE_STD_ZVAL(obj_copy);
array_init(return_value),
object_init(obj_copy);
argc = ZEND_NUM_ARGS();
if(zend_parse_parameters(argc TSRMLS_CC, "o", &object) == FAILURE)
{
return;
}
int elem_count = zend_hash_num_elements(Z_OBJPROP(*object));
zend_hash_internal_pointer_reset(Z_OBJPROP(*object));
if(elem_count > 0)
{
do
{
zend_hash_get_current_data(Z_OBJPROP(*object), (void**)&item);
convert_to_string_ex(item);
if(zend_hash_get_current_key(Z_OBJPROP(*object), &key, &index, 0) == HASH_KEY_IS_STRING){
sprintf(buffer, "%s => %s", key, Z_STRVAL_PP(item));
}else
{
sprintf(buffer, "%d => %s", index, Z_STRVAL_PP(item));
}
add_next_index_string(obj_copy, buffer, 1);
}while(zend_hash_move_forward(Z_OBJPROP(*object)) == SUCCESS)
}
add_assoc_long(return_value, "elements count", elem_count);
add_assoc_zval(return_value, "informations", obj_copy);
}
Come possiamo notare sono state sfruttate le stesse API utilizzate nella funzione definita precedentemente, ma sono state fatte operare su oggetti anziché array.