[Day11]PHP函数01

PHP函数

自定义函数

函数可用以下语法来定义

<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
    echo "Example function.\n";
    return $retval;
}
?>

函数不需要在使用之前被定义,除非是函数是有条件被定义时,才必须在使用前定义

举以下范例

  1. 有条件的函数:
<?php

$makefoo = true;

/* 不能在此处调用foo()函数,    
 因为它还不存在,但可以调用bar()函数。*/

bar();

if ($makefoo) {
  function foo()
  {
    echo "I don't exist until program execution reaches me.\n";
  }
}

/* 现在可以安全调用函数 foo()    
   因为 $makefoo 值为真true */

if ($makefoo) foo();

function bar()
{
  echo "I exist immediately upon program start.\n";
}

?>
  1. 函数中的函数
<?php
function foo()
{
  function bar()
  {
    echo "I don't exist until foo() is called.\n";
  }
}

/* 现在还不能调用 bar() 函数,因为它还不存在 */

foo();

/* 现在可以调用 bar() 函数了,因为 foo() 函数的执行使得 bar() 函数变为已定义的函数 */

bar();

?>

PHP 中的所有函数和类都具有全局作用域,可以定义在一个函数之内而在之外调用,反之亦然。
PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数。

还有递回函数,也就是自己呼叫自己

举个费氏数列的例子(从0,1开始,後面的数是前两个数相加)

<?php
function fib($n)
{
    if($n == 0) return 0;
    if($n == 1) return 1;
    return fib($n-1) + fib($n - 2);
}

for($i = 0; $i <= 5; $i++){
    echo fib("$i ");
}

// outputs
// 0,1,1,2,3,5

注意: 但是要避免递归函数/方法调用超过 100-200 层,因为可能会使堆积崩溃从而使当前脚本终止。无限递归可视为编程错误


函数的参数

通过给予函数参数,传递讯息给函数,可以放入多个参数用逗号分隔,也可以设置参数默认的值。

1. 向函数传递array:

<?php
function takes_array($nums)
{
    echo '$nums[0] + $nums[1] = ', $nums[0] + $nums[1];
}

从php8开始参数尾巴逗号是会被忽略的

2. 使用尾巴逗号

<?php
function takes_many_args(
    $first_name,
    $last_name,
    $age,
    $gender = 1,
    $cellphone = null, // 在 8.0.0 之前,尾部逗号是不允许的。
)
{
    // ...
}
?>

从 PHP 8.0.0 开始,不推荐在可选参数之後传递强制参数。 这通常可以通过删除默认值来解决。 此规则的一个例外是 Type $param = null 形式的参数,其中 null 默认值使类型隐式可为空。 这种用法仍然被允许,但建议改用显式可为空类型。

3. 在强制参数之後传递可选参数

<?php
function foo($a = [], $b) {} // 之前
function foo($a, $b) {}      // 之後

function bar(A $a = null, $b) {} // 同时可用
function bar(?A $a, $b) {}       // 官方推荐
?>

4. 在函数中使用默认参数

PHP 还允许使用数组 array 和特殊类型 null 作为默认参数。

<?php
function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>

// outputs
// Making a cup of cappuccino.
// Making a cup of .
// Making a cup of espresso.

5. 函数默认参数的不正确用法

默认值必须是常量表达式,不能是,如变量,类成员,或者函数调用等。 注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作。

<?php
function makeyogurt($type = "acidophilus", $flavour)
{
    return "Making a bowl of $type $flavour.\n";
}

echo makeyogurt("raspberry");   // won't work as expected
?>

// Warning: Missing argument 2 in call to makeyogurt()

6. 函数默认参数正确用法

<?php
function makeyogurt($flavour, $type = "acidophilus")
{
    return "Making a bowl of $type $flavour.\n";
}

echo makeyogurt("raspberry");   // works as expected
?>

// outputs
// Making a bowl of acidophilus raspberry.

7. 使用 ... 来访问变量参数

PHP 在用户自定义函数中支持可变数量的参数列表。由 ... 语法实现。

包含 ... 的参数,会转换为指定参数变量的一个数组(类似字典),以下示例:

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

// 10

8. 使用...来传递参数

<?php
function add($a, $b) {
    return $a + $b;
}

echo add(...[1, 2])."\n";

$a = [1, 2];
echo add(...$a);
?>

// 3
// 3

9. 输入提示的变量参数

<?php
function total_intervals($unit, DateInterval ...$intervals) { // 必须传递DateInterval类的参数
    $time = 0;
    foreach ($intervals as $interval) {
        $time += $interval->$unit;
    }
    return $time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' days';

// This will fail, since null isn't a DateInterval object.
echo total_intervals('d', null);
?>

// outputs
// 3 days
// Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, 
// null given, called in - on line 14 and defined in - on line 2

命名函数

PHP 8.0.0 开始引入了命名参数作为现有位置参数的扩展。命名参数允许根据参数名而不是参数位置向函数传参。这使得参数的含义自成体系,参数与顺序无关,并允许任意跳过默认值。

命名参数通过在参数名前加上冒号来传递。允许使用保留关键字作为参数名。参数名必须是一个标识符,不允许动态指定。

10. 命名参数语法

<?php
function myFunction($paramName){
    echo $paramName;
}
myFunction(paramName: $value);  // $value指定给予paramName这个参数
array_foobar(array: $value);

// NOT supported.
function_name($variableStoringParamName: $value); // 不能动态指定
?>

11. 通过位置传参与命名参数的对比

<?php
// 使用顺序传递:
array_fill(0, 100, 50);

// 使用命名参数:
array_fill(start_index: 0, count: 100, value: 50);
?>

顺序不重要,下面输出跟上面一样

<?php
array_fill(value: 50, count: 100, start_index: 0);
?>

12. 不可多次传递给同一个参数

<?php
function foo($param) { ... }

foo(param: 1, param: 2);
// Error: Named parameter $param overwrites previous argument
foo(1, param: 2);
// Error: Named parameter $param overwrites previous argument
?>

资料来源: https://www.php.net/


<<:  [Day10] Vite 出小蜜蜂~Function Composition!

>>:  【Day1】资料结构 + 演算法

Day17 Let's ODOO: Data Files

通常我们在写module的时候,会需要一些初始资料或是固定需要的资料,我们可以定义资料在创立Mode...

[Day21] 物件的基础概念2

今天来介绍如何判定物件与纯值以及关於物件未被定义的属性 物件与纯值 在 JavaScript 只有两...

[Day 3] Atomic Operation

前言 昨天简单猜测了非同步框架所应具备的基本功能 ( 某种资料模式, thread schedule...

【Day06】提升(Hoisting)

我们在进到主题前先来看一段程序码,随後在开发人员工具中观察执行过程 function doSomet...

[Day6] Vite 出小蜜蜂~ Scene 场景!

Day6 Scenes 在 Web 的领域里,一个网站会有页面,像是 Main Page, Logi...