正文
本章包括以下内容:
- 包(package):将代码按逻辑分类打包
- 命名空间:从PHP5.3开始,可以将代码元素封装在独立的单元中
- 包含路径:为你的类库代码设置访问路径
- 类函数和对象函数:测试对象、类、属性和方法的函数
- 反射API(ReflectionAPI):一组强大的内置类,可以在代码运行时访问类信息
反射API
反射API的部分类:
- Reflection 为类的摘要信息提供静态函数export()
- ReflectionClass 类信息和工具
- ReflectionMethod 类方法信息和工具
- ReflectionParameter 方法参数信息
- ReflectionProperty 类属性信息
- ReflectionFunction 函数信息和工具
- ReflectionExtension PHP拓展信息
- ReflectionException 错误类
$prodclass = new \ReflectionClass('CdProduct');
\Reflection::export($prodclass);
获取源码的类:
class ReflectionUtil
{
// 获取类源码
public static function getClassSource(\ReflectionClass $class): string
{
$path = $class->getFileName();
$lines = @file($path);
$from = $class->getStartLine();
$to = $class->getEndLine();
$len = $to - $from + 1;
return implode(array_slice($lines, $from - 1, $len));
}
// 获取方法源码
public static function getMethodSource(\ReflectionMethod $method): string
{
$path = $method->getFileName();
$lines = @file($path);
$from = $method->getStartLine();
$to = $method->getEndLine();
$len = $to - $from + 1;
return implode(array_slice($lines, $from - 1, $len));
}
}
获取类详情信息的类:
class ClassInfo
{
// 获取类详情
public static function getData(\ReflectionClass $class)
{
$details = "";
$name = $class->getName();
if ($class->isUserDefined()) {
$details .= "$name is user defined\n";
}
if ($class->isInternal()) {
$details .= "$name is built-in\n";
}
if ($class->isInterface()) {
$details .= "$name is interface\n";
}
if ($class->isAbstract()) {
$details .= "$name is an abstract class\n";
}
if ($class->isFinal()) {
$details .= "$name is a final class\n";
}
if ($class->isInstantiable()) {
$details .= "$name can be instantiated\n";
} else {
$details .= "$name can not be instantiated\n";
}
if ($class->isCloneable()) {
$details .= "$name can be cloned\n";
} else {
$details .= "$name can not be cloned\n";
}
return $details;
}
// 获取方法详情
public static function methodData(\ReflectionMethod $method)
{
$details = "";
$name = $method->getName();
if ($method->isUserDefined()) {
$details .= "$name is user defined\n";
}
if ($method->isInternal()) {
$details .= "$name is built-in\n";
}
if ($method->isAbstract()) {
$details .= "$name is abstract\n";
}
if ($method->isPublic()) {
$details .= "$name is public\n";
}
if ($method->isProtected()) {
$details .= "$name is protected\n";
}
if ($method->isPrivate()) {
$details .= "$name is private\n";
}
if ($method->isStatic()) {
$details .= "$name is static\n";
}
if ($method->isFinal()) {
$details .= "$name is final\n";
}
if ($method->isConstructor()) {
$details .= "$name is the constructor\n";
}
if ($method->returnsReference()) {
$details .= "$name returns a reference (as opposed to a value)\n";
}
return $details;
}
// 获取参数详情
public function argData(\ReflectionParameter $arg)
{
$details = "";
$declaringclass = $arg->getDeclaringClass();
$name = $arg->getName();
$class = $arg->getClass();
$position = $arg->getPosition();
$details .= "\$$name has position $position\n";
if (! empty($class)) {
$classname = $class->getName();
$details .= "\$$name must be a $classname object\n";
}
if ($arg->isPassedByReference()) {
$details .= "\$$name is passed by reference\n";
}
if ($arg->isDefaultValueAvailable()) {
$def = $arg->getDefaultValue();
$details .= "\$$name has default: $def\n";
}
if ($arg->allowsNull()) {
$details .= "\$$name can be null\n";
}
return $details;
}
}
实操:
$prodclass = new \ReflectionClass('CdProduct');
print ClassInfo::getData($prodclass);
$methods = $prodclass->getMethods();
foreach ($methods as $method) {
print ClassInfo::methodData($method);
print "\n----\n";
}
$method = $prodclass->getMethod("__construct");
$params = $method->getParameters();
foreach ($params as $param) {
print ClassInfo::argData($param) . "\n";
}
实践类:
class ModuleRunner
{
private $configData = [
"popp\\ch05\\batch08\\PersonModule" => ['person' => 'bob'],
"popp\\ch05\\batch08\\FtpModule" => [
'host' => 'example.com',
'user' => 'anon'
]
];
private $modules = [];
// class ModuleRunner
public function init()
{
$interface = new \ReflectionClass('popp\\ch05\\batch08\\Module');
foreach ($this->configData as $modulename => $params) {
$module_class = new \ReflectionClass($modulename);
if (! $module_class->isSubclassOf($interface)) {
throw new Exception("unknown module type: $modulename");
}
$module = $module_class->newInstance();
foreach ($module_class->getMethods() as $method) {
$this->handleMethod($module, $method, $params);
// we cover handleMethod() in a future listing!
}
array_push($this->modules, $module);
}
}
// class ModuleRunner
public function handleMethod(Module $module, \ReflectionMethod $method, $params)
{
$name = $method->getName();
$args = $method->getParameters();
if (count($args) != 1 || substr($name, 0, 3) != "set" ) {
return false;
}
$property = strtolower(substr($name, 3));
if (! isset($params[$property])) {
return false;
}
$arg_class = $args[0]->getClass();
if (empty($arg_class)) {
$method->invoke($module, $params[$property]);
} else {
$method->invoke(
$module,
$arg_class->newInstance($params[$property])
);
}
}
}
参考资料
《深入PHP 面向对象、模式与实践(第3版)》 https://ibaiyang.github.io/blog/books/深入PHP面向对象模式与实践.pdf