解决方法是将$ _POST变量指定为函数中的参数默认值

时间:2012-06-27 05:10:35

标签: php

我正在开发一个可通过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(),我认为这有点无效(如果函数重命名则更多{{} 1}}) - 它基本上与写assign_raw_post_var_to_param()一样明确。

问题......

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

1 个答案:

答案 0 :(得分:1)

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

如果你不知道参数的顺序并且需要计算出运行时间,你可以使用reflections来完成。


按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
        )

)