Java의 리플렉션에 비해 PHP의 리플렉션은 실제로 양심의 작업입니다. 유지 관리 측면에서는 Java가 더 우수하고 더 많은 장점을 가지고 있습니다. 그러나 번거로운 처리로 인해 Java의 반사 메커니즘에 특정 학습 비용이 추가됩니다.
오늘은 수업정보를 얻기 위해 PHP의 Reflection 기술을 사용해 보았습니다.
핵심 작업은 PHP의 공식 도움말 문서에서 볼 수 있습니다. 여기서 가장 일반적으로 사용되는 작업은
getProperties getMethods
입니다. 리플렉션의 결과와 유지 관리를 보여주기 위해 먼저 클래스를 생성해 보겠습니다. 디렉토리 구조는 다음과 같습니다.
<?phpclass Person { private $name; private $age; private $address; public function __construct($name, $age, $address) { $this->name = $name; $this->age = $age; $this->address = $address; } public function setter($key, $value) { exec ( "{$this}->" . $key . "={$value}" ); } /** * 通配型的getter方法不好用。 * <br /> * 原因: Object Person can not be converted to string. * * @param unknown $key * @return string */ public function getter($key) { return exec ( "$this" . "->{$key}" ); } /** * 模拟Java语言实现的getter方法。<br /> * * 缺点: 需要为每一个private属性提供单独的getter方法,使得代码略显臃肿。 */ public function getName() { return $this->name; } }class Grade { private $name; public function __construct($name) { $this->name = $name; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } }
는 공식적으로 진행 중입니다. 반영 작업에 앞서 __autoload
자동 로딩 메커니즘에 대해 논의해 보겠습니다. 이름에서 알 수 있듯이 자동으로 로드됩니다(클래스 또는 기타 PHP 파일).
더 깊은 수준에서는 PHP 인터프리터의 작동 원리와 관련이 있습니다. 즉, 프로젝트에 하나의 PHP 파일만 작성할 수는 없습니다. 반대로 프로젝트에는 수백 개의 PHP 파일이 있을 수 있으며 필연적으로 서로 호출됩니다.
즉, 파일 A에서 덧셈 함수를 선언하고 구현하고, 파일 B에서 호출해야 한다는 뜻입니다. 분명히 이 추가는 B 파일에서 전혀 구현되지 않으므로 PHP 인터프리터는 추가 작업을 수행할 수 없습니다.
이때 PHP 인터프리터에게 이 덧셈을 어떻게 하는지 알려줘야 하므로 이 덧셈 기능이 담긴 A 파일이 require / include
필요합니다.
이러한 방식으로 PHP 인터프리터는 PHP 파일을 해석하고 실행하는 방법을 알고 있습니다.
PHP와 마찬가지로 Java 언어에서도 소스 파일 앞에 import
문만 추가하면 Java 가상 머신이 자동으로 관련 클래스 정보를 추가할 수 있습니다. 또한 강력한 형식의 Java는 컴파일 전에 이러한 문제를 감지할 수 있으므로 코드 유지 관리가 더 편리합니다. 그리고 PHP는 수동으로 수행해야 합니다 include/require
.
그러나 두 사람이 약을 바꾼 것이 아니라 국물을 바꾼 것일 뿐이라는 점은 분명해야 한다.
그러나 참조할 각 PHP 파일을 수동으로 로드하는 경우 이러한 로딩 문을 여러 개 작성해야 할 수도 있습니다. 따라서 이 문제를 쉽게 처리하기 위해 PHP5에서는 자동 로딩 메커니즘을 도입했습니다.
void __autoload ( string $class )
$class
는 로드할 클래스의 이름입니다. 类
의 이름입니다.
자동 로딩 기능이 너무 좋은데 어떻게 사용하나요?
답은 다른 클래스 파일을 로드해야 하는 사용자 정의 __autoload($class)
함수를 PHP에 추가하는 것입니다. 지금 AB 파일을 예로 들어보겠습니다.
파일 A에는 작성된 클래스 Person이 있는데, 이를 파일 B에서 사용해야 합니다. 이때 B 파일에 __aotoload
함수를 추가하면 됩니다. 게다가 이 함수의 작성 방법은 비교적 간단합니다(모든 것이 가장 간단한 아이디어에 따라 설계되었다면).
function __autoload($class) { $filename = "$class.class.php"; if(!file_exists($filename)){ throw new RuntimeException("$filename 文件不存在!"); }else { require "$filename"; } }
PHP 인터프리터는 파일 B를 스캔할 때 먼저 확인합니다. 대상 클래스 Person이 도입되지 않은 경우 __autoload
가 구현되어 있는지 확인하고, 존재하는 경우 자동 로딩 기능을 사용하여 로드합니다. 그렇지 않으면 오류와 함께 종료됩니다.
위의 자동 로딩 기능은 비교적 간단하지만 실제로는 많은 "가격"이 필요합니다. 즉, 로드된 클래스 파일의 이름이 클래스와 일치해야 합니다. 일관성(대소문자 구분 필요 없음) 예를 들면 다음과 같습니다.
要加载的类的名称为Person, 则该类所在的文件的名称需要为person.class.php,或者Person.class.php
게다가 경로 문제도 이 간단한 자동 로딩 기능에서 확인하기 어렵지 않습니다. 여기서는 이 조건이 같은 디렉터리에 있습니다. 이 자동 로딩 기능이 얼마나 큰 코드의 양인지 알 수 있습니다.
이 경우 자동 로딩 메커니즘의 원래 의도에도 위배됩니다. 따라서 특정 디렉토리 구조에 따라 관련 클래스 파일을 저장하는 것이 매우 필요합니다.
소위: 중복된 기능을 추가하지만 유지 관리가 쉽다는 장점이 있습니다.
개인적으로는 Java 언어의 디렉토리 구조에 따라 PHP 프로그램을 유지 관리하는 것이 예상치 못한 이득을 얻는 것이 더 좋다고 생각합니다.
이제 요약 부분에서 언급했던 성찰이라는 주제에 본격적으로 들어갑니다. 핵심은 ReflectionClass
의 활용에 있다.
<?phprequire './bean/beans.php'; // Person 在beans.php文件中声明$protype = new ReflectionClass("Person"); // 可以添加一个参数,来进行过滤操作。如只获取public类型的属性 $properties = $protype->getProperties(); // 反射获取到类的属性信息 foreach ($properties as $property) { echo $property."<br />"; }
Java에 비해 PHP에서는 private
속성을 얻는 것이 더 쉽습니다.
<?php require './bean/beans.php'; $protype = new ReflectionClass("Person"); $methods = $protype->getMethods(); foreach ($methods as $method) { echo $method->getName()."<br />"; }
추가로 필터 조건을 추가할 수 있습니다. getMethods 메소드 Tianji에 필터 매개변수를 제공하기만 하면 됩니다.
filter过滤结果为仅包含某些属性的方法。默认不过滤。 ReflectionMethod::IS_STATIC、 ReflectionMethod::IS_PUBLIC、 ReflectionMethod::IS_PROTECTED、 ReflectionMethod::IS_PRIVATE、 ReflectionMethod::IS_ABSTRACT、 ReflectionMethod::IS_FINAL 的任意组合。
注释信息,这里就以文档信息为例。
<?phprequire './bean/beans.php'; $protype = new ReflectionClass ( "Person" ); $properties = $protype->getProperties (); // 反射获取到类的属性信息 foreach ( $properties as $property ) { echo $property . ":"; $doc = $property->getDocComment (); echo " " . $doc . "<br />"; e cho "--------------------------------------------------------" . "<br />"; }$methods = $protype->getMethods(); foreach ($methods as $method) { echo $method->getName()."<br />"; $doc = $method->getDocComment (); echo " " . $doc . "<br />"; echo "--------------------------------------------------------" . "<br />"; }
<?phprequire './bean/beans.php'; $protype = new ReflectionClass ( "Person" );// 模拟数据库中获取到的值,以关联数组的形式抛出 $values = array( "name"=>"郭璞", "age"=> 21, "address"=>"辽宁省大连市");// 开始实例化 $instance = $protype->newInstanceArgs($values); print_r($instance);// var_dump($instance); echo $instance->getName();
<?phprequire './bean/beans.php';$classprotype = new ReflectionClass("Grade");$class = $classprotype->newInstanceArgs(array("name"=>"大三")); var_dump($class);echo $class->getName();
$instance->getName(); // 执行Person 里的方法getName// 或者: $method = $class->getmethod('getName'); // 获取Person 类中的getName方法$method->invoke($instance); // 执行getName 方法// 或者:$method = $class->getmethod('setName'); // 获取Person 类中的setName方法$method->invokeArgs($instance, array('snsgou.com'));
回顾一下,本次试验演示了PHP中的反射技术,对比分析了Java语言的反射技术的实现。也只能说各有利弊吧。
在Java中,反射技术是编写框架的基础。虽然在PHP中反射技术不是特别的重要,而且用的时候约束也比较多,稍显鸡肋。但是比葫芦画瓢的话,还是可以做出一些有用的小工具的。
위 내용은 PHP 반사 기술의 자세한 코드 예제(그림 및 텍스트)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!