Jarrod Nettles
Jarrod Nettles

Reputation: 6293

PHP Reflection - Get Method Parameter Type As String

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

Answers (6)

powtac
powtac

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

masakielastic
masakielastic

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

Mat&#250;š Duchoň
Mat&#250;š Duchoň

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

neofraktal
neofraktal

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

daanl
daanl

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

netcoder
netcoder

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

Related Questions