마법 메서드 (Magic Methods): __call()
, __get()
, __set()
, __isset()
, __unset()
이건 다들 아는 기능이다. 메서드 호출, 멤버 접근 등을 저 메서드를 통해서 속일 수 있다. 예를 들어 PHP에서는 원래 메서드 오버로딩이 안되는데, 이걸 이용하면 오버로딩을 흉내낼 수도 있다.
SPL
원래 확장으로 만들어져 PHP 5.2부터는 기본으로 포함하게 된 SPL은 엄청난 축복이다. 이름을 보면 짐작할 수 있듯, C++ STL의 반복자 개념에 영향을 받아 만든 라이브러리다(나도 STL을 좋아한다). 이것을 잘 이용하면 유사 배열 객체를 만들 수 있다.
Traversable
이 인터페이스를 구현하면 foreach
문에 객체를 집어넣어서 배열처럼 돌릴 수 있다. Traversable
은 유사 인터페이스고, 실제로는 Iterator
혹은 IteratorAggregate
를 구현하면 된다. 전자는 반복자를 직접 구현하는 방식이고, 후자는 IteratorAggregate->getIterator()
메서드를 구현하여 반복자 객체를 위임하는 방식이다. 간단하게 배열처럼만 작동하는 객체를 의도한다면 후자가 좋고, 좀더 정교한 것을 원하면 직접 Iterator
를 구현하는 것이 좋다.
Countable
이 인터페이스를 구현하면 count()
함수에 넣었을 때 배열처럼 원소 개수를 반환하게 할 수 있다.
ArrayAccess
정말 유용하다. 이거 모르는 사람이 매우 많은데, 첨자 연산자([]
)를 오버로드할 수 있다. 단순히 값을 반환하는 것 말고도 해당 키가 존재하는지 확인하는 것(isset($obj[$key])
), 해당 키의 원소를 삭제하는 것(unset($obj[$key])
), 원소를 덧붙이는 것($obj[] = $value
), 해당 키의 원소 값을 수정하거나 추가하는 것($obj[$key] = $value
)이 가능하다.
아, 중요한 것 하나. 배열과 달리 ArrayAccess
를 구현한 객체는 키 값으로 스칼라 외에 배열이나 객체도 받을 수 있다.
가변 인자: func_get_args()
가변적인 갯수의 인자를 전달받을 때 사용한다. PHP는 함수 선언시에 명시한 시그너쳐에 맞지 않는 호출을 하면 오류를 내는데, 시그너쳐의 갯수보다 많은 인자를 받을 땐 오류를 내지 않는다. 이걸 이용하면 가변 인자를 받으면서 쉽게 오류 처리를 할 수 있다. 예를 들어 인자 갯수는 가변적이지만, 꼭 맨 처음의 인자 하나는 배열로 받아야 한다는 제약 사항이 있다면?
function get_array_and() {
$args = func_get_args();
if(!count($args) or !is_array($args[0]))
throw new InvalidArgumentException('First parameter must be array');
$array = $args[0];
위와 같이 할 수도 있지만, 아래처럼 하면 굳이 제약 사항을 검사하고 오류를 내는 코드를 직접 작성할 필요가 없다.
function get_array_and(array $array) {
$args = func_get_args();
주의할 것이 있다. 이 함수의 호출은 항상 맨 첫 문장, 대입식을 제외한 가장 바깥 표현식이어야 한다. 그렇지 않으면 의도한대로 작동하지 않는다. 이유는 나도 모른다. 하지만 이 버그는 PHP쪽에서는 유명하다.
eval()
전달된 PHP 코드 문자열을 해당 문맥에서 실행한다. eval('echo 1234;')
는 1234
를 출력한다. 그렇지만 표현식을 받지는 않는다.
$expr = '123 + 456';
$value = eval($expr);
위와 같이 하면 문장이 세미콜론(;
)으로 종결되지 않았다며 구문 오류가 난다. 표현식을 평가하고 싶다면 아래와 같이 써야 한다.
eval("\$value = ($expr);");
Reflection
PHP 5에서 추가된 리플렉션 기능을 사용하면 클래스의 멤버와 메서드 목록을 얻는다던가, 함수의 시그너쳐를 추적하는 등의 일을 할 수 있다. 인자에 타입 힌트가 있는지, 있다면 어떤 타입인지, 기본값이 있는지, 변수 이름이 무엇인지 등도 알 수 있다. 이런걸 이용하면 Python의 키워드 인자도 흉내낼 수 있을 것이다.
__toString()
이것도 마법 메서드의 하나인데, PHP 5에서 추가된 기능이다. 이 메서드를 정의한 객체는 echo
문으로 출력할 때 __toString()
이 반환한 문자열을 출력한다. Python의 __str__
속성과 비슷한 용도이다. 그런데 이게 PHP 5.2 이후로는 substr()
같이 문자열을 받는 함수에 전달될 때 자동으로 해당 문자열로 캐스팅도 된다. 물론 명시적으로 (string)
캐스팅 연산자를 쓰는 것도 잘 된다.
trigger_error()
웬만하면 예외를 던지는 것이 좋지만, PHP 에러를 내야할 필요가 있을 때 이걸 사용한다.
debug_backtrace()
이 함수를 사용하면 호출 스택을 추적하는 것이 가능하다. eval()
을 통하는 것과, include
, require
를 통한 것도 모두 추적할 수 있다. 대체 이 함수를 어디에 쓰겠느냐고 무심코 지나치면 안된다. 이 함수를 기억하고 있는 것만으로도, 종종 우연히 이 함수를 이용하여 좀더 우아한 DSEL을 달성할 때가 많다.
이 함수를 이용하는 대신 예외 객체를 생성하여 Exception->getTrace()
메서드로 받아내는 방법도 있다.
__FILE__
상수
__FILE__
상수의 값은 include
, require
등과 무관하게 해당 상수는 현재 코드가 위치한 실제 파일 경로이다. 예를 들어 require_once dirname(__FILE__).'/file.php'
과 같이 해당 소스 파일과 같은 위치에 있는 file.php
를 불러올 수 있다. (저렇게 하지 않으면 include
호출의 맨 위쪽에 있는 파일에 상대한 경로로 인클루드를 시도한다.)
operator 확장
PHP에 기본적으로 포함되지는 않았지만, 매우 유용한 확장이다. 연산자 재정의를 가능하게 해준다. C++의 Boost.Spirit 라이브러리 같은 것을 보면 연산자 재정의가 얼마나 언어의 표현력을 높여주는지 알 수 있다. 자세한 것은 내가 예전에 정리해둔 문서를 참고하시라.
출처: http://blog.dahlia.pe.kr/?s=lexical
'Dev > PHP' 카테고리의 다른 글
Excel Write 라이브러리 (0) | 2011.05.17 |
---|---|
PHP에서 지원하는 OOP의 형태 (0) | 2011.05.14 |
PHP CLI 예제 -> 명령행 옵션, argc argv 매개 변수 구하기 (0) | 2011.05.13 |
php5.3 에 ioncube 설치하기 (0) | 2011.05.13 |
컴파일 오류시 대처하기 (0) | 2011.05.13 |