如何在函数调用中跳过可选参数?

115

好的,我完全忘记了如何在PHP中跳过参数。

假设我有以下代码:

function getData($name, $limit = '50', $page = '1') {
    ...
}
我该如何调用这个函数,使得中间的参数采用默认值(即 '50')?
getData('some name', '', '23');

以上的代码是否正确?我似乎无法让它工作。


1
@Chuck,你具体是在寻找什么?比如一个解决方法或者实现这个功能的类等等? - Rizier123
@Rizier123 我想问一下当前版本的PHP是否支持跳过参数(就像其他语言一样)。当前的答案可能已经过时了。从赏金描述来看:“当前的答案已经五年了。当前版本的PHP是否有所改变?” - Chuck Le Butt
1
@Chuck 那么答案可能是:没有任何改变;如果没有解决方法/代码,你将无法获得所需的功能。 - Rizier123
所有这里的答案都似乎假定你对被调用的函数有控制权。如果那个函数是库或框架的一部分,你只能在需要第三个参数时为参数2指定某些内容。唯一的选择是查看函数源代码并复制默认值。 - Snapey
无法跳过它,但是您可以使用ReflectionFunction传递默认参数。我在类似的问题中发布了答案 - David
可能是在函数中使用默认参数的重复问题。 - David
21个回答

1

我需要创建一个带有可选参数的工厂,我的解决方法是使用空值合并运算符:

public static function make(
    string $first_name = null,
    string $last_name = null,
    string $email = null,
    string $subject = null,
    string $message = null
) {
    $first_name = $first_name ?? 'First';
    $last_name  = $last_name ?? 'Last';
    $email      = $email ?? 'foo@bar.com';
    $subject    = $subject ?? 'Some subject';
    $message    = $message ?? 'Some message';
}

使用方法:

$factory1 = Factory::make('First Name Override');
$factory2 = Factory::make(null, 'Last Name Override');
$factory3 = Factory::make(null, null, null, null 'Message Override');

虽然不是最美观的东西,但可能是在测试工厂中使用的好模式。


0

正如其他人已经说过的那样,如果不在函数中添加任何代码行,PHP将无法实现您想要的功能。

但是,您可以将以下代码放置在函数顶部以获得所需的功能:

foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) {
    if(empty(${$param->getName()}) && $param->isOptional())
        ${$param->getName()} = $param->getDefaultValue();
}

所以基本上使用 debug_backtrace(),我可以获取包含此代码的函数名称,然后创建一个新的ReflectionFunction对象并循环遍历所有函数参数。

在循环中,我只需检查函数参数是否为empty()且该参数是“可选的”(即具有默认值)。如果是,则将默认值分配给该参数。

演示


0

将限制设置为 null

function getData($name, $limit = null, $page = '1') {
    ...
}

并调用该函数

getData('some name', null, '23');

如果你想设置限制,可以将其作为参数传递

getData('some name', 50, '23');

0

从PHP 8.0.0开始,声明可选参数后必须参数已经被弃用。

现在您可以省略可选参数。

例如:

<?php

function foo ( $a = '1', $b = '2', $c = '3'  ){
   return "A is " . $a . ", B is " . $b . ", C is " . $b  
}

echo foo(c: '5');  
// Output A is 1, B is 2, C is 5

0

如之前建议的那样, 没有改变。但是要注意,太多参数(尤其是可选参数)是代码出现问题的强烈指示。

也许你的函数做了太多事情:

// first build context
$dataFetcher->setPage(1);
// $dataFetcher->setPageSize(50); // not used here
// then do the job
$dataFetcher->getData('some name');

一些参数可以按逻辑分组:

$pagination = new Pagination(1 /*, 50*/);
getData('some name', $pagination);
// Java coders will probably be familiar with this form:
getData('some name', new Pagination(1));

在最后的情况下,您总是可以引入一个特定的参数对象

$param = new GetDataParameter();
$param->setPage(1);
// $param->setPageSize(50); // not used here
getData($param);

(这只是一种更正式的参数数组技术)的夸大版本。

有时,使参数可选的原因本身就是错误的。在这个例子中,$page真的应该是可选的吗?省几个字符真的有什么区别吗?

// dubious
// it is not obvious at first sight that a parameterless call to "getData()"
// returns only one page of data
function getData($page = 1);

// this makes more sense
function log($message, $timestamp = null /* current time by default */);

0

这段代码:

    function getData($name, $options) {
       $default = array(
            'limit' => 50,
            'page' => 2,
        );
        $args = array_merge($default, $options);
        print_r($args);
    }
getData('foo', array()); getData('foo', array('limit'=>2)); getData('foo', array('limit'=>10, 'page'=>10));

输出结果为:

     Array
    (
        [limit] => 50
        [page] => 2
    )
    Array
    (
        [limit] => 2
        [page] => 2
    )
    Array
    (
        [limit] => 10
        [page] => 10
    )


2
不错。但是稍微解释一下会更有帮助。 - showdev
不错的回答,但如果你想省略可选参数,可以这样做:function getData($name, $args = array()) { $defaults = array('limit':=>50,'page'=>2); $args=array_merge($defaults,$args); } 现在可以只使用第一个参数调用此函数,如下所示:getData('foo'); - EchoSin

0

这是我会做的:

<?php

    function getData($name, $limit = '', $page = '1') {
            $limit = (EMPTY($limit)) ? 50 : $limit;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

     echo getData('table');

    /* output name=table&limit=50&page=1 */

     echo getData('table',20);

    /* name=table&limit=20&page=1 */

    echo getData('table','',5);

    /* output name=table&limit=50&page=5 */

    function getData2($name, $limit = NULL, $page = '1') {
            $limit = (ISSET($limit)) ? $limit : 50;
            $output = "name=$name&limit=$limit&page=$page";
            return $output;
    }

    echo getData2('table');

    // /* output name=table&limit=50&page=1 */

    echo getData2('table',20);

    /* output name=table&limit=20&page=1 */

    echo getData2('table',NULL,3);

    /* output name=table&limit=50&page=3 */

?>

希望这能帮助到某个人


-1

在函数调用中,您不能跳过中间参数。但是,您可以通过以下方式解决:

function_call('1', '2', '3'); // Pass with parameter.
function_call('1', null, '3'); // Pass without parameter.

功能:

function function_call($a, $b='50', $c){
    if(isset($b)){
        echo $b;
    }
    else{
        echo '50';
    }
}

我不确定为什么你会被踩,除了$c还需要一个默认值(在可选参数后面不能有任何必需的参数)。 - Frank Forte

-2
正如 @IbrahimLawal 指出的那样,最好的做法是将它们设置为 null 值。只需检查传递的值是否为 null,如果是,则使用您定义的默认值。
<?php
define('DEFAULT_LIMIT', 50);
define('DEFAULT_PAGE', 1);

function getData($name, $limit = null, $page = null) {
    $limit = is_null($limit) ? DEFAULT_LIMIT : $limit;
    $page = is_null($page) ? DEFAULT_PAGE : $page;
    ...
}
?>

希望这能有所帮助。

你只是简单地复制了回复。相反,你可以点赞或者评论它。 - Ibrahim Lawal

-2

试一下。

function getData($name, $limit = NULL, $page = '1') {
               if (!$limit){
                 $limit = 50;
               }
}

getData('some name', '', '23');

如果限制为0,则将其替换为50。 - avatarofhope2
如果限制为0,它将被替换为50。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接