1

I have a custom PHP class with few methods in it. Is is possible to call class method this way:

<?php 
class someClass{
  function someMethod_somename_1(){
    echo 'somename1';       
  }

  function someMethod_somename_2(){
    echo 'somename2';   
  }
}
$obj = new someClass();
$methodName = $_GET['method_name'];
$obj->someMethod_{$methodName}(); //calling method
?>

My real world application is more complex, but here I provide just this simple example to get the main idea. Maybe I can use eval function here?

j0k
  • 22,600
  • 28
  • 79
  • 90
Bounce
  • 2,066
  • 6
  • 34
  • 65

4 Answers4

4

Please don't use eval() because it's evil in most situations.

Simple string concatenation helps you:

$obj->{'someMethod_'.$methodName}();

You should also verify the user input!

$allowedMethodNames = array('someone_2', 'someone_1');
if (!in_array($methodName, $allowedMethodNames)) {
  // ERROR!
}

// Unrestricted access but don't call a non-existing method!
$reflClass = new ReflectionClass($obj);
if (!in_array('someMethod_'.$methodName, $reflClass->getMethods())) {
  // ERROR!
}

// You can also do this
$reflClass = new ReflectionClass($obj);
try {
  $reflClass->getMethod('someMethod_'.$methodName);
}
catch (ReflectionException $e) {
  // ERROR!
}

// You can also do this as others have mentioned
call_user_func(array($obj, 'someMethod_'.$methodName));
ComFreek
  • 29,044
  • 18
  • 104
  • 156
3

Of course, take this:

$obj = new someClass();
$_GET['method_name'] = "somename_2";
$methodName = "someMethod_" . $_GET['method_name'];

//syntax 1
$obj->$methodName(); 

//alternatively, syntax 2
call_user_func(array($obj, $methodName));

Concatenate the whole method name before you call it.

Update:

Directly calling methods based on user input is never a good idea. Consider doing some previous validation of the method name before.

David Müller
  • 5,291
  • 2
  • 29
  • 33
1

You may also take advantage of php magic methods, namely __call() in combination with call_user_func_array() and method_exists():

class someClass{
    public function __call($method, $args) {
         $fullMethod = 'someMethod_' . $method;
         $callback = array( $this, $fullMethod);

         if( method_exists( $this, $fullMethod)){
            return call_user_func_array( $callback, $args);
         }

         throw new Exception('Wrong method');
    }

    // ...
}

For safety purposes you may want to create a wrapper which would prohibit calling other methods, like this:

class CallWrapper {
    protected $_object = null;

    public function __construct($object){
        $this->_object = $object;
    }

    public function __call($method, $args) {
         $fullMethod = 'someMethod_' . $method;
         $callback = array( $this->_object, $fullMethod);

         if( method_exists( $this->_object, $fullMethod)){
            return call_user_func_array( $callback, $args);
         }

         throw new Exception('Wrong method');
    }
}

And use it as:

$call = new CallWrapper( $obj);
$call->{$_GET['method_name']}(...);

Or maybe create execute method and than add to someClass method GetCallWrapper().

This way you'll get functionality well encapsulated into objects (classes) and won't have to copy it every time (this may come in handy if you'll need to apply some restrictions, i.e. privileges checking).

Vyktor
  • 20,559
  • 6
  • 64
  • 96
0

It is possible to use variable as function. For example if you have function foo() you can have some variable $func and call it. Here is example:

function foo() {
    echo "foo";
}

$func = 'foo';
$func();  

So it should work like $obj->$func();

Ales
  • 898
  • 1
  • 7
  • 13