Reputation: 6293
I'm trying to use PHP reflection to dynamically load the class files of models automatically based upon the type of parameter that is in the controller method. Here's an example controller method.
<?php
class ExampleController
{
public function PostMaterial(SteelSlugModel $model)
{
//etc...
}
}
Here's what I have so far.
//Target the first parameter, as an example
$param = new ReflectionParameter(array('ExampleController', 'PostMaterial'), 0);
//Echo the type of the parameter
echo $param->getClass()->name;
This works, and the output would be 'SteelSlugModel', as expected. However, there is the possibility that the class file of the model may not be loaded yet, and using getClass() requires that the class be defined - part of why I'm doing this is to autoload any models that a controller action may require.
Is there a way to get the name of the parameter type without having to load the class file first?
Upvotes: 14
Views: 13527
Reputation: 41080
This is a better regular expression than the one from that answer. It will work even when the parameter is optional.
preg_match('~>\s+([a-z]+)\s+~', (string)$ReflectionParameter, $result);
$type = $result[1];
Upvotes: 0
Reputation: 4640
getType
method can be used since PHP 7.0.
class Foo {}
class Bar {}
class MyClass
{
public function baz(Foo $foo, Bar $bar) {}
}
$class = new ReflectionClass('MyClass');
$method = $class->getMethod('baz');
$params = $method->getParameters();
var_dump(
'Foo' === (string) $params[0]->getType()
);
Upvotes: 5
Reputation: 151
I supposed this is what you are looking for:
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();
}
Upvotes: 15
Reputation: 41
You could use Zend Framework 2.
$method_reflection = new \Zend\Code\Reflection\MethodReflection( 'class', 'method' );
foreach( $method_reflection->getParameters() as $reflection_parameter )
{
$type = $reflection_parameter->getType();
}
Upvotes: 4
Reputation: 44
I had similar problem, when checking getClass on reflection parameter when a class was not loaded. I made a wrapper function to get the class name from example netcoder made. Problem was that netcoder code didnt work if it was an array or not an class -> function($test) {} it would return the to string method for the reflection parameter.
Below the way how i solved it, im using try catch because my code requires at some point the class. So if i request it the next time, get class works and doesnt throw an exception.
/**
* 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;
}
Upvotes: 1
Reputation: 67745
I think the only way is to export
and manipulate the result string:
$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;
Upvotes: 12