12
votes

Réflexion PHP - Type de paramètre de méthode en tant que chaîne

J'essaie d'utiliser la réflexion PHP pour charger automatiquement les fichiers de classe de modèles en fonction du type de paramètre dans la méthode du contrôleur. Voici un exemple de méthode de contrôleur.

//Target the first parameter, as an example
$param = new ReflectionParameter(array('ExampleController', 'PostMaterial'), 0);

//Echo the type of the parameter
echo $param->getClass()->name;


5 commentaires

Qu'est-ce que $ p ? Voulez-vous dire $ param ?


Sauf si la classe de réflexion ne manque pas d'informations vitales dans ses documents, je ne pense pas que vous puissiez obtenir le type pointé sans avoir la classe chargée.


@simshaun: Non. La classe doit être chargée, sinon getclass jette un réflectionException .


@netcoder, je sais que sur GetClass. J'avais essentiellement dire "sauf s'il y a une autre façon d'obtenir le type pointu que je ne suis pas au courant ou ne pouvait pas trouver dans les documents"


@Rafe - Oui, $ p était censé être $ param. Fixé dans le code.


6 Réponses :


12
votes

Je pense que le seul moyen est de exporter et de manipuler la chaîne de résultat: xxx


2 commentaires

Cela fonctionne, bien que je souhaite vraiment que je puisse éviter d'analyser une chaîne pour le faire. Bon travail.


Est-ce toujours le seul moyen de faire cela? Devoir s'appuyer sur le format de sortie non standard de la méthode d'exportation est Sketchy!



1
votes

J'ai eu un problème similaire, lors de la vérification GetClass sur le paramètre de réflexion lorsqu'une classe n'a pas été chargée. J'ai fait une fonction d'emballage pour obtenir le nom de la classe à partir d'exemple Netcoder. Problème était que le code de NetCoder n'a pas fonctionné s'il s'agissait d'une matrice ou non d'une fonction de classe -> fonction ($ test) {}, il renvoie la méthode de la chaîne pour le paramètre de réflexion.

Situé à la manière dont je l'ai résolu, im en utilisant Essayez d'attraper parce que mon code nécessite à un moment donné de la classe. Donc, si je le demande la prochaine fois, obtenez des travaux de classe et ne jetez pas une exception. P>

/**
 * 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;
}


1 commentaires

Cette fonction n'a pas besoin de perdre du temps à l'utilisation de Preg_Match. (Il échoue également du paramètre n'a pas d'indice de classe). Voir mon exemple mis à jour: gist.github.com/xeoncross/4723819



4
votes

Vous pouvez utiliser Zend Framework 2.

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

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


1 commentaires

La fonction gettype n'est pas existante enymore, elle est maintenant appelée getclass .



13
votes

Je suppose que c'est ce que vous recherchez:

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();
}


2 commentaires

Utilisation de l'API de réflexion actuelle C'est la meilleure solution et devrait être la réponse acceptée.


GetClass () mène à une erreur lors d'une signature de méthode contenant le type d'affichage comme "chaîne" ou "tableau". Et tapez "string" ne peut pas être détecté sur php <7.



2
votes

gettype code> peut être utilisé depuis 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()
);


0 commentaires

0
votes

C'est une meilleure expression régulière que celle de cette réponse . Cela fonctionnera même lorsque le paramètre est facultatif.

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


0 commentaires