前言

最近在系统的学习 PHP ,参考的资料是《PHP编程》+ 官方文档(如果你有好的学习资料,欢迎推荐给我)。虽然这本《PHP编程》是基于 PHP5 的,但我笔记里的代码,全部在 PHP 7.2 的环境里测试过,是能够运行的。另,本笔记中只记录我模糊不清的知识。

定义函数

嵌套函数

PHP 中可以使用嵌套函数,但是其作用有限。内部函数不能自动取到外部函数的参数。除非外部函数被调用,否则内部函数无法被调用,另外外部函数代码被解析后,内部函数也不可以被调用。如:

  1. function outer ($a)
  2. {
  3. function inner ($b)
  4. {
  5. echo "there $b";
  6. }
  7. echo "$a, hello ";
  8. inner($a)
  9. }
  10. inner("reader"); // error! 因为外部函数还没有被调用
  11. outer("well"); // well, hello there well
  12. inner("reader"); // there reader
  13. outer("well"); // error! 因为外部函数被调用时,内部函数被重定义了

嵌套函数,是一种有条件的全局函数,你可以控制在什么情况下提供这样的全局函数给用户使用。但也需要注意,过多的全局函数则会产生“全局污染”,所以,不可多用。

函数参数

按引用传递参数

按引用传递参数允许忽略普通的作用域规则,可以让函数直接访问和操作参数变量。使用 & 来标识:

  1. function doubler(&$value)
  2. {
  3. $value = $value << 1;
  4. }
  5. $a = 3;
  6. doubler($a);
  7. echo $a;

注意:只有变量(非常量)能被声明为按引用传递的参数。如将上面的例子改成: doubler(10) ,就会引起错误。
优点:按值传递时,PHP 必须复制值。特别时对大的字符串和对象来说,这将是一个昂贵的操作。按引用传递则不需要复制值。
缺点:操作难度相对较高。

可变参数

PHP 在用户自定义函数中支持可变数量的传输列表。
在 PHP 5.5 以及更早的版本中,PHP提供了三个函数用于检索在函数中所传递的参数。

  • func_get_args() ,返回一个提供给函数的所有参数的数组
  • func_num_args() ,返回提供给函数的参数数目
  • func_get_arg(argument_number) ,返回一个来自传输的特定参数。 ``` function countList() { if (func_num_args() == 0) { return false; } else { $count = 0; for ($i = 0; $i < func_num_args(); $i++) {
    1. $count += func_get_arg($i);
    } return $count; } }

echo countList(1, 5, 9); // 15

  1. PHP 5.6 及以上的版本中,由 `...` 语法实现。<br />访问变量参数中使用:

function sum(…$numbers) { $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; }

echo sum(1, 2, 3, 4)

  1. 传递过程中使用:

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

echo add(…[1, 2]).”\n”; // 3

$a = [1, 2]; echo add(…$a); // 3 ?>

  1. ### 类型提示
  2. 当定义一个函数时,你可以要求一个参数是一个特定的类,或是继承自一个特定的接口的实例,一个数组或者一个回调。并在 PHP 7 中增加了对**标量类型**的支持:(`bool`, `float`, `string`, `bool`)。

// Scalar Type Hints function printRecord(string $name, int $id, float $salary, bool $sex) { echo $sex ? “$name, $id, $salary, male.\n” : “$name, $id, $salary, female. \n”; }

printRecord(“Tom”, 101, 5650.00, TRUE); // Tom, 101, 5650, male. printRecord(“Suzy”, 101, 5650.00, FALSE); // Suzy, 101, 5650, female.

  1. PHP 7 中还增加了对函数返回值的的类型提示(这下彻底支持强类型了)

function mySuperFunction(): int { return “5”; }

echo mySuperFunction(); // 5

  1. ### 返回值
  2. 函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。

function returnTwo() { return array(“Fred”, 35); }

  1. 从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 `&`

$names = array(“Fred”, “Barney”, “Wilma” ,”Betty”);

function &findOne($n) { global $names;

  1. return $names[$n];

}

$person =& findOne(1); echo $person, $names[1]; // Barney Barney $person = “Barnetta”; echo $person, $names[1]; // Barnetta Barnetta

  1. PHP 7 中增加了对返回值类型声明的支持。

function sum($a, $b): float { return $a + $b; }

// Note that a float will be returned. var_dump(sum(1, 2)); // float(3)

  1. ## 可变函数
  2. PHP 支持可变函数的概念。这意味着**如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数**,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。

function foo() { echo “In foo()
\n”; }

function bar($arg = ‘’) { echo “In bar(); argument was ‘$arg’.
\n”; }

// 使用 echo 的包装函数 function echoit($string) { echo $string; }

$func = ‘foo’; $func(); // This calls foo()

$func = ‘bar’; $func(‘test’); // This calls bar()

$func = ‘echoit’; $func(‘test’); // This calls echoit()

  1. 如果没有为这个变量存在的函数,则代码执行时会产生一个运行错误。可以使用 `function_exists()` 来确定名为此变量的函数是否存在 `$yesOrNo = function_exists(funcion_name);`。<br />可变函数不能用于例如 [echo](https://www.php.net/manual/zh/function.echo.php),[print](https://www.php.net/manual/zh/function.print.php),[unset()](https://www.php.net/manual/zh/function.unset.php),[isset()](https://www.php.net/manual/zh/function.isset.php),[empty()](https://www.php.net/manual/zh/function.empty.php),[include](https://www.php.net/manual/zh/function.include.php),[require](https://www.php.net/manual/zh/function.require.php) 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。
  2. ## 匿名函数(闭包)
  3. 有些时候,一些函数是局部的和临时的。为了反映回调函数的短暂特性,允许临时创建一个没有指定名字的函数:匿名函数(或也称为闭包)。<br />闭包可以从父作用域中继承变量。 任何此类变量都应该用 _use_ 语言结构传递进去。 PHP 7.1 起,不能传入此类变量: [superglobals](https://www.php.net/manual/zh/language.variables.predefined.php)、 $this 或者和参数重名。

$array = array(“really long string here, body”, “this”, “middling length”, “larger”); $sortOption = “random”;

function sortNonrandom($array) { $sortOption = false;

  1. usort($array, function($a, $b) use ($sortOption){
  2. if ($sortOption == "random"){
  3. // 通过随机返回( -1, 0, 1)进行随机排序
  4. return rand(0,2) - 1;
  5. }else{
  6. // 按照字符长度惊喜排序
  7. return strlen($a) - strlen($b);
  8. }
  9. });
  10. print_r($array);

} print_r(sortNonrandom($array)); // 正常排序

  1. PHP 文档中的一个例子,从父作用域继承变量:

$message = ‘hello’;

// 没有 “use” $example = function () { var_dump($message); }; echo $example(); // 输出如下 // Notice: Undefined variable: message in phpfile on line 6 // NULL

// 继承 $message $example = function () use ($message) { var_dump($message); }; echo $example(); // string(5) “hello”

// 继承变量的值来自定义函数时之前的值,而不是调用时的值 $message = ‘world’; echo $example(); // string(5) “hello”

// 变量更新 $message = ‘hello’;

// 通过引用继承 $example = function () use (&$message) { var_dump($message); }; echo $example(); // string(5) “hello”

// 父作用域中更改的值反映在函数调用内 $message = ‘world’; echo $example(); // string(5) “world”

// 闭包也可以接受常规参数 $example = function ($arg) use ($message) { var_dump($arg . ‘ ‘ . $message); }; $example(“hello”); // string(11) “hello world”

```

感谢你看到了这里。如果文章有错误,请评论指正,谢谢!