106

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

可以说我有:

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

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

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

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

4

20 回答 20

58

你的帖子是正确的。

不幸的是,如果您需要在参数列表的最后使用可选参数,则必须指定最后一个参数之前的所有内容。一般来说,如果你想混搭,你给它们默认值''or null,如果它们是默认值,就不要在函数内部使用它们。

于 2009-06-30T23:35:09.133 回答
42

除了指定默认值,如falseor之外,没有其他方法可以“跳过”参数null

由于 PHP 在这方面缺少一些语法糖,因此您经常会看到如下内容:

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

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

这提供了最大的灵活性,但在某些情况下可能不需要。至少你可以把你认为大多数时候不期望的东西移到参数列表的末尾。

于 2009-06-30T23:35:42.330 回答
42

不,不可能以这种方式跳过参数。只有当参数位于参数列表的末尾时,您才能省略传递参数。

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

于 2015-05-14T15:22:12.933 回答
6

关于能够跳过可选参数没有任何改变,但是为了正确的语法和能够为我想跳过的参数指定 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');将来调用该函数的任何人都不需要每次都记住默认值或为它们声明的常量。

于 2015-05-18T12:25:20.970 回答
5

简单的答案是否定的。但是,为什么要在重新排列参数实现这一点时跳过呢?

你的是“默认函数参数的错误使用”,不会像你期望的那样工作。

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"

在非默认值之后将默认值放在您的右侧,以确保它始终会重新调整该变量的默认值,如果它没有定义/给出 这是一个供参考的链接以及这些示例的来源。

编辑:null按照其他人的建议将其设置为可能会起作用,并且是另一种选择,但可能不适合您想要的。如果未定义,它将始终将默认值设置为 null。

于 2015-05-20T11:26:39.987 回答
2

对于跳过的任何参数(您必须)使用默认参数,以确保安全。

(在默认参数为 '' 或类似参数的情况下设置为 null,反之亦然,这会让您陷入困境......)

于 2013-01-29T10:07:54.797 回答
2

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

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

您可以添加任意数量的参数,无需定义它们。当你调用函数时,你把你的参数是这样的:

myfunction(array("name" => "Bob","age" => "18", .........));
于 2015-05-15T07:42:48.190 回答
2

如上所述,您将无法跳过参数。我写这个答案是为了提供一些附录,它太大而不能放在评论中。

@Frank Nocke建议使用其默认参数调用该函数,例如

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.

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

这个解决方案的清晰性当然比提供对读者无话可说的原始默认值(如 等)NULL要好。0

(我同意打电话给like$var = a(,,'ddd');是最好的选择)

于 2015-05-15T10:56:58.447 回答
2

此功能在 PHP 8.0 中实现

PHP 8 引入了命名参数

哪个:

允许任意跳过默认值

参考文档_

使用此功能无需更改:

让我们使用 OPs 功能function getData($name, $limit = '50', $page = '1')

用法

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

本机函数也将使用此功能

htmlspecialchars($string, double_encode: false);
// Same as
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

支持 Netbeans IDE 12.3 功能

支持此功能,命名参数的代码完成除外,看起来更好;)

在此处输入图像描述

于 2021-10-31T13:44:42.430 回答
1

这是一个老问题,有许多技术上能胜任的答案,但它呼唤 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

于 2019-01-12T00:01:20.927 回答
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');

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

于 2020-07-06T22:11:13.673 回答
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()AND 参数是否为“可选”(意味着它具有默认值)。如果是,我只需将默认值分配给参数。

Demo

于 2015-05-15T20:04:11.233 回答
0

将限制设置为空

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

并调用该函数

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

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

getData('some name', 50, '23');
于 2015-05-16T07:03:03.503 回答
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 */);
于 2015-05-19T21:31:16.563 回答
0

这个片段:

    函数 getData($name, $options) {
       $默认 = 数组(
            '限制' => 50,
            '页面' => 2,
        );
        $args = array_merge($default, $options);
        print_r($args);
    }

    getData('foo', 数组());
    getData('foo', array('limit'=>2));
    getData('foo', array('limit'=>10, 'page'=>10));

答案是:

     大批
    (
        [限制] => 50
        [页面] => 2
    )
    大批
    (
        [限制] => 2
        [页面] => 2
    )
    大批
    (
        [限制] => 10
        [页] => 10
    )

于 2015-05-20T13:07:47.480 回答
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 */

?>

希望这会对某人有所帮助

于 2016-12-18T09:13:35.360 回答
-1

尝试这个。

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

getData('some name', '', '23');
于 2015-05-19T08:10:18.473 回答
-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';
    }
}
于 2015-05-19T19:06:01.430 回答
-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;
    ...
}
?>

希望这可以帮助。

于 2015-05-20T02:35:09.673 回答
-6
getData('some name');

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

于 2015-05-19T07:43:42.447 回答