1

いくつかのメソッドを含むカスタムPHPクラスがあります。この方法でクラスメソッドを呼び出すことは可能です:

<?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
?>

私の実際のアプリケーションはもっと複雑ですが、ここでは、主要なアイデアを得るためにこの簡単な例を示します。たぶん私はここでeval関数を使うことができますか?

4

4 に答える 4

4

ほとんどの状況でであるため、eval()は使用しないでください。

単純な文字列連結は次のことに役立ちます。

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

また、ユーザー入力を確認する必要があります。

$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));
于 2012-11-11T22:00:55.540 に答える
3

もちろん、これを取ります:

$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));

メソッド名を呼び出す前に、メソッド名全体を連結します。

アップデート:

ユーザー入力に基づいてメソッドを直接呼び出すことは決して良い考えではありません。以前にメソッド名の検証を行うことを検討してください。

于 2012-11-11T22:01:01.127 に答える
1

また、phpマジックメソッドを利用することもできます。つまり、とと__call()組み合わせて使用​​することもできます。call_user_func_array()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');
    }

    // ...
}

安全上の理由から、次のような他のメソッドの呼び出しを禁止するラッパーを作成することをお勧めします。

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

そしてそれを次のように使用します:

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

または、メソッドを作成してからメソッドexecuteに追加することもできます。someClassGetCallWrapper()

このようにして、機能をオブジェクト(クラス)に適切にカプセル化し、毎回コピーする必要がなくなります(これは、特権チェックなどの制限を適用する必要がある場合に便利です)。

于 2012-11-11T22:02:14.673 に答える
0

関数として変数を使用することが可能です。たとえば、関数foo()がある場合は、変数$funcを使用して呼び出すことができます。次に例を示します。

function foo() {
    echo "foo";
}

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

だからそれは次のように動作するはずです$obj->$func();

于 2012-11-11T22:05:58.313 に答える