PHP函数具有无限数量的参数

时间:2009-10-16 10:47:22

标签: php arguments

如何编写一个可以接受无限数量参数的函数?

我要做的是在包含以下内容的类中创建一个函数:

$stmt->bind_param('sssd', $code, $language, $official, $percent);

8 个答案:

答案 0 :(得分:23)

您是否看过func_get_argsfunc_get_argfunc_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)

使用func_get_args()

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";
}