최근에 "php Core Technology and Best Practices"라는 책을 읽고 있습니다. 이 책의 첫 번째 장에서는 __call() 메서드를 사용하여 간단한 문자열 체인 작업을 구현할 수 있다고 언급하고 있습니다. then 길이를 구하는 연산은 일반적으로 다음과 같이 작성됩니다:
strlen(trim($str));
그럼 다음과 같은 작성이 가능할까요?
$str->trim()->strlen();
아래에서 시도해 보겠습니다.
체인 연산은 직설적으로 말하면 실제로는 객체 메서드를 호출하는 체인 메서드입니다. 문자열 체인 작업을 구현하려면 문자열 클래스를 구현한 다음 이 클래스의 개체를 호출해야 합니다. 문자열 클래스에 대한 기대치는 다음과 같습니다. (1) 객체를 생성할 때 문자열을 객체의 속성에 할당할 수 있으며 이 속성에 액세스하여 값을 읽을 수 있습니다. (2) Trim( ) 및 strlen( ) 메서드; (3) $str->trim()->strlen() 메서드를 이와 같이 호출할 수도 있습니다.
위의 (1) 항목은 문자열 클래스의 기본 요구 사항입니다. 이것을 먼저 구현하십시오:
class String { public $value; public function __construct($str=null) { $this->value = $str; } }
다음을 시도해 보십시오:
1 $str = new String('01389');
2 echo $str->
그런 다음 항목 2를 살펴보고 먼저 $str->trim()을 구현하고 책의 아이디어를 참조하십시오. __call 메서드를 트리거한 다음 call_user_func를 실행합니다. . 코드는 다음과 같습니다.
class String { public $value; public function __construct($str=null) { $this->value = $str; } public function __call($name, $args) { $this->value = call_user_func($name, $this->value, $args[0]); return $this; } }
테스트:
1 $str = new String('01389');
2 echo $str->trim( '0')->value;
결과는 다음과 같습니다.
위에서 주목해야 할 것은 12행입니다. $ this->value = call_user_func($name, $this->value, $args[0]); $name은 콜백 함수의 이름입니다(여기서는 Trim입니다). 마지막 두 개는 콜백 함수의 매개변수입니다. (tirm), 매개변수의 순서를 거꾸로 변경하지 마십시오. $args는 배열이므로 주의가 필요합니다.
Strlen()은 Article 2에서 구현되어야 합니다. 이때 위 코드의 13행은 매우 중요합니다. return $this 이 함수는 12행에서 Trim()을 호출하여 처리를 완료하는 것입니다. 문자열 뒤에는 값 속성이 다시 할당된 다음 현재 개체의 참조가 반환되므로 개체의 다른 메서드가 속성 값에 대해 연속적인 작업을 수행할 수 있으므로 체인 작업이 실현됩니다. $str->strlen()은 다음과 같이 구현됩니다:
class String { public $value; public function __construct($str=null) { $this->value = $str; } public function __call($name, $args) { $this->value = call_user_func($name, $this->value, $args[0]); return $this; } public function strlen() { return strlen($this->value); } }
테스트:
1 $str = new String('01389');
2 echo $ str->strlen();
결과:
체인 작업:
echo $str-> Trim('0')->strlen();
결과:
class String { public $value; public function __construct($str=null) { $this->value = $str; } public function trim($t) { $this->value = trim($this->value, $t); return $this; } public function strlen() { return strlen($this->value); } }
체인 작업의 핵심은 다음과 같습니다. 작업을 완료한 후 $this를 반환합니다.
또한 이 글은 정원에 있는 이 글에서 영감을 받아 call_user_func() 구현을 call_user_func_array()로 대체하고 __call() 메서드를 다음과 같이 수정했습니다.
public function __call($name, $args) { array_unshift($args, $this->value); $this->value = call_user_func_array($name, $args); return $this; }
은 위의 __call() 메서드와 동일한 효과를 가지므로 이전 구현보다 코드가 더 우아해 보입니다.
요약:
__call()은 객체가 접근할 수 없는 메소드를 호출할 때 트리거되므로 클래스의 동적 메소드 생성을 구현하고 PHP의 메소드 오버로딩 기능을 구현할 수 있지만, 실제로 이것은 구문상의 설탕입니다(또한 __construct() 메서드).
그러면 __call()과 같은 구문 설탕이 없다면 동적 메서드 생성과 체인 작업이 실현될 수 있을까요? 나는 다음과 같은 측면을 포함할 것이라고 생각합니다: 클래스 메소드가 존재하는지, 호출될 수 있는지. 이는 method_exists, is_callable, get_class_methods 및 기타 메소드를 사용하여 달성할 수 있습니다. 또한 객체를 생성할 때 속성에 값(초기화)을 할당하는 것은 실제로 편리하지만 꼭 필요한 것은 아닙니다. 시간 나면 다시 공부해 봅시다.