PHP反射-将方法参数类型获取为字符串

PHP反射-将方法参数类型获取为字符串,php,reflection,Php,Reflection,我试图使用PHP反射根据控制器方法中的参数类型自动动态加载模型的类文件。下面是一个示例控制器方法 <?php class ExampleController { public function PostMaterial(SteelSlugModel $model) { //etc... } } 这是可行的,输出将是“SteelSlugModel”,正如预期的那样。但是,模型的类文件可能尚未加载,使用getClass()需要定义该类——我这样做的部

我试图使用PHP反射根据控制器方法中的参数类型自动动态加载模型的类文件。下面是一个示例控制器方法

<?php

class ExampleController
{
    public function PostMaterial(SteelSlugModel $model)
    {
        //etc...
    }
}
这是可行的,输出将是“SteelSlugModel”,正如预期的那样。但是,模型的类文件可能尚未加载,使用getClass()需要定义该类——我这样做的部分原因是自动加载控制器操作可能需要的任何模型


有没有一种方法可以在不必首先加载类文件的情况下获取参数类型的名称?

我认为唯一的方法是导出并操作结果字符串:

$refParam = new ReflectionParameter(array('Foo', 'Bar'), 0);

$export = ReflectionParameter::export(
   array(
      $refParam->getDeclaringClass()->name, 
      $refParam->getDeclaringFunction()->name
   ), 
   $refParam->name, 
   true
);

$type = preg_replace('/.*?(\w+)\s+\$'.$refParam->name.'.*/', '\\1', $export);
echo $type;

我也有类似的问题,当类未加载时,在反射参数上检查getClass。我制作了一个包装器函数,从netcoder制作的示例中获取类名。问题是,如果netcoder代码是数组或不是类->函数($test){},它将返回反射参数的to string方法,则netcoder代码不起作用

在我解决这个问题的方法下面,我使用try-catch,因为我的代码在某些时候需要类。所以,如果我下次请求它,让类工作并且不抛出异常

/**
 * Because it could be that reflection parameter ->getClass() will try to load an class that isnt included yet
 * It could thrown an Exception, the way to find out what the class name is by parsing the reflection parameter
 * God knows why they didn't add getClassName() on reflection parameter.
 * @param ReflectionParameter $reflectionParameter
 * @return string Class Name
 */
public function ResolveParameterClassName(ReflectionParameter $reflectionParameter)
{
    $className = null;

    try
    {
                 // first try it on the normal way if the class is loaded then everything should go ok
        $className = $reflectionParameter->getClass()->name;

    }
    // if the class isnt loaded it throws an exception and try to resolve it the ugly way
    catch (Exception $exception)
    {
        if ($reflectionParameter->isArray())
        {
            return null;
        }

        $reflectionString = $reflectionParameter->__toString();
        $searchPattern = '/^Parameter \#' . $reflectionParameter->getPosition() . ' \[ \<required\> ([A-Za-z]+) \$' . $reflectionParameter->getName() . ' \]$/';

        $matchResult = preg_match($searchPattern, $reflectionString, $matches);

        if (!$matchResult)
        {
            return null;
        }

        $className = array_pop($matches);
    }

    return $className;
}
/**
*因为反射参数->getClass()可能会尝试加载尚未包含的类
*它可能引发异常,这是通过解析反射参数来确定类名的方法
*天知道他们为什么不在反射参数上添加getClassName()。
*@param ReflectionParameter$ReflectionParameter
*@返回字符串类名称
*/
公共函数ResolveParameterClassName(ReflectionParameter$ReflectionParameter)
{
$className=null;
尝试
{
//首先以正常方式尝试,如果类已加载,那么一切都应该正常
$className=$reflectionParameter->getClass()->name;
}
//如果未加载该类,它将抛出一个异常,并尝试以丑陋的方式解决它
捕获(异常$Exception)
{
如果($reflectionParameter->isArray())
{
返回null;
}
$reflectionString=$reflectionParameter->_-toString();
$searchPattern='/^Parameter\\\'.$reflectionParameter->getPosition().\[\([A-Za-z]+)\$”.$reflectionParameter->getName().\]$/;
$matchResult=preg_match($searchPattern,$reflectionString,$matches);
如果(!$matchResult)
{
返回null;
}
$className=array\u pop($matches);
}
返回$className;
}

您可以使用Zend Framework 2

$method_reflection = new \Zend\Code\Reflection\MethodReflection( 'class', 'method' );

foreach( $method_reflection->getParameters() as $reflection_parameter )
{
  $type = $reflection_parameter->getType();
}

我想这就是你要找的:

class MyClass {

    function __construct(AnotherClass $requiredParameter, YetAnotherClass $optionalParameter = null) {
    }

}

$reflector = new ReflectionClass("MyClass");

foreach ($reflector->getConstructor()->getParameters() as $param) {
    // param name
    $param->name;

    // param type hint (or null, if not specified).
    $param->getClass()->name;

    // finds out if the param is required or optional
    $param->isOptional();
}

自PHP7.0以来,可以使用
getType
方法

class Foo{}
类条{}
类MyClass
{
公共功能baz(Foo$Foo,Bar$Bar){}
}
$class=新的ReflectionClass('MyClass');
$method=$class->getMethod('baz');
$params=$method->getParameters();
瓦鲁垃圾场(
'Foo'==(字符串)$params[0]->getType()
);

这是一个比中的正则表达式更好的正则表达式。即使参数是可选的,它也会工作

preg_match('~>\s+([a-z]+)\s+~', (string)$ReflectionParameter, $result);
$type = $result[1];

什么是
$p
?你的意思是
$param
?除非反射类的文档中缺少一条重要信息,否则我不认为你可以在不加载类的情况下获得暗示类型。@simshaun:不。该类需要加载,否则
getClass
抛出
ReflectionException
@netcoder,我知道关于getClass的这一点。我基本上是说“除非有另一种方法来获取我不知道或在文档中找不到的暗示类型”@Rafe-yes,$p应该是$param。这在代码中得到了修复。虽然我真的希望可以避免解析字符串来完成这项工作,但这是可行的。干得好。这仍然是唯一的方法吗?必须依靠导出方法的非标准输出格式是粗略的!函数
getType
不存在于enymore中,它现在被称为
getClass
。此函数不需要使用preg\u match浪费时间。(如果参数没有类提示,它也会失败)。请参阅我更新的示例:使用当前反射API,这是最好的解决方案,应该是公认的答案。
getClass()
当方法签名包含“字符串”或“数组”之类的类型提示时,会导致错误。在PHP<7上无法检测到类型“string”。
preg_match('~>\s+([a-z]+)\s+~', (string)$ReflectionParameter, $result);
$type = $result[1];