활용하면 좋은 PHP 매직 메소드

서론

PHP에서 매직 메소드는 특정 상황에서 자동으로 호출되는 메소드로, 이름은 항상 두 개의 밑줄로 시작된다(__). 이들은 객체 지향 프로그래밍에서 다양한 상황에 대응하거나, 코드를 보다 유연하고 읽기 쉽게 만드는 데 도움을 준다. 본 포스팅에서는 PHP에서 제공되는 매직 메소드를 예시를 들며 소개한다. 

 

 

__construct()

객체가 생성될 때 자동으로 호출되는 생성자 메소드로 주로 초기화 작업에 주로 사용된다.

class Person {
    public $name;
    public $age;

    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
}

$person = new Person("John", 30); // __construct를 호출.

 

 

 

__destruct()

객체가 소멸될 때 자동으로 호출되는 소멸자 메소드로 주로 리소스 정리에 사용된다.

class FileHandler {
    protected $file;

    public function __construct($filename) {
        $this->file = fopen($filename, 'w');
    }

    public function __destruct() {
        fclose($this->file); // 파일을 닫는다.
    }
}

 

 

 

__call()

객체에 없거나 객체에서 접근할 수 없는 메소드를 호출하려고 할 때 실행된다.

class Test {
    public function __call($name, $arguments) {
        echo "메소드 '$name'를 호출. 인자: " . implode(', ', $arguments);
    }

    private function test1($name) {
        echo "프라이빗 메소드 test1 호출";
    }
}

$obj = new Test();
$obj->isNotExistingMethod('mingyu', 'kim','test',1); // 메소드 'isNotExistingMethod'를 호출. 인자: mingyu, kim, test, 1
$obj->test1('test'); // 메소드 'test1'를 호출. 인자: test

 

 

__get() & __set()

객체에서 접근할 수 없는 속성을 읽거나 쓰려고 할 때 실행된다.

class Test {
    private array $data = [];

    public function __get(string $key) {
        return $this->data[$key] ?? null;
    }

    public function __set($key, $value) {
        $this->data[$key] = $value;
    }
}

$obj = new Test();
$obj->a = "key : a , value A"; // __set이 호출.
$obj->b = "key : b , value BBBB"; // __set이 호출.
echo $obj->a; // __get이 호출. key : a , value A
echo $obj->b; // __get이 호출. key : b , value BBBB

 

 

__toString()

객체를 문자열로 표현하려 할 때 호출된다. 객체를 "echo" 혹은 "print" 등으로 사용하여 확인할 때 유용하다.

class Test {

    private array $data = [];

    public function __get(string $key) {
        return $this->data[$key] ?? null;
    }

    public function __set($key, $value) {
        $this->data[$key] = $value;
    }

    public function __toString(): string
    {
        return implode(",",$this->data) ?? "";
    }
}

$obj = new Test();
$obj->a = "key : a , value A";
$obj->b = "key : b , value BBBB";

echo $obj; // key : a , value A,key : b , value BBBB

 

 

PHP 8.1부터 도입된 __serialize, __unserialize 매직 메소드

위에서 소개한 메직 메소드들은 PHP 5부터 사용 가능했었다. 하지만 PHP 7 이상으로 업데이트 되면서 Zend Engine 3.0을 도입되어 매직 메소드를 포함한 모든 함수 및 메소드들의 호출이 빠르게 처리되며 성능 향상이 되었고, EgnineException과 ParseException을 포함한 새로운 예외 계층이 도입되며 __toString() 메소드에서 예외를 발생시킬 때 유용하게 작용되었다.

 

그리고 PHP 8.1 에서 객체의 직렬화와 역직렬화 과정을 더 세밀하게 제어할 수 있게 하는 __serialize, __unserialize 매직 메소드가 도입되었다. 이 메소드들은 기존의 serialize(), unserialize() 함수 혹은 __sleep(), __wakeup() 매직 메소드와 관련이 있지만, 더 발전되었다.

 

 

__serialize()

객체를 안전하게 직렬화하기 위한 데이터를 지정하여 객체의 내부 상태를 직렬화 형식으로 변환시킨다.

class Test {

    private mixed $data;
    
    public function __construct(mixed $data) {
        $this->data = $data;
    }

    public function __serialize(): array
    {
        return [
            'data' => $this->data
        ];
    }
}

$obj = new Test("Test Data");

// 객체 직렬화
$serialized = serialize($obj);
dump($serialized); // O:16:"App\Library\Test":1:{s:4:"data";s:9:"Test Data";}

 

 

__unserialize()

직렬화된 데이터로부터 객체를 복원할 때 호출되며 저장된 데이터로부터 객체의 상태를 복원하거나 초기화 한다.

class Test {

    private mixed $data;

    public function __construct(mixed $data) {
        $this->data = $data;
    }

    public function __serialize(): array
    {
        return [
            'data' => $this->data
        ];
    }

    public function __unserialize(array $data): void
    {
        $this->data = array();
    }
}

$obj = new Test("Test Data");

// 객체 직렬화
$serialized = serialize($obj);

// 객체 역직렬화
$unSerialized = unserialize($serialized);
dump($unSerialized); //["data":"App\Library\Test":private]=> array(0) { }