Asked  7 Months ago    Answers:  5   Viewed   31 times

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?

 Answers

64

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;
Wednesday, March 31, 2021
 
tompave
answered 7 Months ago
70

Good question. Consider this example

function foo($foo = 'foo', $bar) {}

For the $foo parameter, isDefaultValueAvailable() would understandably return true however isOptional() would return false as the next parameter ($bar) has no default value and is therefore not optional. To support the non-optional $bar parameter, $foo must itself be non-optional.

Hope this makes sense ;)

I've noted that behaviour differs across PHP versions. 5.5 returns the above whereas 5.4 says parameter 1 is both not optional and has no default value.

  • PHP 5.4 - https://eval.in/154641
  • PHP 5.5 - https://eval.in/154642
Wednesday, March 31, 2021
 
Raef
answered 7 Months ago
60

There is no way to get the names of the parameters of a method or a function.

The reason for this is because the names are not really important for someone calling a method or a function. What matters is the types of the parameters and their order.

A Function type denotes the set of all functions with the same parameter and result types. The type of 2 functions having the same parameter and result types is identical regardless of the names of the parameters. The following code prints true:

func f1(a int) {}
func f2(b int) {}

fmt.Println(reflect.TypeOf(f1) == reflect.TypeOf(f2))

It is even possible to create a function or method where you don't even give names to the parameters (within a list of parameters or results, the names must either all be present or all be absent). This is valid code:

func NamelessParams(int, string) {
    fmt.Println("NamelessParams called")
}

For details and examples, see Is unnamed arguments a thing in Go?

If you want to create some kind of framework where you call functions passing values to "named" parameters (e.g. mapping incoming API params to Go function/method params), you may use a struct because using the reflect package you can get the named fields (e.g. Value.FieldByName() and Type.FieldByName()), or you may use a map. See this related question: Initialize function fields

Here is a relevant discussion on the golang-nuts mailing list.

Saturday, June 19, 2021
 
iftheshoefritz
answered 4 Months ago
81

You should be able to call ReflectionMethod::getDeclaringClass() to get the class declaring the method. Then a call to ReflectionClass::getParentClass() to get the parent class. Lastly a call to ReflectionClass::hasMethod() will tell you if the method was declared in the parent class.

Example:

<?php
class Foo {
    function abc() {}
}

class Bar extends Foo {
    function abc() {}
    function def() {}
}


$bar = new Bar();

$meth = new ReflectionMethod($bar, "abc");
$cls = $meth->getDeclaringClass();
$prnt = $cls->getParentClass();

if ($cls->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Barn";
}
if ($prnt->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Foon";
}

$meth = new ReflectionMethod($bar, "def");
$cls = $meth->getDeclaringClass();
$prnt = $cls->getParentClass();

if ($cls->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Barn";
}
if ($prnt->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Foon";
}
Friday, July 30, 2021
 
sharjeel
answered 3 Months ago
46

Use the class ReflectionClass:

On Codepad.org: http://codepad.org/VEi5erFw
<?php

class MyClass
{
  public function func1(){}
  public static function func2(){}
}

$reflection = new ReflectionClass('MyClass');
var_dump( $reflection->getMethods(ReflectionMethod::IS_STATIC) );

This will output all static functions.

Or if you want to determine whether a given function is static you can use the ReflectionMethod class:

On Codepad.org: http://codepad.org/2YXE7NJb

<?php

class MyClass
{
  public function func1(){}
  public static function func2(){}
}

$reflection = new ReflectionClass('MyClass');

$func1 = $reflection->getMethod('func1');
$func2 = $reflection->getMethod('func2');

var_dump($func1->isStatic());
var_dump($func2->isStatic());
Monday, August 16, 2021
 
BenOfTheNorth
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :