好的,我完全忘记了如何跳过PHP中的参数。
可以说我有:
function getData($name, $limit = '50', $page = '1') {
...
}
我将如何调用此函数,以使中间参数采用默认值(即“ 50”)?
getData('some name', '', '23');
以上正确吗?我似乎无法使它正常工作。
好的,我完全忘记了如何跳过PHP中的参数。
可以说我有:
function getData($name, $limit = '50', $page = '1') {
...
}
我将如何调用此函数,以使中间参数采用默认值(即“ 50”)?
getData('some name', '', '23');
以上正确吗?我似乎无法使它正常工作。
Answers:
您的帖子是正确的。
不幸的是,如果您需要在参数列表的最后使用可选参数,则必须指定直到最后一个参数为止的所有内容。通常,如果要混合匹配,请给它们提供默认值''
或null
,如果它们是默认值,则不要在函数内使用它们。
$limit = is_numeric($limit) ? $limit : '50';
在getData函数的开头执行
除了指定默认值(例如false
或)外,无法“跳过”参数null
。
由于PHP在此方面缺少一些语法糖,因此您经常会看到类似以下的内容:
checkbox_field(array(
'name' => 'some name',
....
));
正如评论中雄辩地说的那样,它使用数组来模拟命名参数。
这提供了最大的灵活性,但在某些情况下可能不需要。至少,您可以将大多数情况下无法想到的内容移至参数列表的末尾。
否,无法以这种方式跳过参数。仅当传递的参数位于参数列表的末尾时,才可以省略传递的参数。
对此有一个正式建议:https : //wiki.php.net/rfc/skipparams,但被拒绝了。提案页面链接到有关此主题的其他SO问题。
能够跳过可选参数的方法没有任何改变,但是对于正确的语法以及能够为我想跳过的参数指定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');
调用:并且将来调用该函数的任何人都不必记住每次的默认值或为它们声明的常量。
简单的答案是“ 否”。但是,为什么在重新排列参数时跳过此操作呢?
您的代码是“ 默认函数参数的不正确用法 ”,将无法正常使用。
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。
如上所述,您将无法跳过参数。我已写出此答案以提供一些附录,该附录太大而无法在评论中放置。
@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
等等),这没什么好说的读者。
(我同意打电话$var = a(,,'ddd');
是最好的选择)
您不能跳过参数,但是可以使用数组参数,并且只需要定义1个参数,即参数数组。
function myfunction($array_param)
{
echo $array_param['name'];
echo $array_param['age'];
.............
}
您可以添加所需的任意多个参数,而无需定义它们。调用函数时,您可以像下面这样放置参数:
myfunction(array("name" => "Bob","age" => "18", .........));
正如其他人已经说过的那样,如果不在函数中添加任何代码行,PHP便无法实现您想要的功能。
但是您可以将这段代码放在函数的顶部,以获取功能:
foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) {
if(empty(${$param->getName()}) && $param->isOptional())
${$param->getName()} = $param->getDefaultValue();
}
因此,基本上,debug_backtrace()
我得到了放置此代码的函数名称,然后创建一个新ReflectionFunction
对象并遍历所有函数参数。
在循环中,我只是检查function参数是否为empty()
AND,参数是否为“可选”(意味着它具有默认值)。如果是,我只是将默认值分配给参数。
将限制设置为空
function getData($name, $limit = null, $page = '1') {
...
}
并调用该功能
getData('some name', null, '23');
如果要设置限制,可以将其作为参数传递
getData('some name', 50, '23');
如前所述,什么都没有改变。但是要注意,过多的参数(尤其是可选参数)是代码异味的有力指标。
也许您的功能做得太多:
// 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 */);
此代码段:
函数getData($ name,$ options){ $默认=数组( '限制'=> 50, '页面'=> 2, ); $ args = array_merge($ default,$ options); print_r($ args); } getData('foo',array()); getData('foo',array('limit'=> 2)); getData('foo',array('limit'=> 10,'page'=> 10));
答案是:
数组 ( [限制] => 50 [页面] => 2 ) 数组 ( [限制] => 2 [页面] => 2 ) 数组 ( [限制] => 10 [页面] => 10 )
这就是我要做的:
<?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 */
?>
希望这会帮助某人
这是一个古老的问题,提供了许多技术胜任的答案,但它呼唤着PHP中的一种现代设计模式:面向对象编程。与其注入原始标量数据类型的集合,不如考虑使用包含函数所需的所有数据的“注入对象”。 http://php.net/manual/zh/language.types.intro.php
注入的对象可能具有属性验证例程等。如果将数据的实例化和注入到注入的对象中无法通过所有验证,则代码可以立即引发异常,并且应用程序可以避免笨拙的处理过程可能包含不完整的数据。
我们可以键入提示以在部署之前捕获注入的对象以发现错误。几年前的这篇文章中总结了一些想法。
https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html
我必须使用可选参数创建一个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');
这不是最漂亮的东西,但可能是在工厂中进行测试的好模式。
试试这个。
function getData($name, $limit = NULL, $page = '1') {
if (!$limit){
$limit = 50;
}
}
getData('some name', '', '23');
您不能在函数调用中跳过中间参数。但是,您可以解决此问题:
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';
}
}
正如@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;
...
}
?>
希望这可以帮助。