PHP的对象支持向数组一样使用foreach来遍历操作对象内部的数据,我们在遍历时就像遍历数组元素一样遍历对象的属性。但注意这个遍历方法受到访问修饰限制的影响。
例如,
定义如下的类:
复制代码
得到学生类 Student 的对象:然后遍历其属性:
复制代码
从输出结果上可以看到,我们的对象,就像一个集合类型数据数组一样,可以遍历其内部属性。
但是注意,这种遍历方式也是受访问修饰控制:
因此没有输出 $gender 和 $age这两个属性。
tip:大家可以在类的内部定义一个方法,然后在方法内部尝试遍历该对象,测试是否可以访问到私有的属性?
而且还要注意,遍历对象时,由于对象是引用传递,因此我们遍历的是对象的本身,而不是像遍历数组一样遍历的是数组的拷贝。这也意味着,在foreach遍历对象时,如果操作了对象属性,会影响到我们遍历的过程的:测试下看看:
复制代码
注意上面的结果,遍历的次数为3次,说明我们增加的属性也是需要遍历的。(想想数组来)
而且在foreach时,也支持值的引用传递,例如:
复制代码
注意输出结果中的tel属性,被改为了新值。
以上就是使用 foreach 的语句结构完成对对象属性的遍历。
但是上面的遍历,不能灵活控制我们需要遍历到的属性,上面的遍历就如同遍历数组一样,那么对象的处理数据的能力就被放弃了,与直接用数组的区别就不是很大了吧!
我们还可以使用定制性更强的遍历对象的方式:
类通过实现内置接口Iterator来实现迭代属性的目的:
php内置了一个接口 Iterator,我们可以通过实现这个接口,让我们的对象有能力自己定义对象的遍历过程:
先看看这个接口的结构吧:
复制代码
例如,假设我们有一个学些小组类,班级内有保存了很多学生:
复制代码
现在 我们的小组对象$team就有一个私有属性$stus,保存组内的所有学生信息:
此时我们如果需要遍历$team,遍历的结果为输出组内所有学生的姓名,此时仅仅使用foreach就不行了。就可以通过实现Iterator来实现:
复制代码
下面遍历这个$team:
复制代码
此时大家可以发现 按照我们自己需要的遍历方式完成了对象的遍历。
Iterator接口是内置接口,直接就可以使用,在php内有很多迭代器, 都是通过实现这个接口完成。
例如,
定义如下的类:
- //PHP代码:
- class Student {
- public $name;
- public $tel;
- private $age;
- private $gender;
- public function __construct($name, $tel, $age = 0, $gender = 'secrecy') {
- $this->name = $name;
- $this->tel = $tel;
- $this->age = $age;
- $this->gender = $gender;
- }
- }
- //php代码
- $stu1 = new Student('令狐冲', '15112345678', 26, 'male');
- foreach($stu1 as $property => $value) {
- echo $property, ':', $value;
- echo '
- ';
- }
- //输出结果为:
- //name:令狐冲
- //tel:15112345678
但是注意,这种遍历方式也是受访问修饰控制:
因此没有输出 $gender 和 $age这两个属性。
tip:大家可以在类的内部定义一个方法,然后在方法内部尝试遍历该对象,测试是否可以访问到私有的属性?
而且还要注意,遍历对象时,由于对象是引用传递,因此我们遍历的是对象的本身,而不是像遍历数组一样遍历的是数组的拷贝。这也意味着,在foreach遍历对象时,如果操作了对象属性,会影响到我们遍历的过程的:测试下看看:
- //PHP代码
- $stu1 = new Student('令狐冲', '15112345678', 26, 'male');
- foreach($stu1 as $property => $value) {
- //遍历时为$stu1对象增加了一个属性
- $stu1->subject[] = mt_rand(1,9);
- echo $property, ':'; print_r($value);
- echo '
- ';
- }
- //输出结果:
- //name:令狐冲
- //tel:15112345678
- //subject:Array
- (
- [0] => 3
- [1] => 8
- )
而且在foreach时,也支持值的引用传递,例如:
- //PHP代码
- foreach($stu1 as $property => &$value) {
- if($property == 'tel') {
- //修改$value
- $value = '13887654321';
- }
- }
- var_dump($stu1);
- //输出结果:
- //object(Student)#1 (4) {
- ["name"]=>
- string(9) "令狐冲"
- ["tel"]=>
- &string(11) "<b>13887654321"</b>
- ["age":"Student":private]=>
- int(26)
- ["gender":"Student":private]=>
- string(4) "male"
- }
以上就是使用 foreach 的语句结构完成对对象属性的遍历。
但是上面的遍历,不能灵活控制我们需要遍历到的属性,上面的遍历就如同遍历数组一样,那么对象的处理数据的能力就被放弃了,与直接用数组的区别就不是很大了吧!
我们还可以使用定制性更强的遍历对象的方式:
类通过实现内置接口Iterator来实现迭代属性的目的:
php内置了一个接口 Iterator,我们可以通过实现这个接口,让我们的对象有能力自己定义对象的遍历过程:
先看看这个接口的结构吧:
- //PHP代码
- Iterator extends Traversable {
- //获得当前遍历到的属性值的方法, return mixed
- public current ();
- //获得当前遍历到的属性名的方法, return scalar
- public key ();
- //向下移动需要遍历的位置 return void
- public next ();
- //重置移动的位置,return void
- public rewind ();
- //验证当前位置是否有效的方法,return bool
- public valid ();
- }
当一个类实现了Iterator接口后,在foreach遍历这个类实例化的对象时,会按照如下的执行流程执行以上的方法:
此时 我们就可以通过实现Iterator接口来按照我们的需求遍历我们的对象:

例如,假设我们有一个学些小组类,班级内有保存了很多学生:
- //PHP代码:
- class Team {
- private $stus;
- public function __construct() {
- $this->stus = array();
- }
- public function addStu($stu) {
- $this->stus[] = new Student($stu['name'], $stu['tel'], $stu['age'], $stu['gender']);
- }
- }
- //实例化对象,并添加5个学生
- $team = new Team();
- $team->addStu(array('name'=>'令狐冲', 'tel'=>'131123456789', 'age'=>24, 'gender'=>'male'));
- $team->addStu(array('name'=>'仪琳', 'tel'=>'131321231232', 'age'=>22, 'gender'=>'female'));
- $team->addStu(array('name'=>'岳不群', 'tel'=>'13156784321', 'age'=>37, 'gender'=>'male'));
- $team->addStu(array('name'=>'陆猴儿', 'tel'=>'13155667788', 'age'=>23, 'gender'=>'male'));
- $team->addStu(array('name'=>'岳灵珊', 'tel'=>'13112343121', 'age'=>21, 'gender'=>'female'));
此时我们如果需要遍历$team,遍历的结果为输出组内所有学生的姓名,此时仅仅使用foreach就不行了。就可以通过实现Iterator来实现:
- //php代码
- class Team implements Iterator{
- private $stus;
- public function __construct() {
- $this->stus = array();
- }
- public function addStu($stu) {
- $this->stus[] = new Student($stu['name'], $stu['tel'], $stu['age'], $stu['gender']);
- }
- public function rewind() {
- reset($this->stus);
- }
- public function valid() {
- return key($this->stus) !== null;
- }
- public function current() {
- $stu = current($this->stus);
- return $stu->name;//只需要当前对象的姓名
- }
- public function key() {
- return key($this->stus);
- }
- public function next() {
- next($this->stus);
- }
- }
- //PHP代码
- foreach($team as $name) {
- echo $name, '
- ';
- }
- //得到结果
- //令狐冲
- //仪琳
- //岳不群
- //陆猴儿
- //岳灵珊
Iterator接口是内置接口,直接就可以使用,在php内有很多迭代器, 都是通过实现这个接口完成。