Php mysqli bind_param中可变长度参数列表的最佳实践
我正在寻找处理mysqliPhp mysqli bind_param中可变长度参数列表的最佳实践,php,mysqli,prepared-statement,variadic-functions,Php,Mysqli,Prepared Statement,Variadic Functions,我正在寻找处理mysqlibind_param方法的可变长度参数的最佳方法/模式/习惯用法 我在PHP中创建了一个变量函数,类似于mysqli\u stmt::bind\u param。因此,第一个必需参数需要一个字符串,其他参数是可选的,但第一个参数的字符串长度必须等于可选参数的数量 函数定义: function bind_param_test($types, ...$args){ $typesArr = str_split($types); foreach($args as
bind_param
方法的可变长度参数的最佳方法/模式/习惯用法
我在PHP中创建了一个变量函数,类似于mysqli\u stmt::bind\u param
。因此,第一个必需参数需要一个字符串,其他参数是可选的,但第一个参数的字符串长度必须等于可选参数的数量
函数定义:
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;
}
}
}
问题是:你能找到比案例4更好的方法吗?我这么问是因为我觉得第四个案子很神秘。我担心这可能会让其他开发者大吃一惊 您可以减少处理所有所需类型的数组,并对不允许的类型抛出异常。更现代的PHP支持数组销毁
..$array
和[$var1,$var2]=$array
当我传递一个$actionStr='xyz'
时,您还应该抛出一个异常
此示例根据您的订单是数字的
,是字符串
,它同时处理'123'
和123
,作为数字:
// ------------- CASE 4 ---------------------------
$argumentList = array(
'a' => 'ten',
'b' => 20,
'c' => '0',
'd' => null,
'e' => 0,
// 'e' => false, // throws Exception
// 'f' => [1,2,3], // throws Exception
);
[$argumentList, $actionStr] = array_reduce
(
$argumentList,
function(array $aggr, $v) : array
{
if(null === $v)
return $aggr;
if(is_numeric($v))
{
$aggr[0][] = $v;
$aggr[1] .= 'd';
return $aggr;
}
if(is_string($v))
{
$aggr[0][] = $v;
$aggr[1] .= 's';
return $aggr;
}
throw new InvalidArgumentException('Type ' . gettype($v) . ' not allowed.');
},
[[], '']
);
doSomething($actionStr, ...$argumentList);
如果希望将
'123'
处理为字符串而不是数字,请首先选中是否为字符串。我想回答我自己的问题。我只是想改进这个案子。
这是我的进步
$argumentList = array(
'a' => 10,
'b' => 20,
'c' => null,
'd' => null,
'e' => null,
);
$argumentList = array_filter($argumentList);
$mysqli_param_types = '';
foreach($argumentList as $k => $v){
if(is_numeric($v)){
$actionStr .= 'd';
}
if(is_string($v)){
$actionStr .= 's';
}
}
// instead of array_values() and array_merge()
// its more clear to iterate over argumentList (even if its twice)
$mysqli_reference_params[] =& $actionStr;
foreach($argumentList as &$var) {
$mysqli_reference_params[] =& $var;
}
call_user_func_array('bind_param_test', $mysqli_reference_params);
/* OUTPUT:
Decimal: 10
Decimal: 20 */
好吧,为什么这很重要?这很重要,因为我希望有一个模式能够很好地与bind_param
和可变长度参数列表配合使用
惯用语:mysqli中的可变长度准备语句
处理mysqli中可变长度参数列表并结合准备语句的习惯用法。
这里是一个真正的代码习惯用法
$sql = " SELECT p.`productID`,
p.`productCode`,
p.`productName`,
p.`productDescription`,
p.`productPrice`,
p.`productRating`,
p.`productDateTime`
FROM `products` as p
WHERE `p`.`productID` IS NOT NULL ";
if($searchCode){
$sql .= "AND p.`productCode` = ? ";
}
if($searchName){
$sql .= "AND p.`productName` = ? ";
}
if($searchDescription) {
$sql .= "AND p.`productDescription` = ? ";
}
if($searchPrice) {
$sql .= "AND p.`productPrice` = ? ";
}
if($searchRating) {
$sql .= "AND p.`productRating` = ? ";
}
if($searchDateTime) {
$sql .= "AND p.`productDateTime` = ? ";
}
// Create mysqli_stmt
$statement = $mysqli->prepare($sql);
if ($statement instanceof \mysqli_stmt === false) {
return null;
}
// Handle search variables through bind_param()
$bindParamVarList = array(
'productCode' => $searchCode,
'productName' => $searchName,
'productDescription' => $searchDescription,
'productPrice' => $searchPrice,
'productRating' => $searchRating,
'productDateTime' => $searchDateTime,
);
$bindParamVarList = array_filter($bindParamVarList);
if($bindParamVarList){
$types = '';
foreach($bindParamVarList as &$v){
if(is_numeric($v)){
$types .= 'd';
$v = (float)$v;
continue;
}
if(is_string($v)){
$types .= 's';
continue;
}
}
// call_user_func_array needs references and not values
$mysqli_reference_params = array();
$mysqli_reference_params[] =& $types;
foreach($bindParamVarList as &$bindParamVar) {
$mysqli_reference_params[] =& $bindParamVar;
}
call_user_func_array(array($statement, 'bind_param'), $mysqli_reference_params);
}
$statement->execute();
$statement->store_result();
$amount = $statement->num_rows;
$statement->bind_result($productID,
$productCode,
$productName,
$productDescription,
$productPrice,
$productRating,
$productDateTime
);
$products = array();
$productsSet = array();
while($statement->fetch()){
$product = array();
$product['productID'] = $productID;
$product['productCode'] = $productCode;
$product['productName'] = $productName;
$product['productDescription'] = $productDescription;
$product['productPrice'] = $productPrice;
$product['productRating'] = $productRating;
$product['productDateTime'] = $productDateTime;
$products[] = $product;
}
// JavaScript is only able to work with indexed Array's
$productsSet[] = $products;
$productsSet[] = $amount;
您可以将最后5行缩减为doSomething($actionStr,$argumentList)代码>您打算如何使用阵列过滤器
?不仅应该删除null
,而且还应该删除“”,0,'0',false,array()
。@Quasimodo's如果为null,则我不希望该项位于参数列表中。然后,您至少必须在回调函数中指定它。默认情况下,它可以过滤上面我的评论中列出的所有计算结果为false的内容。@Quasimodo's one-hmmmm我想知道在案例4中是否有改进的余地,而不是回调函数中。
// ------------- CASE 4 ---------------------------
$argumentList = array(
'a' => 'ten',
'b' => 20,
'c' => '0',
'd' => null,
'e' => 0,
// 'e' => false, // throws Exception
// 'f' => [1,2,3], // throws Exception
);
[$argumentList, $actionStr] = array_reduce
(
$argumentList,
function(array $aggr, $v) : array
{
if(null === $v)
return $aggr;
if(is_numeric($v))
{
$aggr[0][] = $v;
$aggr[1] .= 'd';
return $aggr;
}
if(is_string($v))
{
$aggr[0][] = $v;
$aggr[1] .= 's';
return $aggr;
}
throw new InvalidArgumentException('Type ' . gettype($v) . ' not allowed.');
},
[[], '']
);
doSomething($actionStr, ...$argumentList);
$argumentList = array(
'a' => 10,
'b' => 20,
'c' => null,
'd' => null,
'e' => null,
);
$argumentList = array_filter($argumentList);
$mysqli_param_types = '';
foreach($argumentList as $k => $v){
if(is_numeric($v)){
$actionStr .= 'd';
}
if(is_string($v)){
$actionStr .= 's';
}
}
// instead of array_values() and array_merge()
// its more clear to iterate over argumentList (even if its twice)
$mysqli_reference_params[] =& $actionStr;
foreach($argumentList as &$var) {
$mysqli_reference_params[] =& $var;
}
call_user_func_array('bind_param_test', $mysqli_reference_params);
/* OUTPUT:
Decimal: 10
Decimal: 20 */
$sql = " SELECT p.`productID`,
p.`productCode`,
p.`productName`,
p.`productDescription`,
p.`productPrice`,
p.`productRating`,
p.`productDateTime`
FROM `products` as p
WHERE `p`.`productID` IS NOT NULL ";
if($searchCode){
$sql .= "AND p.`productCode` = ? ";
}
if($searchName){
$sql .= "AND p.`productName` = ? ";
}
if($searchDescription) {
$sql .= "AND p.`productDescription` = ? ";
}
if($searchPrice) {
$sql .= "AND p.`productPrice` = ? ";
}
if($searchRating) {
$sql .= "AND p.`productRating` = ? ";
}
if($searchDateTime) {
$sql .= "AND p.`productDateTime` = ? ";
}
// Create mysqli_stmt
$statement = $mysqli->prepare($sql);
if ($statement instanceof \mysqli_stmt === false) {
return null;
}
// Handle search variables through bind_param()
$bindParamVarList = array(
'productCode' => $searchCode,
'productName' => $searchName,
'productDescription' => $searchDescription,
'productPrice' => $searchPrice,
'productRating' => $searchRating,
'productDateTime' => $searchDateTime,
);
$bindParamVarList = array_filter($bindParamVarList);
if($bindParamVarList){
$types = '';
foreach($bindParamVarList as &$v){
if(is_numeric($v)){
$types .= 'd';
$v = (float)$v;
continue;
}
if(is_string($v)){
$types .= 's';
continue;
}
}
// call_user_func_array needs references and not values
$mysqli_reference_params = array();
$mysqli_reference_params[] =& $types;
foreach($bindParamVarList as &$bindParamVar) {
$mysqli_reference_params[] =& $bindParamVar;
}
call_user_func_array(array($statement, 'bind_param'), $mysqli_reference_params);
}
$statement->execute();
$statement->store_result();
$amount = $statement->num_rows;
$statement->bind_result($productID,
$productCode,
$productName,
$productDescription,
$productPrice,
$productRating,
$productDateTime
);
$products = array();
$productsSet = array();
while($statement->fetch()){
$product = array();
$product['productID'] = $productID;
$product['productCode'] = $productCode;
$product['productName'] = $productName;
$product['productDescription'] = $productDescription;
$product['productPrice'] = $productPrice;
$product['productRating'] = $productRating;
$product['productDateTime'] = $productDateTime;
$products[] = $product;
}
// JavaScript is only able to work with indexed Array's
$productsSet[] = $products;
$productsSet[] = $amount;