__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를 생성하거나, 메서드 포워딩을 구현하거나, 메서드 이름이 데이터베이스 작업으로 변환되는 동적 쿼리 빌더를 구축하는 데 매우 강력합니다. 이를 통해 객체는 명시적으로 정의하지 않은 메서드 호출을 포함하여 모든 메서드 호출에 지능적으로 응답할 수 있습니다.
챌린지
쉬움매직 메서드를 사용하여 메서드 호출을 유연하게 처리하는 동적 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 호출
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8매직 메서드
매직 메서드 소개__toString 및 __debugInfo__get, __set, __isset, __unset__call 및 __callStatic__clone 및 객체 복제__serialize 및 __unserialize요약 - 커스텀 컬렉션