맞는 말이지만, php5 객체가 사용하는 API 함수는 여전히 php4의 API에 따라 구축되었습니다. 10장 "php4 객체"를 읽었다면 이 장의 내용에 어느 정도 익숙해졌을 것입니다. Chapter 10과 마찬가지로 확장 이름을 Sample3으로 바꾸고 중복 코드를 정리하고 확장의 뼈대 코드만 남겨두세요. > php5 개체 변수에는 두 가지 핵심 구성 요소가 있습니다. 9장 "리소스 데이터 타입"에서 소개한 숫자형 리소스 ID와 매우 유사한 숫자형 식별자로, 해당 테이블에서 객체 인스턴스를 찾는 키 역할을 한다. zend_class_entry 및 내부 속성 테이블에 대한 참조를 포함합니다.
두 번째 요소는 개체 변수입니다. Zend 엔진이 인스턴스를 처리하는 방법을 사용자 정의할 수 있는 핸들 테이블이 표시됩니다.
zend_class_entry
클래스 항목은 사용자 정의 클래스의 내부 표현입니다. 이전 장에서 본 것처럼 이 구조는 클래스 이름과 해당 함수 테이블을 사용하여 INIT_CLASS_ENTRY()를 호출하여 초기화됩니다. 다음 MINIT 단계에서 등록하려면 zend_register_internal_class()를 사용하세요. 지금까지는?", 그리고 지금까지는 당신이 옳을 것입니다. 이제 몇 가지 객체 메서드를 정의해 보겠습니다. 매우 명확하고 환영할 만한 차이점을 발견하게 될 것입니다.
PHP_METHOD() 매크로는 Zend Engine 2에서 도입되었습니다. 이는 PHP_FUNCTION() 매크로를 캡슐화한 것으로, php4와 같이 수동으로 메소드를 정의하지 않고도 클래스 이름과 메소드 이름을 결합합니다.
정의
메서드 구현을 정의합니다. , 다른 함수와 마찬가지로 클래스의 함수 테이블에 연결하기만 하면 됩니다. 구현에 사용되는 PHP_METHOD() 매크로 외에도 함수 목록 정의에 사용할 수 있는 몇 가지 새로운 매크로가 있습니다.
PHP_ME(classname, methodname, arg_info, flags)
에 소개된 PHP_FE() 매크로와 비교 5장 "첫 번째 확장", PHP_ME()는 클래스 이름 매개 변수와 플래그 매개 변수를 끝에 추가합니다(공용, 보호, 개인, 정적 및 기타 액세스 제어와 추상 및 기타 옵션을 제공하는 데 사용됨). helloWorld 메소드를 정의하려면 다음과 같이 정의할 수 있습니다:
예를 들어 앞서 정의한 Sample3_SecondClass::helloWorld() 메서드에는 객체 인스턴스가 필요하지 않으므로 정의를 단순에서 변경할 수 있습니다. ZEND_ACC_PUBLIC을 ZEND_ACC_PUBLIC | ZEND_ACC_STATIC으로 변경하여 엔진이 이를 알고 나면 (인스턴스를) 제공하지 않도록 합니다.
마법의 방법
ZE1의 매직 메소드 외에도 ZE2에는 다음 표와 같이 많은 새로운 매직 메소드가 추가되었습니다. (또는 http://www.php.cn/에서 확인할 수 있습니다.)
방법
사용법
__construct(...)
자동으로 호출되는 객체 생성자 (가 클래스 이름과 일치하는 메서드를 이전에 정의함). __construct() 및 classname()의 두 구현 모두 , 이 인스턴스화되어 존재합니다. 이 과정에서 ,는 __construct()
< 호출을 우선으로 합니다. 🎜>
__destruct()
인스턴스가 범위를 벗어날 때
, 또는 완전 종료를 요청할 때 ,은 모두 인스턴스의 __destruct() 메소드가 일부 정리 작업을 처리하기 위해 암시적으로 호출되도록 합니다, 예를 들어 파일 또는 네트워크 핸들을 닫는 경우 .
__clone()
기본적으로 ,모든 인스턴스는 진정한 참조별 전달입니다.php5에서 객체 인스턴스,를 실제로 복사하려면 clone키워드를 사용해야 합니다.객체 인스턴스에서 clone 키워드를 호출할 때,
__clone() 메서드는 암시적으로 실행됩니다,. 이를 통해 객체가 일부 필수 내부 리소스 데이터를 복사할 수 있습니다.
__toString()
텍스트를 사용하여 객체를 나타내는 경우 ,예를 들어 echo 또는 print 문을 객체에 직접 사용하는 경우,
__toString() 메서드는 엔진 에 의해 자동으로 호출됩니다. 클래스가 이 마법 메서드 를 구현하는 경우 는 개체의 현재 상태에 대한 설명이 포함된 문자열을 반환해야 합니다 .
__get($var)
스크립트가 개체의 보이지 않는 속성을 요청하는 경우 (이 존재하지 않거나 접근 제어로 인해 보이지 않습니다 )할 때,
__get()마법 메서드가 호출됩니다,유일한 매개 변수는 요청된 속성 이름입니다.구현 자체 내부 논리를 사용하여 .
__set($var , $value)
및 __get()은 과 매우 유사합니다.
__set()은 객체의 보이지 않는 속성에 할당하는 논리를 처리하는 데 사용되는 , 구현을 제공합니다. __set()은 표준 속성 테이블 , 에서 이러한 변수를 암시적으로 생성하고 다른 저장 메커니즘 , <을 사용하여 값을 설정하도록 선택할 수 있습니다. 🎜> 아니면 오류를 발생시키고 .
__call($fname, $args)
객체의 정의되지 않은 메서드를 호출할 때 __call()을 사용하면 아름다운 결과를 얻을 수 있습니다. 🎜> 매직 메소드 처리.이 메소드는 두 개의 매개변수 를 허용합니다:호출된 메소드 이름,호출에 전달된 모든 인수의 숫자 인덱스를 포함하는 배열.
__isset ($varname )
php5.1.0 이후 isset($obj->prop) 호출은 🎜>$obj, , 에 prop이 있는지 확인하세요. $obj__isset()method, 동적 평가 동적 사용 여부 __get() 및 __set() 메서드는
<🎜 속성을 성공적으로 읽고 쓸 수 있습니다. >
__unset($varname)
__isset(), php 5.1과 유사 .0은 unset() 함수에 대한 간단한 OOP인터페이스를 소개합니다. 객체 속성에 사용할 수 있습니다,이 속성은 객체의 표준 속성 테이블에 없을 수도 있지만,그러나 __get() 및 __set()의 동적 속성 공간에는 적합할 수 있습니다. 따라서 이 문제를 해결하기 위해 __unset()을 도입했습니다.
get_property_ptr_ptr()은 read_property()의 변형입니다. 즉, 호출 범위에서 현재 zval *을 새 값으로 직접 바꿀 수 있습니다. 표준 속성 테이블 속성의 포인터 주소가 존재하지 않고 __get()/__set() 매직 메서드가 없으면 포인터가 암시적으로 생성되고 __get() 또는 __set() 메서드가 반환됩니다. , 이 핸들이 실패하게 되어 엔진이 대신 별도의 read_property 및 write_property 호출에 의존하게 됩니다.
zval *read_dimension(zval *obj, zval * idx, int 유형 TSRMLS_DC)
read_dimension() 및 write_dimension()은 해당 read_property() 및 write_property()와 유사하지만 $obj['idx'] 메서드를 사용하여 객체에 배열로 액세스할 때 트리거됩니다. 객체의 클래스가 ArrayAccess 인터페이스를 구현하지 않는 경우 기본 동작은 오류를 트리거하는 것입니다. 그렇지 않으면 매직 메소드 offsetget($idx) 또는 offsetset($idx, $value)를 호출합니다.
zval *get( zval *obj TSRMLS_DC)
void set(zval *obj, zval *value TSRMLS_DC)
객체의 값을 설정하거나 검색할 때 객체에 대해 get() 또는 set() 메서드가 호출됩니다. 객체 자체는 다음과 같이 전달됩니다. 첫 번째 매개변수는 새 값이 두 번째 매개변수로 전달됩니다. ; 실제로 이러한 메소드는 산술 연산에 사용됩니다.
int has_property(zval *obj, zval *prop, int chk_type TSRMLS_DC)
이 핸들러는 isset()이 호출될 때 호출됩니다. 기본적으로 표준 핸들러는 지정된 속성 이름을 확인합니다. 이 속성이 PHP 5.1.0에 없고 __isset() 메소드가 정의되어 있으면 chk_type 매개변수의 값이 2입니다. , 속성만 존재해야 합니다. chk_type 값이 0이면 존재해야 하며 IS_NULL 값이 아니어야 합니다. chk_type 값이 1이면 속성이 존재해야 하며 FALSE 이외의 값이어야 합니다. PHP 5.0.x,
chk_type의 의미는 has_dimension의 chk_type과 일치합니다.
int has_dimension(zval *obj, zval *idx, int chk_type TSRMLS_DC)
객체를 배열(예: isset($obj['idx']))로 처리할 때 isset()을 호출하면 이 프로세서가 사용됩니다. 객체 구현 여부 확인 ArrayAccess 인터페이스가 구현되어 있으면 offsetexists($idx) 메소드를 호출하고, 찾지 못하면(offsetexists() 호출 참조), offsetexists() 메소드가 구현되지 않은 것과 동일합니다. 그렇지 않고 chk_type이 0이면 직접 true(1)를 반환합니다. chk_type이 1이면 개체의 offsetget($idx) 메서드를 호출하고 반환 값을 테스트해야 함을 나타냅니다.
값이 FALSE가 아닌 경우에만 TRUE(1)를 반환합니다.
객체 속성을 언로드하려고 할 때 이 두 가지 방법을 사용하세요. (또는 배열의 객체에 unset()을 적용할 때) unset_property() 핸들러는 표준 속성 테이블(존재하는 경우)에서 속성을 제거하거나 구현된 __unset($prop) 메서드(php 5.1)를 호출하려고 시도합니다. .0), unset_dimension()은 클래스가 ArrayAccess를 구현할 때 offsetunset($idx) 메서드를 호출합니다.
HashTable *get_properties(zval *obj TSRMLS_DC)
이 핸들러는 내부 함수가 Z_OBJPROP() 매크로를 사용하여 표준 속성 테이블에서 속성을 읽을 때 실제로 호출됩니다. 프로세서는 압축을 풀고 실제 표준 속성 테이블인 Z_OBJ_P(객체)->properties를 반환합니다.
union _zend_function *get_method(zval **obj_ptr char *method_name, int 메소드 이름_len TSRMLS_DC)
이 핸들러는 클래스의 function_table에 있는 객체 메서드를 구문 분석할 때 호출됩니다. 해당 메서드가 기본 function_table에 없으면 기본 핸들러는 객체에 대한 포인터를 반환합니다. 이름, $args) 메소드 래핑 zend_function * 포인터.
int call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
ZEND_OVERLOADED_FUNCTION 유형으로 정의된 함수는 call_method 프로세서로 실행됩니다. 기본적으로 이 프로세서는 정의되지 않습니다.
union _zend_function *get_constructor(zval *obj TSRMLS_DC)
이 프로세서는 get_method() 프로세서와 유사하게 해당 객체 메서드 참조를 반환합니다. 클래스의 zend_class_entry에 있는 생성자는 다음 위치에 저장됩니다. 이 메서드를 재정의하는 것은 매우 드뭅니다.
get_constructor()와 유사하며 이 프로세서의 목적은 객체 인스턴스를 매핑하는 것입니다. 원래 클래스 정의로 돌아갑니다.
int get_class_name(zval *object, char **name zend_uint *len, int parent TSRMLS_DC)
get_class_entry()는 한 단계입니다. 객체의 zend_object를 가져온 후 객체의 클래스 이름이나 상위 클래스 이름을 사용합니다(이는 매개변수 parent 값에 따라 다름). 클래스 이름의 반환된 복사본을 반환해야 합니다. 비영구 저장소(emalloc())를 사용합니다.
int Compare_objects(zval *obj1, zval * obj2 TSRMLS_DC)
비교 연산자(예: ==, !=, <=, <, >, >=)를 사용하는 경우 두 개의 객체가 있는 경우 비교 연산자()를 호출 피연산자(비교에 참여하는 두 개체)는 이 작업의 첫 번째 부분입니다. 반환 값은 일반적으로 각각 초과, 같음, 미만을 나타내는 1, 0, -1입니다. 기본적으로 개체는 비교 기준으로 사용됩니다. 표준 속성 테이블에서 8장 "배열 및 해시 테이블 작업"에서 배운 배열 비교 규칙과 동일한 비교 규칙을 사용합니다.
int cast_object( zval *src, zval *dst, int type, int should_free TSRMLS_DC)
객체를 다른 데이터 유형으로 캐스팅하려고 하면 이 프로세서가 트리거됩니다. should_free가 0이 아닌 값으로 설정되면 dst에서 zval_dtor()가 호출되어 먼저 내부 리소스를 해제합니다. 즉, 프로세서는 src의 객체를 zval * 유형의 Out으로 dst로 나타내려고 시도해야 합니다. 이 핸들러는 기본적으로 정의되지 않지만 존재하는 경우 SUCCESS 또는 FAILURE를 반환해야 합니다.
int count_elements (zval *obj, long *count TSRMLS_DC)
배열 액세스를 구현하는 객체는 이 핸들러를 정의해야 합니다. 이 핸들러는 현재 요소 수를 count로 설정하고 현재 인스턴스가 배열을 구현하지 않는 경우 SUCCESS를 반환합니다. 액세스할 경우 엔진이 돌아가서 표준 속성 테이블을 확인하도록 하려면 FAILURE를 반환해야 합니다.
주석: 위의 핸들 테이블과 php-5.4.9에서 사용되는 번역기는 더 이상 완전히 일관성이 없습니다. 이 부분을 공부할 때 독자는 Zend/zend_object_handlers.c.