当前位置: 首页 > 后端技术 > PHP

在PHP中检测一个类是否可以通过foreach遍历

时间:2023-03-29 18:47:45 PHP

在PHP中,我们可以很容易的判断一个变量的类型,也可以很容易的判断一个数组的长度来判断这个数组是否可以被遍历。上课呢?我们怎么知道这个类是否可以通过foreach遍历呢?其实PHP已经为我们提供了现成的接口。类Obj1{public$v='V:Obj1';private$prv='prv:Obj1';}$obj1=newObj1();echo$obj1instanceof可遍历?'是':'否',PHP_EOL;//noclassObj2实现IteratorAggregate{public$v='V:Obj2';私人$prv='prv:Obj2';publicfunctiongetIterator(){returnnewArrayIterator(['v'=>$this->v,'prv'=>$this->prv,]);}}$obj2=newObj2();echo$obj2instanceofTraversable?'是':'否',PHP_EOL;//是的从上面的例子可以看出,每一个A\$obj1都不能被Traversable确定,所以无法遍历。第二个$obj2实现了iterator接口,这个对象可以通过Traversable来判断。在PHP手册中,Traversable接口就是用来检测一个类是否可以被foreach遍历的接口。该接口有几个特点:可以使用foreach遍历实现该接口的内置类,而无需实现IteratorAggregate或Iterator接口。这是一个内部引擎接口,无法在PHP脚本中实现。可以改用IteratorAggregate或Iterator接口。也就是说这个接口不需要我们手动去实现。我们只需要我们的类实现iterator相关的接口就可以通过这个接口的验证判断。如果我们单独实现这个接口,会报错,提示我们实现IteratorAggregate或者Iterator接口。//Fatalerror:ClassImplTraversablemustimplementinterfaceTraversableaspartofeitherIteratororIteratorAggregateinUnknownclassImplTraversableimplementsTraversable{}其实在之前的文章中,我们已经验证了对象是可以遍历的,不需要实现什么foreach可以遍历iterator接口。它将输出所有公共属性。//foreachforeach($obj1as$o1){echo$o1,PHP_EOL;}foreach($obj2as$o2){echo$o2,PHP_EOL;}//V:Obj1//V:Obj2//prv:Obj2也也就是说这个Traversable接口在实际使用中的作用并不明显。相信我们大多数人都没有用过这个接口来判断一个类是否可以遍历。但是从上面的例子我们可以看出,迭代器可以自定义我们需要输出的内容。相对而言,它比直接遍历对象更加灵活和可控。另外,如果是数组强制对象的情况,Traversable接口是无法判断的。$arr=[1,2,3,4];$obj3=(对象)$arr;echo$obj3instanceof可遍历?'是':'否',PHP_EOL;//noforeach($obj3as$o3){echo$o3,PHP_EOL;}事实上,数组本身就是一个天然的可迭代对象。这里虽然进行了类型强制转换,但是实际上将强制转换数组的对象看成默认实现迭代器的对象更合适。当然,这类接口更大的意义在于代码规范和强制检查。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202003/source/%E5%9C%A8PHP%E4%B8%AD%E6%A3%80%E6%B5%8B%E4%B8%80%E4%B8%AA%E7%B1%BB%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E8%A2%ABforeach%E9%81%8D%E5%8E%86.php参考文档:https://www.php.net/manual/zh/class.traversable.phphttps://www.php.net/manual/zh/control-structures.foreach.phphttps://www.php.net/manual/zh/language.oop5.iterations.php各媒体平台均可搜索【硬核项目经理】