next up previous contents
Next: Additional Examples Up: Usage Previous: Creating PHP Arrays   Contents

Navigating PHP Arrays

Exploring the contents of php_array objects in C++ requires the use of the php_iterator class. This class must be initialized with a specific array and has an additional optional boolean argument for type warnings much like the base php class.

php_iterator it(a);

Just initializing the iterator causes it to jump to the first element in the array with a call to go_to_start but it is also possible to start at the end by calling go_to_end. These functions can also be used to reset the position of the iterator at any point during execution.

The ++ and -- operators are used to navigate forward and backwards in the array a single element at a time and the done function is used to check for when the iterator has gone beyond the boundary of the php_array in any direction.

int count = 0;
while(!it.done()){
  count++;
  it++;
}

At the end of this loop the value of count should be the same as the return of a call to the size function of the it object.

Navigation wouldn't be very useful without the ability to get data back out of the array. However, since any entry could contain data of any type, there are functions for checking the type of key and type of data at each element. See Table 2 for a list of all supported and unsupported types.


Table 2: php_type values
Supported Unsupported
IS_LONG IS_NULL
IS_DOUBLE IS_OBJECT
IS_STRING IS_RESOURCE
IS_BOOL IS_CONSTANT
IS_ARRAY anything else

By using the type information the current position of the iterator, the data can be safely interpreted. NOTE: While the data at any array element could be any of the types listed in Table 2, keys can only be of type IS_STRING or IS_LONG. Consider the following code which prints out the key and value types and data for the last object in a iterator (doing nothing if the array is empty).

it.go_to_end();
if(!it.done()){
  switch(it.get_key_type()){
    case IS_LONG:
      printf("long %ld => ", it.get_key_long());
      break;
    case IS_STRING:
      printf("string %s => ", it.get_key_c_string());
      break;
    default:
      printf("??? %s => ", it.get_key_c_string());
      break;
    }

  switch(it.get_data_type()){
    case IS_LONG:
      printf("long %ld\n", it.get_data_long());
      break;
    case IS_STRING:
      printf("string %s\n", it.get_data_c_string());
      break;
    case IS_DOUBLE:
      printf("double %f\n", it.get_data_double());
      break;
    case IS_BOOL:
      printf("bool %s\n", it.get_data_c_string());
      break;
    case IS_ARRAY:
      printf("Array\n");
      {
        php_array suba = it.get_data_array();
        php_iterator subit(suba);
        // now iterate on the sub array
      }
      break;
    default:
      printf("??? %s\n", it.get_data_c_string());
      break;
  }
}

Note that in several cases PHP type conversion is used to get the data in a C-Style string even when it has a known type. For boolean values this makes sense for output since C++ would only print 0 or 1 if the data were printed as an integer. It also works with the data of unknown type since those must include a mechanism for printing as a string and will provide better insight into what data was provided such as a resource of or an object name. Of course, since it is only printing the data underneath it anyways this code could also just ignore the type of the data underlying entirely and always print the C style string data, but that wouldn't make a very informative example.

Observe also in the above example that in the case that the data is an array a new php_array object is created and initialized to that sub array. Unlike the majority of operations in PHPEmbed, the sub array suba is actually a reference to the same data that exists in the a object so mutating it by using the add or remove methods of php_array will affect both suba and a.


next up previous contents
Next: Additional Examples Up: Usage Previous: Creating PHP Arrays   Contents
Andrew Bosworth 2008-03-24