1. 소개
PHP에서 필수 객체 유형을 구현하는 것은 때때로 매우 중요할 수 있습니다. 잘못된 프로그래밍 가정에 따른 지식 부족이나 단순한 게으름으로 인해 누락된 경우 특정 웹 애플리케이션에서 예상하지 못한 결과가 표시됩니다. 특히 PHP 4에서 프로그래밍할 때 "is_a()" 함수(다른 방법도 있지만)를 사용하여 작업 중인 객체의 유형을 확인하는 것은 매우 쉽습니다. 물론 강제 객체 유형을 사용하면 동일한 애플리케이션의 다른 PHP 클래스에 매개변수로 전달해야 하는 입력 객체를 필터링할 수도 있습니다.
그러나 PHP 4는 객체 모델에 대한 몇 가지 약점을 드러내지 않습니다. 성숙한 객체 지향 언어에서 발견되는 특정 기능을 구현하기 위해 때때로 추가 코드를 작성해야 할 수도 있습니다. 이 사실은 오랫동안 PHP 커뮤니티에 알려져 왔습니다. 그러나 PHP 5가 출시되면서 이러한 매우 귀중한 기능 중 다수가 향상된 개체 모델의 일부로 추가되었습니다. 이는 객체 기반 코드 개발을 더욱 긴밀하게 구현하는 데 도움이 되며 특정 객체 특성을 사용할 수 있게 해줍니다.
위의 경우 객체 유형 강제에 있어서 특별한 주의가 필요합니다. 실제로 PHP 5는 개발자에게 웹 애플리케이션 실행 중에 객체 유형을 확인할 수 있는 최소한 두 가지 방법, 즉 "instanceof" 연산자와 "유형 힌트" 기능을 제공합니다. 이제 이 기사의 주요 주제로 돌아가서, PHP 5의 "instanceof" 연산자를 소개하겠습니다. 작업 중인 개체가 특정 유형에 속하는지 여부를 결정하는 데 매우 편리하다는 사실을 곧 알게 될 것입니다.
이 기사는 몇 가지 객체 지향 예제를 통해 PHP 5에서 필수 객체 유형을 구현하는 방법을 이해하는 데 도움이 될 것입니다.
2. 하지 말아야 할 일
PHP 5에서 객체 유형 강제 변환을 구현하는 방법을 보여주기 위해 (X)HTML 위젯 클래스와 간단한 페이지 빌더 클래스를 사용하고 PHP 5 개발 환경에 맞게 간단히 수정하겠습니다.
내 첫 번째 예는 추상 기본 클래스 "HTMLElement"에서 파생된 일부 (X)HTML 위젯 클래스를 나열합니다. 이 클래스는 입력 개체의 유형 확인을 건너뜁니다. 먼저 다음 클래스를 살펴보십시오.
//추상 클래스 'HTMLElement'를 정의합니다.
추상 클래스 HTMLElement{
보호된 $속성;
보호된 함수 __construct($attributes){
if(!is_array($attributes)){
throw new Exception('잘못된 속성 유형');
}
$this->속성=$속성;
}
// 추상 'getHTML()' 메서드 추상 보호 함수 getHTML();
}
//특정 클래스 'Div' 정의 - HTMLElement 확장
클래스 Div는 HTMLElement를 확장합니다.
개인 $output='<div';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</div>';
$this->출력을 반환합니다.
}
}
//구체 클래스 'Header1' 정의 - HTMLElement 확장
클래스 Header1은 HTMLElement를 확장합니다.
비공개 $output='<h1 ';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</h1>';
$this->출력을 반환합니다.
}
}
//구체적 클래스 'Paragraph' 정의 - HTMLElement 확장
클래스 단락은 HTMLElement를 확장합니다.
비공개 $output='<p';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</p>';
$this->출력을 반환합니다.
}
}
//구체 클래스 'UnorderedList' 정의 - HTMLElement 확장
UnorderedList 클래스는 HTMLElement를 확장합니다.
비공개 $output='<ul';
개인 $items=배열();
공용 함수 __construct($attributes=array(), $items=array()){
parent::__construct($attributes);
if(!is_array($items)){
throw new Exception('목록 항목에 대한 매개변수가 잘못되었습니다.');
}
$this->items=$items;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->항목을 $item으로){
$this->output.='<li>'.$item.'</li>';
}
$this->output.='</ul>';
$this->출력을 반환합니다.
}
}
보시다시피 위의 (X)HTML 위젯 클래스는 웹에서 특정 요소를 생성하는 데 매우 유용하지만 입력 매개변수의 유효성을 확인할 수 없도록 의도적으로 각 클래스에 대한 코드를 작성했습니다. 짐작할 수 있듯이 입력 매개변수는 클래스 생성자에 직접 전달되고 속성으로 할당됩니다. 질문이 생깁니다. 이 작업을 수행하는 데 문제가 있습니까? 예, 그렇습니다. 이제 가장 간단한 페이지 빌더 클래스를 정의하고 이와 같은 위젯을 제공하여 이 클래스에 대한 입력이 잘못된 개체와 어떻게 혼합되는지 확인할 것입니다. 다음은 페이지 생성기 클래스의 서명입니다.
class PageGenerator{
비공개 $output='';
비공개 $제목;
공개 함수 __construct($title='기본 페이지'){
$this->제목=$제목;
}
공개 함수 doHeader(){
$this->output='<html><head><title>'.$this-
>제목.'</title></head><body>';
}
공개 함수 addHTMLElement($htmlElement){
$this->output.=$htmlElement->getHTML();
}
공개 함수 doFooter(){
$this->output.='</body></html>';
}
공개 함수 fetchHTML(){
$this->출력을 반환합니다.
}
}
이제 다음 예제와 같이 일부 (X)HTML 위젯 개체를 인스턴스화하고 해당 생성기 클래스에 전달하기 시작합니다
.
//몇 가지 HTML 요소 생성 $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
요소가 여기에 표시됩니다.');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'Div 요소의 콘텐츠
여기로 간다');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'단락 내용
요소가 여기에 표시됩니다.');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), 배열
('항목1'=>'값1', '항목2'=>'값2', '항목3'=>'값3'));
//페이지 생성기 클래스 인스턴스화 $pageGen=new Page Generator();
$pageGen->doHeader();
//'HTMLElement' 객체 추가 $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
//웹페이지 표시 echo $pageGen->fetchHTML();
}
catch(예외 $e){
echo $e->getMessage();
출구();
}
위의 PHP 코드를 실행한 후 얻을 수 있는 결과는 간단한 웹 페이지입니다. 여기에는 이전에 생성된 일부 (X)HTML 개체가 포함되어 있습니다. 이 경우 어떤 이유로 인해 페이지 빌더 클래스가 잘못된 개체를 수신하고 해당 "addHTML()" 메서드를 호출하면 어떤 일이 발생하는지 쉽게 이해할 수 있습니다. 여기에서는 존재하지 않는 (X)HTML 위젯 객체를 사용하여 충돌 조건을 재작업했습니다. 다음 코드를 다시 살펴보세요.
try{
//몇 가지 HTML 요소 생성 $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
요소가 여기에 표시됩니다.');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'Div 요소의 콘텐츠
여기로 간다');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'단락 내용
요소가 여기에 표시됩니다.');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), 배열
('항목1'=>'값1', '항목2'=>'값2', '항목3'=>'값3'));
//페이지 생성기 클래스 인스턴스화 $pageGen=new Page Generator();
$pageGen->doHeader();
//'HTMLElement' 객체 추가 $pageGen->addHTMLElement($fakeobj) //존재하지 않는 객체를 이 메소드에 전달 $pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// 페이지 표시 echo $pageGen->fetchHTML();
}
catch(예외 $e){
echo $e->getMessage();
출구();
}
이 경우 다음 줄에 표시된 대로:
$pageGen->addHTMLElement($fakeobj)//존재하지 않는 개체를 이 메서드에 전달
존재하지 않는 (X)HTML 위젯 개체가 페이지 생성기 클래스에 전달됩니다. 치명적인 오류가 발생합니다:
Fatal error: Call to a member function on a non-object in
경로/대상/파일은
어떻습니까
?이는 생성기 클래스에 전달된 객체의 유형을 확인하지 않은 것에 대한 직접적인 처벌입니다! 따라서 스크립트를 작성할 때 이 점을 염두에 두십시오. 다행히도 이러한 문제에 대한 간단한 해결책이 있으며, 여기서 "instanceof" 연산자의 힘이 발휘됩니다. 이 연산자가 어떻게 사용되는지 알고 싶다면 계속 읽어보세요.
3. "instanceof" 연산자를 사용하십시오.
보시다시피 "instanceof" 연산자의 사용은 두 개의 매개변수를 사용하여 해당 기능을 완성합니다. 첫 번째 매개변수는 확인하려는 객체이고, 두 번째 매개변수는 해당 객체가 해당 클래스의 인스턴스인지 여부를 확인하는 데 사용되는 클래스 이름(실제로는 인터페이스 이름)입니다. 물론 이 연산자가 얼마나 직관적으로 사용되는지 알 수 있도록 의도적으로 위의 용어를 사용했습니다. 기본 구문은 다음과 같습니다.
if (객체 인스턴스of 클래스 이름){
//유용한 일을 해라
}
이제 이 연산자가 PHP 5에서 어떻게 사용되는지 이해했으므로 "addHTMLElement()" 메소드에 전달된 객체 유형을 확인하기 위해 해당 웹 페이지 빌더 클래스를 정의해 보겠습니다. 다음은 앞서 언급한 "instanceof" 연산자를 사용하는 이 클래스의 새로운 서명입니다.
class PageGenerator{
비공개 $output='';
비공개 $제목;
공개 함수 __construct($title='기본 페이지'){
$this->제목=$제목;
}
공개 함수 doHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
공개 함수 addHTMLElement($htmlElement){
if(!$htmlElement 인스턴스ofHTMLElement){
throw new Exception('잘못된 (X)HTML 요소');
}
$this->output.=$htmlElement->getHTML();
}
공개 함수 doFooter(){
$this->output.='</body></html>';
}
공개 함수 fetchHTML(){
$this->출력을 반환합니다.
}
}
위 클래스에서 전달된 모든 개체가 이전에 정의한 "HTMLElement" 클래스의 인스턴스인지 확인하기 위해 "instanceof" 연산자가 "addHTMLElement()" 메서드에 어떻게 포함되어 있는지 참고하세요. 이제 앞서 본 웹 페이지를 재구성할 수 있습니다. 이 경우 웹 페이지 빌더 클래스에 전달된 모든 입력 개체가 실제 (X)HTML 위젯 개체인지 확인하세요. 여기에 해당하는 예가 있습니다:
try{
//몇 가지 HTML 요소 생성 $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'H1 요소의 콘텐츠가 여기에 표시됩니다.');
$div=new Div(array('name'=>'div1', 'class'=>'divclass'), 'Div 요소의 콘텐츠가 여기에 표시됩니다.');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'단락 요소의 내용이 여기에 표시됩니다.');
$teststr='이것은 HTML 요소가 아닙니다';
//페이지 생성기 클래스 인스턴스화 $pageGen=new Page Generator();
$pageGen->doHeader();
//'HTMLElement' 객체 추가 $pageGen->addHTMLElement($teststr) //이 메소드에 간단한 문자열 전달 $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->doFooter();
//웹페이지 표시 echo $pageGen->fetchHTML();
}
catch(예외 $e){
echo $e->getMessage();
출구();
}
위의 예에서 볼 수 있듯이 간단한 테스트 문자열("HTMLElement" 객체가 아님)을 페이지 빌더 클래스에 전달합니다. 그러면 아래와 같이 특정 "catch" 블록에 의해 포착된 예외가 발생합니다.
잘못된 (X)HTML 요소
이때 입력 개체의 유효성을 확인하기 위해 "instanceof" 연산자를 사용하여 위 웹 페이지가 될 수 있도록 입력을 필터링하는 것의 중요성을 진심으로 인식하시기 바랍니다. 이 연산자를 사용하여 외부 오류를 방지하기 위한 클래스 메소드
웹 페이지 생성기 클래스 내에서 "instanceof" 연산자의 올바른 구현을 보여준 후 이전 기사에서 PHP 4에 대해 작성한 것과 유사한 작업이 더 있습니다. (X) HTML 위젯 클래스의 경우 "getHTML()" 메서드의 일부로 이 연산자를 포함하여 중첩된 (X)HTML 요소를 생성하는 웹 페이지를 생성하는 방법을 논의하겠습니다.
4. "instanceof" 연산자 사용 확장: 중첩된 (X)HTML 위젯이
좋습니다. "instanceof" 연산자가 페이지 빌더 기능에 직접 삽입된 입력 개체에 대한 유형 검사에 효과적이라는 것을 확인했습니다. 이제 한 단계 더 나아가 (X)HTML 위젯 클래스의 생성자와 "getHTML()" 메서드에 검사 루틴을 추가하여 다른 위젯을 입력 매개변수로 받아들일 수 있도록 하겠습니다. 아래 클래스를 확인하세요.
클래스 Div는 HTMLElement를 확장합니다.
개인 $output='<div';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
if(!$data 인스턴스ofHTMLElement&&!is_string($data)){
throw new Exception('잘못된 매개변수 유형');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->HTMLElement의 데이터 인스턴스)?
$this->data->getHTML():$this->data;
$this->output.='</div>';
$this->출력을 반환합니다.
}
}
클래스 Header1은 HTMLElement를 확장합니다.
비공개 $output='<h1 ';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
if(!$data 인스턴스ofHTMLElement&&!is_string($data)){
throw new Exception('잘못된 매개변수 유형');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->HTMLElement의 데이터 인스턴스)?
$this->data->getHTML():$this->data;
$this->output.='</h1>';
$this->출력을 반환합니다.
}
}
클래스 단락은 HTMLElement를 확장합니다.
비공개 $output='<p';
비공개 $data;
공개 함수 __construct($attributes=array(),$data){
if(!$data 인스턴스ofHTMLElement&&!is_string($data)){
throw new Exception('잘못된 매개변수 유형');
}
parent::__construct($attributes);
$this->data=$data;
}
//'getHTML()' 메소드의 특정 구현 public function getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->HTMLElement의 데이터 인스턴스)?
$this->data->getHTML():$this->data;
$this->output.='</p>';
$this->출력을 반환합니다.
}
}
UnorderedList 클래스는 HTMLElement를 확장합니다.
비공개 $output='<ul';
개인 $items=배열();
공용 함수 __construct($attributes=array(), $items=array()){
parent::__construct($attributes);
if(!is_array($items)){
throw new Exception('목록 항목에 대한 매개변수가 잘못되었습니다.');
}
$this->items=$items;
}
//'getHTML()' 메소드의 특정 구현
공개 함수 getHTML(){
foreach($this->속성을 $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->항목을 $item으로){
$this->output.=($item 인스턴스
HTMLElement)?'<li>'.$item->getHTML().'</li>':'<li>'.$item.'</li>';
}
$this->output.='</ul>';
$this->출력을 반환합니다.
}
}
위 클래스에서 볼 수 있듯이 해당 웹 페이지를 생성할 때 중첩된 (X)HTML 요소가 구현될 수 있도록 하기 위해 생성자와 "getHTML()" 메서드를 각각 리팩터링했습니다. 각 클래스의 생성자에 다음 조건부 블록을 포함시켰습니다.
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('잘못된 매개변수 유형');
}
이 시점에서 실제로 수행하는 작업은 문자열 데이터와 "HTMLElement" 유형의 개체만 각 클래스의 입력 매개 변수로 허용되는지 확인하는 것입니다. 그렇지 않으면 해당 메서드에서 예외가 발생하고 애플리케이션 실행이 중지될 수 있습니다. 그래서 입력된 데이터를 확인하는 과정입니다. 이제 "instanceof" 연산자도 사용하는 "getHTML()" 메소드의 새로운 서명을 살펴보겠습니다.
$this->output.=($this->data instanceof HTMLElement)?$this->data-
>getHTML():$this->data;
보시다시피 이 경우 this 연산자는 (X)HTML 위젯 클래스의 다형성 기능을 활용하는 데 매우 유용합니다. $data 속성도 위젯인 경우 "getHTML()" 메소드가 올바르게 호출되어 중첩된 웹 요소가 표시됩니다. 반면에 단순한 문자열인 경우 현재 클래스의 모든 출력에 직접 추가됩니다.
이 시점에서 특정 객체가 특정 유형에 속하는지 확인하기 위해 PHP 5에서 "instanceof" 연산자의 사용법을 이해했을 것입니다. 이 기사에서 볼 수 있듯이 PHP 5에서 객체 유형을 강제하는 것은 실제로 매우 간단한 작업입니다. 지금은 이 방법을 사용하여 PHP 애플리케이션의 개체를 필터링하는 예제를 개발하여 이해를 심화하는 것이 좋습니다.
5. 요약
이 기사에서는 PHP 5에서 "instanceof" 연산자를 사용하여 입력 개체의 유형을 확인하는 방법을 배웠습니다. 그러나 제가 보여드린 방법이 유일한 방법은 아닙니다. 이후 기사에서는 객체 유형 지정을 강제하는 또 다른 방법인 PHP 5의 멋진 "유형 힌트" 기능을 구현하는 방법을 설명하겠습니다.
저자: Zhu Xianzhong 컴파일러 출처: Tianji Development