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

时间:2009-06-30 23:31:40

标签: php function parameters default-value optional-parameters

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

让我说我有:

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

我如何调用此函数以使middle参数采用默认值(即'50')?

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

以上是否正确?我似乎无法让这个工作。

19 个答案:

答案 0 :(得分:48)

你的帖子是正确的。

不幸的是,如果您需要在参数列表的最后使用可选参数,则必须在最后一个参数之前指定所有内容。通常,如果您想要混合匹配,则为其提供默认值''null,如果它们是默认值,则不要在函数内使用它们。

答案 1 :(得分:37)

除了指定falsenull之类的默认值之外,无法“跳过”参数。

由于PHP在这方面缺乏一些语法糖,你经常会看到这样的东西:

checkbox_field(array(
    'name' => 'some name',
    ....
));

正如评论中雄辩地说的那样,正在使用数组来模拟命名参数。

这提供了最大的灵活性,但在某些情况下可能不需要。至少你可以把你想到的大部分时间都没想到的东西移到参数列表的末尾。

答案 2 :(得分:33)

不,不可能以这种方式跳过参数。如果它们位于参数列表的末尾,则可以省略传递参数

有一个正式的提案:https://wiki.php.net/rfc/skipparams,它被拒绝了。提案页面链接到有关此主题的其他SO问题。

答案 3 :(得分:5)

关于能够跳过可选参数没有任何改变,但是为了正确的语法并且能够为我想跳过的参数指定NULL,这里我是如何做到的:

define('DEFAULT_DATA_LIMIT', '50');
define('DEFAULT_DATA_PAGE', '1');

/**
 * getData
 * get a page of data 
 *
 * Parameters:
 *     name - (required) the name of data to obtain
 *     limit - (optional) send NULL to get the default limit: 50
 *     page - (optional) send NULL to get the default page: 1
 * Returns:
 *     a page of data as an array
 */

function getData($name, $limit = NULL, $page = NULL) {
    $limit = ($limit==NULL) ? DEFAULT_DATA_LIMIT : $limit;
    $page = ($page==NULL) ? DEFAULT_DATA_PAGE : $page;
    ...
}

这可以被称为:getData('some name',NULL,'23');并且将来调用该函数的任何人都不需要记住每次的默认值或为它们声明的常量。

答案 4 :(得分:3)

简单的答案是。但是,为什么在重新安排论证时会跳过这个?

您的“默认函数参数的使用不正确”,并且无法按预期工作。

PHP文档的附注:

  

使用默认参数时,任何默认值都应位于任何非默认参数的右侧;否则,事情将无法按预期工作。

请考虑以下事项:

function getData($name, $limit = '50', $page = '1') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '', '23');   // won't work as expected

输出将是:

"Select * FROM books WHERE name = some name AND page = 23 limit"

默认函数参数的正确用法应如下所示:

function getData($name, $page = '1', $limit = '50') {
    return "Select * FROM books WHERE name = $name AND page = $page limit $limit";
}

echo getData('some name', '23');  // works as expected

输出将是:

"Select * FROM books WHERE name = some name AND page = 23 limit 50"

在非默认值之后将默认设置放在右侧,确保在未定义/给定的情况下,它将始终重新调整该变量的默认值 这是一个link供参考,这些例子来自何处。

编辑:将其设置为null,因为其他人建议可能有效并且是另一种选择,但可能无法满足您的需求。如果未定义,它将始终将默认值设置为null。

答案 5 :(得分:2)

对于任何跳过的参数(必须)使用默认参数,为了安全起见。

(在默认参数为''或类似的情况下设置为null,反之亦然会让您遇到麻烦......)

答案 6 :(得分:2)

您不能跳过参数,但可以使用数组参数,只需要定义一个参数,这是一个参数数组。

function myfunction($array_param)
{
    echo $array_param['name'];
    echo $array_param['age'];
    .............
}

您可以添加所需的参数,不需要定义它们。当您调用该函数时,您可以输入如下参数:

myfunction(array("name" => "Bob","age" => "18", .........));

答案 7 :(得分:2)

如上所述,您将无法跳过参数。我写了这个答案,提供了一些补遗,这个补遗太大了,无法发表评论。

@Frank Nocke proposes以默认参数调用该函数,例如

function a($b=0, $c=NULL, $d=''){ //...

你应该使用

$var = a(0, NULL, 'ddd'); 

在功能上与省略前两个($b$c)参数相同。

目前尚不清楚哪些是默认值(0键入提供默认值,还是重要?)。

当默认值可以由函数(或方法)作者更改时,还存在将默认值问题连接到外部(或内置)函数的危险。因此,如果您不想在程序中更改您的调用,则可能会无意中更改其行为。

一些解决方法可能是定义一些全局常量,例如DEFAULT_A_B,这将是“函数A的B参数的默认值”和“省略”参数:

$var = a(DEFAULT_A_B, DEFAULT_A_C, 'ddd');

对于类,如果定义类常量,它会更容易,更优雅,因为它们是全局范围的一部分,例如。

class MyObjectClass {
  const DEFAULT_A_B = 0;

  function a($b = self::DEFAULT_A_B){
    // method body
  }
} 
$obj = new MyObjectClass();
$var = $obj->a(MyObjectClass::DEFAULT_A_B); //etc.

请注意,此默认常量在整个代码中只定义一次(即使在方法声明中也没有值),因此如果出现一些意外更改,您将始终为函数/方法提供正确的默认值。

此解决方案的清晰度当然比提供原始默认值(如NULL0等)更好,这对读者没有任何意义。

(我同意像$var = a(,,'ddd');这样的呼叫是最好的选择)

答案 8 :(得分:0)

我必须创建一个带有可选参数的Factory,我的解决方法是使用空合并运算符:

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');

这不是最漂亮的东西,但可能是在工厂中用于测试的好模式。

答案 9 :(得分:0)

这是一个古老的问题,提供了许多技术胜任的答案,但是它呼唤着PHP中的一种现代设计模式:面向对象编程。与其注入原始的标量数据类型的集合,不如考虑使用包含函数所需的所有数据的“注入对象”。 http://php.net/manual/en/language.types.intro.php

注入的对象可能具有属性验证例程,等等。如果实例化和将数据注入到注入的对象中无法通过所有验证,则代码可以立即引发异常,并且应用程序可以避免尴尬处理潜在不完整数据的过程。

我们可以键入提示以在部署之前发现注入的对象以发现错误。几年前的这篇文章中总结了一些想法。

https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html

答案 10 :(得分: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 */

?>

希望这会有所帮助

答案 11 :(得分: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
    )

答案 12 :(得分:0)

As advised earlier,没有任何改变。 但要注意,太多参数(尤其是可选参数)是代码嗅觉的强烈指示。

也许你的功能做得太多了:

// 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));

最后,您可以随时介绍特设parameter object

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

(这只是不太正式的parameter array technique

的美化版本

有时,使参数可选的原因是错误的。在这个例子中,$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 */);

答案 13 :(得分:0)

将限制设置为空

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

并调用该函数

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

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

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

答案 14 :(得分: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()并且参数是&#34;可选&#34; (表示它有一个默认值)。如果是,我只需将默认值分配给参数。

Demo

答案 15 :(得分:-1)

试试这个。

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

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

答案 16 :(得分:-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;
    ...
}
?>

希望这有帮助。

答案 17 :(得分:-2)

您不能跳过函数调用中的中间参数。但是,你可以解决这个问题:

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

答案 18 :(得分:-6)

getData('some name');

只是不传递它们,将接受默认值