0

我正在开发一个可通过 Web 访问的 API,并且一直在尝试找出将 $_POST / $_GET 变量分配为函数参数的最简洁和最有效的方法。我知道变量不能用作参数默认值,所以目标是 DRY(不要重复自己);使 API 函数既可以在应用程序内部使用,也可以通过外部接口使用。

背景:

1)目前,API 函数被组织成具有公共静态方法的类。当发出远程请求时,请求的类和方法(安全地)确定,如果类+方法组合有效,则使用call_user_func("$class::$method").

2)最终调用的代码class::method()是故意愚蠢的——它不知道也不关心函数的参数。由于无法在缺少参数的情况下调用函数,因此 API 中的所有函数必须要么没有参数,要么没有参数而没有默认值。我认为在这里要做的最干净的事情是使用默认值定义所需的参数,null并让函数在内部处理 $_POST 变量的分配:

public static function complete($id = null, $offset = 0, $limit = 50){ ... }

3)在内部,API 方法返回常规 PHP 变量,然后外部接口用json_encode().

我现在拥有的东西:

起初我尝试了一些怪物,每个函数需要 10 或更多额外的行,但我已将其缩减为可重用的函数。我看了看,extract()但它对我的目的来说不够精确或安全。

function assign($postIndex, &$target, $require = true){
    // Any code assigned parameter overrides remote values
    if($target != null && $require == true)
        return;

    // Force parameter requirement if specified
    if($require && !isset($_POST[$postIndex]))
        throw new MissingParameterException();

    // Assign to referenced variable if it's set
    if(isset($_POST[$postIndex]))
        $target = $_POST[$postIndex];
}

像这样使用:

public static function delete($id = null){
    assign('id', $id);

    ...

}

请注意,我知道潜在的注入漏洞;无论来源如何,所有 API 函数都会清理其参数。我也知道其他使用此方法为 API 编写函数的人可能会假设参数是安全的,但是由于assign()必须显式调用,我认为这有点无效(如果函数被重命名则更是如此 assign_raw_post_var_to_param()) - 它本质上与写作$name = $_POST['name'];

问题...

有没有更好的方法将 $_POST / $_GET 变量分配给函数参数,允许通过外部接口和代码透明地调用函数?如果是这样,您将如何实施?

4

1 回答 1

1

我认为你需要call_user_func_array. 使用它你可以指定一个参数数组,这样你就可以保留简单的方法签名。

如果您不知道参数的顺序并且需要确定是否运行时,您可以使用反射来完成。


由 OP 编辑​​:

反射是一个很好的解决方案。例如:

class TestClass {
    public static function some_method($name, $email, $bannana){

    }
}

$reflection = new ReflectionMethod('TestClass', 'some_method');
$params = $reflection->getParameters();

$params现在看起来像这样:

Array
(
    [0] => ReflectionParameter Object
        (
            [name] => name
        )

    [1] => ReflectionParameter Object
        (
            [name] => email
        )

    [2] => ReflectionParameter Object
        (
            [name] => bannana
        )

)
于 2012-06-27T09:11:06.810 回答