Just contact to the problem, I did not take into account the iterator mode, tried a few general ideas, after the failure .... Directly to look at the source of the implementation of foreach, expect to find a foreach processing object when there is any particularity, you can do as a breakthrough.
After half a day of tracking, a strange switch in the core logic was found:
Copy Code code as follows:
Switch (zend_iterator_unwrap (array, &iter tsrmls_cc)) {
Default
Case Zend_iter_invalid:
.....
Break
Case Zend_iter_plain_object: {
......
Break
Case Zend_iter_plain_array:
.....
Break
Case Zend_iter_object:
......
Break
}
From this structure, we can see that the objects are divided into Zend_iter_object and zend_iter_plain_object, what does this mean?
Copy Code code as follows:
Zend_api enum Zend_object_iterator_kind Zend_iterator_unwrap (
Zval *array_ptr, Zend_object_iterator **iter tsrmls_dc)
{
Switch (z_type_p (array_ptr)) {
Case Is_object:
if (z_obj_ht_p (array_ptr) = = &iterator_object_handlers) {
*iter = (Zend_object_iterator *) zend_object_store_get_object (array_ptr tsrmls_cc);
return zend_iter_object;
}
if (hash_of (array_ptr)) {
return zend_iter_plain_object;
}
return zend_iter_invalid;
Case Is_array:
if (hash_of (array_ptr)) {
return zend_iter_plain_array;
}
return zend_iter_invalid;
Default
return zend_iter_invalid;
}
}
This is about PHP's built-in interface iterator, PHP5 began to support the interface, and built the iterator interface, so if you define a class and implement the iterator interface, then your class object is Zend_iter_object, Otherwise it's zend_iter_plain_object.
For a Zend_iter_plain_object class, foreach obtains the object's default property array by Hash_of, and then foreach the array.
For Zend_iter_object class objects, the interface is foreach,iterator by calling the iterator interface-related functions implemented by the object:
Copy Code code as follows:
Iterator extends Traversable {
/* Method * *
Abstract public mixed current (void)
Abstract public scalar key (void)
Abstract public void next (void)
Abstract public void rewind (void)
Abstract public boolean valid (void)
}
Therefore, for this question, you can make the following answer:
Copy Code code as follows:
Class Sample implements Iterator
{
Private $_items = Array (1,2,3,4,5,6,7);
Public Function __construct () {
;//void
}
Public Function Rewind () {Reset ($this->_items);}
Public function current () {return current ($this->_items);}
Public Function key () {return key ($this->_items);}
Public function Next () {return next ($this->_items);}
Public Function valid () {return ($this->current ()!== false);
}
$sa = new sample ();
foreach ($sa as $key => $val) {
Print $key. "=>". $val;
}
The above code works fine under my PHP 5.3.