<slide title="Object Factory Approach">

<blurb>
This gets quite a bit more complex than returning simple types, or even arrays. 
The first thing to do is to declare an extension-wide global class ptr along
with the methods available in this object you are creating.
</blurb>

<example fontsize="1.5em" type="c"><![CDATA[static zend_class_entry *my_class_entry_ptr;
static zend_function_entry php_my_class_functions[] = {
  PHP_FE(add,  NULL)
  PHP_FALIAS(del,           my_del,     NULL)
  PHP_FALIAS(list,          my_list,    NULL)
  {NULL, NULL, NULL}
};]]></example>

<blurb>
Next, in our module_init function we initialize and register our class definition.
</blurb>

<example fontsize="1.4em" type="c"><![CDATA[PHP_MINIT_FUNCTION(test) {
  zend_class_entry my_class_entry;

  INIT_CLASS_ENTRY(my_class_entry, "my_class", php_my_class_functions);
  my_class_entry_ptr = zend_register_internal_class(&my_class_entry TSRMLS_CC);
  return SUCCESS;
}]]></example>

<blurb>
And then we create our object factory function which will return an instantiated object.
</blurb>

<example fontsize="1.5em" type="c"><![CDATA[PHP_FUNCTION(my_object) {
  char *fn = NULL;
  int argc = ZEND_NUM_ARGS();
  int fn_len;
  long length;
  double price;
  zend_bool setting;

  if (zend_parse_parameters(argc TSRMLS_CC,
                            "sbld", &fn, &fn_len,
                            &setting, &length, &price) == FAILURE)
      return;

  object_init_ex(return_value, my_class_entry_ptr);

  add_property_stringl(return_value, "filename", fn, fn_len, 1);
  add_property_bool   (return_value, "toggle", setting ? 0 : 1);
  add_property_long   (return_value, "length", length);
  add_property_double (return_value, "price", price);
}]]></example>

<blurb>
From user space it would be called like this:
</blurb>

<example type="php"><![CDATA[<?php
  $obj = my_object();
  $obj->add(...);
?>]]></example>

<blurb>
If you want to have the more traditional class instantiation syntax and want
to have a constructor run for it.  eg.
</blurb>

<example type="php"><![CDATA[<?php
  $obj = new my_class();
?>]]></example>

<blurb>
Then create a constructor function:
</blurb>

<example fontsize="1.5em" type="c"><![CDATA[PHP_FUNCTION(my_class) {
  char *fn = NULL;
  int argc = ZEND_NUM_ARGS();
  int fn_len;
  long length;
  double price;
  zend_bool setting;

  if (zend_parse_parameters(argc TSRMLS_CC,
                            "sbld", &fn, &fn_len,
                            &setting, &length, &price) == FAILURE)
      return;

  add_property_stringl(this_ptr, "filename", fn, fn_len, 1);
  add_property_bool(this_ptr, "toggle", setting?0:1);
  add_property_long(this_ptr, "length", length);
  add_property_double(this_ptr, "price", price);
}]]></example>

<blurb>
Note the use of %this_ptr% here.
</blurb>

<blurb>
If you want to access properties from within one of the methods, you can do this:
</blurb>

<example fontsize="1.4em" type="c"><![CDATA[pval **tmp;
if(zend_hash_find(HASH_OF(this_ptr), "my_property", 11, (void **)&tmp)==SUCCESS) {
    convert_to_string_ex(tmp);
    php_printf("my_property is set to %s\n", Z_STRVAL_PP(tmp));
}]]></example>

</slide>
