Computer >> 컴퓨터 >  >> 프로그래밍 >> PHP

PHP 객체 반복 완벽 가이드: foreach 루프와 Iterator 인터페이스 활용법

개요

PHP 5부터는 객체가 가진 모든 접근 가능한(visible) 항목들을 순회(iteration)할 수 있습니다. 객체 반복은 foreach 루프나 Iterator 인터페이스를 통해 수행할 수 있으며, 이 외에도 같은 목적으로 사용할 수 있는 IteratorAggregate 인터페이스가 PHP에 존재합니다.

foreach 루프를 사용한 객체 반복

객체를 foreach 루프에 직접 넣으면 해당 객체의 속성(property)들이 순서대로 순회됩니다. 다만 접근 범위(visibility)에 따라 결과가 달라지는데, 클래스 외부에서 반복할 때는 public 속성만 노출되고, 클래스 내부 메서드에서 $this를 반복하면 private과 protected 속성까지 모두 접근할 수 있습니다.

예제

<?php
class myclass{
   private $var;
   protected $var1;
   public $x, $y, $z;
   public function __construct(){
      $this->var="private variable";
      $this->var1=TRUE;
      $this->x=100;
      $this->y=200;
      $this->z=300;
   }
   public function iterate(){
      foreach ($this as $key => $value) {
         print "$key => $value\n";
      }
   }
}
$obj = new myclass();
foreach($obj as $key => $value) {
   print "$key => $value\n";
}
echo "\n";
$obj->iterate();
?>

실행 결과

위 코드의 실행 결과는 다음과 같습니다.

x => 100
y => 200
z => 300

var => private variable
var1 => 1
x => 100
y => 200
z => 300

결과를 보면 첫 번째 foreach(클래스 외부)에서는 public 속성인 x, y, z만 출력된 반면, 두 번째 iterate() 메서드 내부의 foreach에서는 private 변수 var와 protected 변수 var1까지 모두 출력된 것을 확인할 수 있습니다.

Iterator 인터페이스 사용하기

Iterator 인터페이스는 아래와 같은 추상 메서드들을 정의하고 있으며, 이를 구현하는 클래스는 foreach 루프에서 객체가 어떻게 순회될지 직접 제어할 수 있습니다.

abstract public current ( void ) : mixed
abstract public key ( void ) : scalar
abstract public next ( void ) : void
abstract public rewind ( void ) : void
abstract public valid ( void ) : bool

각 메서드의 역할은 다음과 같습니다.

  • Iterator::current — 현재 요소를 반환합니다.
  • Iterator::key — 현재 요소의 키(key)를 반환합니다.
  • Iterator::next — 다음 요소로 커서를 이동합니다.
  • Iterator::rewind — 반복자를 첫 번째 요소로 되돌립니다.
  • Iterator::valid — 현재 위치가 유효한지 검사합니다.

다음 예제는 Iterator 인터페이스를 구현하여 객체 반복을 수행하는 방법을 보여줍니다.

예제

<?php
class myclass implements Iterator{
   private $arr = array('a','b','c');
   public function rewind(){
      echo "rewinding\n";
      reset($this->arr);
   }
   public function current(){
      $var = current($this->arr);
      echo "current: $var\n";
      return $var;
   }
   public function key() {
      $var = key($this->arr);
      echo "key: $var\n";
      return $var;
   }
   public function next() {
      $var = next($this->arr);
      echo "next: $var\n";
      return $var;
   }
   public function valid(){
      $key = key($this->arr);
      $var = ($key !== NULL && $key !== FALSE);
      echo "valid: $var\n";
      return $var;
   }
}
$obj = new myclass();
foreach ($obj as $k => $v) {
   print "$k: $v\n";
}
?>

실행 결과

위 코드를 실행하면 다음과 같은 결과가 출력됩니다.

rewinding
valid: 1
current: a
key: 0
0: a
next: b
valid: 1
current: b
key: 1
1: b
next: c
valid: 1
current: c
key: 2
2: c
next:
valid:

출력 과정을 살펴보면 foreach 루프가 시작될 때 먼저 rewind()가 호출되어 커서를 처음으로 되돌리고, 매 반복마다 valid()로 유효성을 검사한 뒤 current()key()로 값을 가져오고, 마지막으로 next()가 호출되어 다음 요소로 이동하는 것을 알 수 있습니다. 이처럼 Iterator 인터페이스를 구현하면 배열뿐 아니라 파일, 데이터베이스 결과 등 다양한 데이터 구조를 foreach로 자연스럽게 순회할 수 있습니다.