如何编写一个可以接受无限数量参数的函数?
我要做的是在包含以下内容的类中创建一个函数:
$stmt->bind_param('sssd', $code, $language, $official, $percent);
答案 0 :(得分:23)
您是否看过func_get_args,func_get_arg和func_num_args
例如:
function foo(){
if ( func_num_args() > 0 ){
var_dump(func_get_args());
}
}
或:
function bind_param(){
if ( func_num_args() <= 1 ){
return false; //not enough args
}
$format = func_get_arg(0)
$args = array_slice(func_get_args(), 1)
//etc
}
修改强>
关于Ewan Todds评论:
我没有任何关于您正在创建包装器的基本API的知识,但另一种选择可能是使用链接函数执行某些操作,因此您生成的界面看起来像:
$var->bind()->bindString($code)
->bindString($language)
->bindString($official)
->bindDecimal($percent);
我更喜欢使用func_get_args,因为代码可能更具可读性,更重要的是由于缺少格式变量而不太可能导致错误。
答案 1 :(得分:11)
以前您应该使用func_get_args()
,但在 php 5.6 中,您可以使用... operator。
例如,您可以编写函数,该函数返回发送给函数的所有数字的总和:
function bind_param(...$params){
var_dump($params);
}
您的params
实际上是所有元素的数组。
答案 2 :(得分:5)
function my_func() {
$args = func_get_args();
foreach ($args as $arg) {
echo "Arg: $arg\n";
}
}
答案 3 :(得分:4)
以上建议都很好,但我认为它们不适合你的情况。
$stmt->bind_param('sssd', $code, $language, $official, $percent);
如果要包装此函数,则需要将 references 传递给bind_param函数的原始参数变量。我不认为func_get_args()会给你这个,它会为你提供值。因此,将无法使用这些传递给父函数。当我试图扩展mysqli_stmt并且从未达到令人满意的解决方案时,我遇到了类似的问题。
这实际上不是你的问题的答案,我担心,只是警告其他论点可能不适用于你的任意数量的论点的特定应用。
答案 4 :(得分:3)
如果您使用的是PHP 5.6或更高版本,则参数列表可能包含 ...
标记,以表示该函数接受可变数量的参数。参数将作为数组传递给给定变量;只需使用 ...
即可访问无限量变量参数。
例如:
<?php
function sum(...$numbers) {
$sum = 0;
foreach ($numbers as $n) {
$sum += $n;
}
return $sum ;
}
echo sum(1, 2, 3, 4, 5);
?>
如果您使用 PHP版本&lt; = 5.5 ,则可以使用func_num_args(),func_get_arg()和func_get_args()函数访问无限制参数。
例如:
<?php
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs \n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "\n";
}
}
foo(1, 2, 3);
?>
答案 5 :(得分:2)
在5个参数下,此设计开始展示AntiPattern“Too Many Parameters”。这表明重构称为Parameter Object,一个对象或结构,其数据成员表示要传入的参数。但是,避免将其设为Magic Container。
另请参阅refactoring.com上的Introduce Parameter Object重构。
答案 6 :(得分:0)
有一个名为func_get_args()的函数,它是传递给函数的所有参数的数组。
来自PHP.net的示例
function foo()
{
$numargs = func_num_args();
echo "Number of arguments: $numargs<br />\n";
if ($numargs >= 2) {
echo "Second argument is: " . func_get_arg(1) . "<br />\n";
}
$arg_list = func_get_args();
for ($i = 0; $i < $numargs; $i++) {
echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
}
}
foo(1, 2, 3);
以上示例将输出:
论点数量:3
第二个论点是:2
参数0是:1
参数1是:2
参数2是:3
答案 7 :(得分:0)
func_get_args()的答案适用于非参考参数。 但是,有一个技巧可以让参考传递参数起作用。 此外,从技术上讲,它不是一个接受无限参数的函数,而只是一些任意大的数字,比如一百个。
你可以做的是定义一个接受大量参数的函数,并将它们默认为null。 然后,在该函数内部,将每个非null引用附加到一个数组,然后使用* call_user_func_array()*来调用* bind_param()*。
function my_bind_param(&$stmt, $types, &$arg1, &$arg2 = null, &$arg3 = null, ...)
{
$vars = array($types);
$vars[] = $arg1;
if ($arg2 != null)
$vars[] = &$arg2;
if ($arg3 != null)
$vars[] = &$arg3;
...
if (!call_user_func_array(array($stmt, "bind_param"), $vars))
{
if ($stmt->errno == 0)
return array(-1, "Unknown error binding parameters.");
else
return array(-1, "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error);
}
return array(0, "");
}
真正的诀窍是你不想手工编写这个东西。 只需创建另一个脚本,它将输出此函数的主体(波形括号之间的所有内容)为* my_bind_param_body.php *。 然后,只需在主文件中定义函数的标题,并将正文包含在该函数定义中。 即。
function my_bind_param(&$stmt, $types, &$arg1, &$arg2 = null, &$arg3 = null, ...)
{
return include "my_bind_param_wrapper_body.php";
}