I'm looking for the best approach / pattern / idiom for handling a variable-length argument for the mysqli bind_param
method.
I've created a variadic function in PHP that is similar to mysqli_stmt::bind_param
. Thus, the first required argument expects an string, the other arguments are optional, but the string length of the first argument must be equal to the amount of optional arguments.
The function definition:
function bind_param_test($types, ...$args){
$typesArr = str_split($types);
foreach($args as $i => $n) {
switch ($typesArr[$i]) {
case 'd':
echo "Decimal: " . $n . '<br>';
break;
case 's':
echo "String: " . $n . '<br>';
break;
default:
break;
}
}
}
Now I'm trying to use it.
// ------------- CASE 1 ---------------------------
// In this case I have 5 arguments. So I can do this:
$a = 10;
$b = 20;
$c = 'hello';
$d = 'cheese';
$e = 500;
if($a && $b && $c && $d && $e){
bind_param_test('ddssd', $a, $b, $c, $d, $e);
}
/* OUTPUT:
Decimal: 10
Decimal: 20
String: hello
String: cheese
Decimal: 500
*/
echo '<hr>';
Please see case 2 and 3 below.
// ------------- CASE 2 ---------------------------
// I'm using 4 variables
$e = null;
if($a && $b && $c && $d && !$e){
bind_param_test('ddss', $a, $b, $c, $d);
}
/* OUTPUT:
Decimal: 10
Decimal: 20
String: hello
String: cheese
*/
echo '<hr>';
// ------------- CASE 3 ---------------------------
// 3 variables
$d = null;
$e = null;
if($a && $b && $c && !$d && !$e){
bind_param_test('dds', $a, $b, $c);
}
/* OUTPUT:
Decimal: 10
Decimal: 20
String: hello */
echo '<hr>';
Case 2 and 3 are hard-coded, and thus not DRY. I want to make it DRY in case 4. Please see case 4.
Case 4: pattern to handle mysqli bind_param by array
// ------------- CASE 4 ---------------------------
// I want to have a more generic approach.
$argumentList = array(
'a' => 10,
'b' => 20,
'c' => null,
'd' => null,
'e' => null,
);
$argumentList = array_filter($argumentList);
$actionStr = '';
foreach($argumentList as $k => $v){
if(is_numeric($v)){
$actionStr .= 'd';
}
if(is_string($v)){
$actionStr .= 's';
}
}
$varList = array_values($argumentList);
$param_arr = array();
$param_arr[] = $actionStr;
$param_arr = (array_merge($param_arr, $varList));
call_user_func_array('bind_param_test', $param_arr);
/* OUTPUT:
Decimal: 10
Decimal: 20 */
The question: can you find a better approaches then case 4? I'm asking because I think that case 4 is mysterious. I'm afraid that it might astonish other developers.