php中如何使对象可以像数组一样进行foreach循环
2015-01-24信息快讯网
php中如何使对象可以像数组一样进行foreach循环呢?下面小编就详细的为大家介绍一下吧!需要的朋友可以 过来参考下
刚接触到题的时候,我也没有考虑到Iterator模式,试了几个一般想法,失败以后。。。。就直接去翻看了foreach的源码实现,期望发现foreach处理对象的时候是否有什么特殊性,可以做为突破口。
跟踪了半天以后发现了核心逻辑中的一个奇怪的switch:
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; }
从这个结构,我们可以看到,对象分为ZEND_ITER_OBJECT和ZEND_ITER_PLAIN_OBJECT, 这是什么意思呢?
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; } }
这就要讲到PHP的内置接口Iterator了,PHP5开始支持了接口, 并且内置了Iterator接口, 所以如果你定义了一个类,并实现了Iterator接口,那么你的这个类对象就是ZEND_ITER_OBJECT,否则就是ZEND_ITER_PLAIN_OBJECT.
对于ZEND_ITER_PLAIN_OBJECT的类,foreach会通过HASH_OF获取该对象的默认属性数组,然后对该数组进行foreach.
而对于ZEND_ITER_OBJECT的类对象,则会通过调用对象实现的Iterator接口相关函数来进行foreach,iterator接口:
Iterator extends Traversable { /* 方法 */ 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 ) }
所以, 对于这道笔试题, 可以作出如下的答案:
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; }
以上代码在我的php 5.3下运行正常。
php获取网卡的MAC地址支持WIN/LINUX系统
yii框架配置默认controller和action示例
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
smarty模板中使用get、post、request、cookies、session变量的方法
php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
PHP函数addslashes和mysql_real_escape_string的区别
CodeIgniter框架提示Disallowed Key Characters的解决办法
PHP5.5在windows安装使用memcached服务端的方法
用PHP和Shell写Hadoop的MapReduce程序
PHP header()函数常用方法总结
PHP扩展模块Pecl、Pear以及Perl的区别
PHP中的Memcache详解
PHP包含文件函数include、include_once、require、require_once区别总结
php警告Creating default object from empty value 问题的解决方法
PHP把网页保存为word文件的三种方法
PHP的password_hash()使用实例
php导出word文档与excel电子表格的简单示例代码
Drupal7 form表单二次开发要点与实例
PHP $_FILES中error返回值详解
浅析PHP原理之变量分离/引用(Variables Separation)
php接口与接口引用的深入解析
php number_format() 函数通过千位分组来格式化数字的实现代码
注意:php5.4删除了session_unregister函数
ueditor 1.2.6 使用方法说明
如何使用FireFox插件FirePHP调试PHP
请离开include_once和require_once
php/js获取客户端mac地址的实现代码
如何修改和添加Apache的默认站点目录
Apache实现Web Server负载均衡详解(不考虑Session版)
如何在Ubuntu下启动Apache的Rewrite功能
如何解决CI框架的Disallowed Key Characters错误提示
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
解决PHP mysql_query执行超时(Fatal error: Maximum execution time …)
Smarty foreach控制循环次数的实现详解
php修改NetBeans默认字体的大小
解析PHP跳出循环的方法以及continue、break、exit的区别介绍
mongo Table类文件 获取MongoCursor(游标)的实现方法分析
深入解析php中的foreach问题
浅析HTTP消息头网页缓存控制以及header常用指令介绍