Menu
Coddy logo textTech

__call 및 __callStatic

Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 47번째.

__get()__set()이 속성 접근을 가로채는 것과 마찬가지로, __call()__callStatic() 메서드는 메서드 호출을 가로챕니다. 이 메서드들은 객체나 클래스에서 존재하지 않거나 접근할 수 없는 메서드를 호출할 때 트리거됩니다.

__call() 메서드는 인스턴스 메서드 호출을 처리합니다. 이 메서드는 메서드 이름과 인자 배열을 전달받습니다:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");

출력:

Called 'sendEmail' with: Hello, World

정적 메서드 호출의 경우, __callStatic()을 사용하세요. 반드시 static으로 선언되어야 함에 유의하세요:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");

출력:

Finding by Email: test@example.com

이러한 매직 메서드들은 플루언트 API를 생성하거나, 메서드 포워딩을 구현하거나, 메서드 이름이 데이터베이스 작업으로 변환되는 동적 쿼리 빌더를 구축하는 데 매우 강력합니다. 이를 통해 객체는 명시적으로 정의하지 않은 메서드 호출을 포함하여 모든 메서드 호출에 지능적으로 응답할 수 있습니다.

challenge icon

챌린지

쉬움

매직 메서드를 사용하여 메서드 호출을 유연하게 처리하는 동적 API 클라이언트를 구축해 보겠습니다. 각 메서드를 명시적으로 정의하지 않고도 인스턴스 및 정적 메서드 호출을 가로채서 의미 있는 API 스타일의 응답으로 변환하는 클래스를 만들 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • ApiClient.php — 매직 메서드를 사용하여 API 상호작용을 시뮬레이션하는 ApiClient 클래스를 생성합니다. 클래스는 생성자를 통해 설정되는 프라이빗 $baseUrl 속성을 가져야 합니다. 다음 두 가지 매직 메서드를 구현하세요:
    • __call() — 인스턴스 메서드 호출을 처리합니다. get으로 시작하는 메서드(예: getUsers 또는 getPosts)가 호출되면, 리소스 이름("get" 뒤의 부분)을 추출하여 "GET [baseUrl]/[resource]: [arguments joined by comma]"를 반환합니다. 리소스 이름은 소문자로 변환되어야 합니다. 메서드가 "get"으로 시작하지 않으면 "Unknown action: [methodName]"을 반환합니다.
    • __callStatic() — 정적 메서드 호출을 처리합니다. create로 시작하는 메서드(예: createUser)가 호출되면, 리소스 이름을 추출하여 "POST /[resource]: [arguments joined by comma]"를 반환합니다. 리소스 이름은 소문자여야 합니다. delete로 시작하는 메서드의 경우 "DELETE /[resource]: [first argument]"를 반환합니다. 그 외의 다른 메서드는 "Static action not supported: [methodName]"을 반환합니다.
  • main.php — ApiClient 파일을 포함합니다. 베이스 URL, 리소스 식별자, 값이라는 세 가지 입력을 받게 됩니다. 베이스 URL을 사용하여 ApiClient 인스턴스를 생성합니다. 그런 다음 네 줄을 출력하세요:
    • 리소스 식별자를 메서드 이름 접미사로 사용하여 동적 get 메서드를 호출하고(예: 리소스가 "Users"인 경우 getUsers 호출), 값을 인자로 전달합니다.
    • getProducts를 두 개의 인자 "electronics""active"와 함께 호출합니다.
    • 정적 메서드 createOrder를 값을 인자로 하여 호출합니다.
    • 정적 메서드 deleteItem을 리소스 식별자를 인자로 하여 호출합니다.

매직 메서드를 사용하면 API 클라이언트가 모든 메서드 호출에 동적으로 응답할 수 있습니다. getUsers(), getPosts(), getProducts() 등 수십 개의 메서드를 정의하는 대신, 단일 __call() 메서드가 메서드 이름을 검사하고 관련 정보를 추출하여 모든 호출을 처리합니다.

치트 시트

__call() 메서드는 존재하지 않거나 접근할 수 없는 인스턴스 메서드 호출을 가로챕니다. 이 메서드는 메서드 이름과 인자 배열을 전달받습니다:

<?php
class Messenger {
    public function __call(string $name, array $arguments): string {
        return "Called '$name' with: " . implode(", ", $arguments);
    }
}

$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");
// Output: Called 'sendEmail' with: Hello, World

__callStatic() 메서드는 정적 메서드 호출을 가로챕니다. 이 메서드는 반드시 static으로 선언되어야 합니다:

<?php
class QueryBuilder {
    public static function __callStatic(string $name, array $arguments): string {
        if (str_starts_with($name, "findBy")) {
            $field = substr($name, 6);
            return "Finding by $field: " . $arguments[0];
        }
        return "Unknown method: $name";
    }
}

echo QueryBuilder::findByEmail("test@example.com");
// Output: Finding by Email: test@example.com

이러한 매직 메서드들은 유연한 API(fluent APIs)를 생성하거나, 메서드 포워딩을 구현하거나, 메서드 이름이 작업으로 변환되는 동적 쿼리 빌더를 구축할 때 유용합니다.

직접 해보기

<?php

require_once 'ApiClient.php';

// 입력 읽기
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: 베이스 URL을 사용하여 ApiClient 인스턴스 생성

// TODO: 리소스를 메서드 이름 접미사로 사용하여 동적 get 메서드 호출
// 힌트: $api->{"get" . $resource}($value)와 같은 가변 메서드 호출 사용

// TODO: "electronics"와 "active" 두 개의 인자로 getProducts 호출

// TODO: value를 인자로 하여 정적 메서드 createOrder 호출
// 힌트: ApiClient::createOrder($value) 사용

// TODO: 리소스를 인자로 하여 정적 메서드 deleteItem 호출

?>
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨