参数数量不限的 PHP 函数

Posted

技术标签:

【中文标题】参数数量不限的 PHP 函数【英文标题】:PHP function with unlimited number of parameters 【发布时间】:2010-12-07 08:04:21 【问题描述】:

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

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

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

【问题讨论】:

如果不付出辛勤的努力,您将无法做到。我建议要么以通常的方式构建查询,要么如果您不惜任何代价想要本地准备好的语句,则移至 PDO。他们有 bindValue,请注意 感谢您的信息。不幸的是,与仅编写我自己的简单东西相比,PDO 似乎有点矫枉过正,需要更多的努力和样板。 对于简单的东西,您可以使用我的用户信息中的库。不过这真的很简单。 【参考方案1】:

你看过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,因为代码可能更具可读性,更重要的是由于缺少格式变量而不太可能导致错误。

【讨论】:

我不时使用 func_get_args。它的缺点是很难一目了然地看到该方法的输入是什么。另外,它在你的代码中引入了一段丑陋的语法。我只推荐这种方法作为最后的手段。首选参数对象重构。 我同意你的观点,这是一种处理可变参数的坏方法。我在答案中添加了一个替代想法 我比 func_get_args 更喜欢“链接函数”的提议。我知道这个设计是一个 FLUENT 界面。它是通过让 bindString()、bindDecimal() 等执行“return $this;”来完成的。作为他们的最后一行。 FLUENT 界面对于某些类型的工厂来说是一个很好的选择。【参考方案2】:

有一个名为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

【讨论】:

【参考方案3】:

使用func_get_args():

function my_func() 
  $args = func_get_args();
  foreach ($args as $arg) 
    echo "Arg: $arg\n";
  

【讨论】:

如果没有设置参数,这不起作用,然后通过引用传递,在函数内部设置。 func_get_args 尝试访问引发错误的未设置变量。【参考方案4】:

以上建议都不错,但我认为它们不适合您的情况。

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

如果要包装此函数,则需要将 references 传递给 bind_param 函数的原始参数变量。我不认为 func_get_args() 给你这个,而是给你价值。因此,不可能使用这些传递给父函数。我在尝试扩展 mysqli_stmt 时遇到了类似的问题,但从未得到令人满意的解决方案。

恐怕这并不是对您问题的真正答案,只是警告其他论点在您对任意数量的论点的特定应用中可能不起作用。

【讨论】:

确实如此。上次我检查(1 年多前)时,无法包装/扩展 bind_param(),因为 func_get_args() 不会返回引用。【参考方案5】:

在 5 个参数时,此设计开始展示反模式“Too Many Parameters”。这表明重构称为Parameter Object,它是一个对象或结构,其数据成员表示要传入的参数。但是,请避免将其设为Magic Container。

另请参阅 refactoring.com 上的 Introduce Parameter Objectrefactoring。

【讨论】:

【参考方案6】:

func_get_args() 的答案适用于非参考参数。 然而,让通过引用传递的参数起作用是有技巧的。 此外,从技术上讲,它不是一个接受 无限 参数的函数,而只是一些任意大的数字,比如一百。

你可以做的是定义一个接受大量参数的函数,并让它们默认为空。 然后,在该函数内部,将每个非空引用附加到一个数组,然后使用 *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";

【讨论】:

【参考方案7】:

之前你应该使用func_get_args(),但是在php 5.6中,你可以使用... operator。

例如,您可以编写一个函数,该函数返回所有数字的总和,并发送给函数:

function bind_param(...$params)
   var_dump($params);

您的params 实际上是一个包含所有元素的数组。

【讨论】:

【参考方案8】:

如果您使用的是 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 版本 ,那么您可以使用 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);
?>

【讨论】:

以上是关于参数数量不限的 PHP 函数的主要内容,如果未能解决你的问题,请参考以下文章

PHP 函数可以接受无限数量的参数吗? [复制]

php 可变数量的参数列表

PHP传递任意数量的函数参数

每日编程-20170327

c语言中如何保存一个位数不限的小数?

PHP - 具有未知数量参数的安全 PDO 准备语句