1

I have two variables:

$a = 'some_class';
$b = 'some_method';

What I want to do is something like this (the method is static):

$a::$b;

Is it possible? I've tried the reflection class, but I can't call static methods...

4 Answers 4

3

This should do it

call_user_func(array($a, $b));
Sign up to request clarification or add additional context in comments.

Comments

2

How to invoke the static method, 3 options

You have a few options:

Code

<?PHP

    class test {
        static function doThis($arg) {
            echo '<br>hello world '.$arg;
        }
    }

    $class='test';
    $method='doThis';
    $arg='stack';

    //just call
    $class::$method($arg);

    //with function
    call_user_func(array($class, $method), $arg);

    //ugly but possible
    $command=$class.'::'.$method.'("'.$arg.'");';
    eval($command);

Output

    hello world stack
    hello world stack
    hello world stack

What happens when you call it with those options

Code with a backtrace so you can see what happens under the hood in PHP:

Code

<?PHP

class test {
    static function doThis($arg) {
        echo 'hello world with argument: '.$arg.PHP_EOL;
        print_R(debug_backtrace());
    }
}

function runTest() {

    $class='test';
    $method='doThis';
    $arg='stack';



    //just call
    $class::$method($arg);

    //with function
    call_user_func(array($class, $method), $arg);

    //ugly but possible
    $command=$class.'::'.$method.'("'.$arg.'");';
    eval($command);

}

echo '<pre>';
runTest();

Output

$class::$method($arg);

hello world with argument: stack
Array
(
    [0] => Array
        (
            [file] => folder/test.php
            [line] => 19
            [function] => doThis
            [class] => test
            [type] => ::
            [args] => Array
                (
                    [0] => stack
                )

        )

    [1] => Array
        (
            [file] => folder/test.php
            [line] => 31
            [function] => runTest
            [args] => Array
                (
                )

        )

)

call_user_func(array($class, $method), $arg);

hello world with argument: stack
Array
(
    [0] => Array
        (
            [function] => doThis
            [class] => test
            [type] => ::
            [args] => Array
                (
                    [0] => stack
                )

        )

    [1] => Array
        (
            [file] => folder/test.php
            [line] => 22
            [function] => call_user_func
            [args] => Array
                (
                    [0] => Array
                        (
                            [0] => test
                            [1] => doThis
                        )

                    [1] => stack
                )

        )

    [2] => Array
        (
            [file] => folder/test.php
            [line] => 31
            [function] => runTest
            [args] => Array
                (
                )

        )

)

eval($command);

hello world with argument: stack
Array
(
    [0] => Array
        (
            [file] => folder/test.php(26) : eval()d code
            [line] => 1
            [function] => doThis
            [class] => test
            [type] => ::
            [args] => Array
                (
                    [0] => stack
                )

        )

    [1] => Array
        (
            [file] => folder/test.php
            [line] => 26
            [function] => eval
        )

    [2] => Array
        (
            [file] => folder/test.php
            [line] => 31
            [function] => runTest
            [args] => Array
                (
                )

        )

)

As you can see first way has no step in between which is being registered, it directly makes the call while the other 2 options act by themselves as a function and make the call from themselves.

In practice not a lot of difference but it might make sense when optimizing such a process.

5 Comments

Is there any advantage to these options? I mean, excluding the eval option. Is call_user_func better than :: or vice versa? Or is this just a preference thing?
All work so for functionality we don't make a difference. Then the eval() one, just don't use. Reasons enough. Then why one could use call_user_func(), it allows for a flexible amount of arguments. That is quite nice for some uses but in your case not very useful. In my opinion it comes back to style. Main difference is that both eval and call_user_func are a separate step in your program trace while $class::$method just calls it. Uploaded new code with the backtrace so you can see the main difference of what happens.
So it looks like $a::$b() is a bit more efficient than call_user_func when calling the same class, but only fractionally.
I expect, but did not benchmark, the performance. For readability I would suggest $a::$b() if really needed. To put that more specific: In general it should not be needed to call flexible classnames but there are some situations where it is needed. I would put it together in one method and add enough checks and debug tricks to it so you can simply debug which class and method are called with which argument. It is tricky because you cannot find all calls to the method with a search for example because it is dynamically generated.
None of these options allow overriding accessibility the way it can be done with $reflectionMethod->setAccessible(true); $reflectionMethod->invoke($obj);. The asker tagged their question with "reflection".
2

you have to add () to the end of the var for it to turn into a method. $a::$b() not $a::$b;

PHP

<?php

$a = 'some_class';
$b = 'some_method';
$c = 'double';

echo $a::$b();
echo "<br>";
echo $a::$c(15);


class some_class{

    public static function some_method(){
        return "static return";
    }

    public static function double($int){
        return $int*2;
    }
}

?>

Output

static return
30

Comments

1

This will work for you: $a::$b();

Example:

<?php

class A {
    public static function b()
    {
        echo 'Done!', PHP_EOL;
    }
}

$class  = 'A';
$method = 'b';

$class::$method(); // Shows:  Done!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.