I’m working on a web-accessible API and have been trying to figure out the tidiest and most efficient way of assigning $_POST / $_GET variables as function parameters. I know variables can’t be used as parameter defaults, so the goal is DRY (Don’t Repeat Yourself); to have API functions usable from both within the application and through the external interface.
Background:
1) Currently, API functions are organised into classes with public static methods. When a remote request is made, the requested class and method are (safely) determined, and if the class+method combination is valid, it is called using call_user_func("$class::$method").
2) The the code that ends up calling class::method() is intentionally dumb – it doesn’t know or care about the parameters a function takes. As functions cannot be called with missing parameters, all functions in the API must either have no parameters, or no parameters without defaults. I figured the cleanest thing to do here was to have required parameters defined with a default of null and let functions handle the assignment of $_POST variables internally:
public static function complete($id = null, $offset = 0, $limit = 50){ ... }
3) Internally, API methods return regular PHP variables, then the external interface encodes this value with json_encode().
What I have now that works:
I tried a few monstrosities at first that required 10 or more extra lines per function, but I’ve whittled it down to a reusable function. I had a look at extract() but it wasn’t precise or safe enough for my purpose.
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];
}
Used like:
public static function delete($id = null){
assign('id', $id);
...
}
Please note that I am aware of the potential injection vulnerability; all API functions clean their parameters regardless of origin. I am also aware that other people writing functions for an API using this method might assume parameters are safe, however as assign() has to be explicitly called, I think this is somewhat void (more so if the function was renamed assign_raw_post_var_to_param()) – it’s essentially as explicit as writing $name = $_POST['name'];.
The question…
Is there a better way to assign $_POST / $_GET variables to function parameters that allows functions to be called both through an external interface and from code transparently? How would you implement it if so?
I think you need
call_user_func_array. Using that you can specify an array of parameters so you can just keep plain method signatures.If you don’t know the order of parameters and need to figure if out run-time, you could do so using reflections.
Edit by OP:
Reflection is an excellent solution. For example:
$paramsnow looks like this: