前言
最近在系统的学习 PHP ,参考的资料是《PHP编程》+ 官方文档(如果你有好的学习资料,欢迎推荐给我)。虽然这本《PHP编程》是基于 PHP5 的,但我笔记里的代码,全部在 PHP 7.2 的环境里测试过,是能够运行的。另,本笔记中只记录我模糊不清的知识。
定义函数
嵌套函数
PHP 中可以使用嵌套函数,但是其作用有限。内部函数不能自动取到外部函数的参数。除非外部函数被调用,否则内部函数无法被调用,另外外部函数代码被解析后,内部函数也不可以被调用。如:
function outer ($a)
{
function inner ($b)
{
echo "there $b";
}
echo "$a, hello ";
inner($a)
}
inner("reader"); // error! 因为外部函数还没有被调用
outer("well"); // well, hello there well
inner("reader"); // there reader
outer("well"); // error! 因为外部函数被调用时,内部函数被重定义了
嵌套函数,是一种有条件的全局函数,你可以控制在什么情况下提供这样的全局函数给用户使用。但也需要注意,过多的全局函数则会产生“全局污染”,所以,不可多用。
函数参数
按引用传递参数
按引用传递参数允许忽略普通的作用域规则,可以让函数直接访问和操作参数变量。使用 &
来标识:
function doubler(&$value)
{
$value = $value << 1;
}
$a = 3;
doubler($a);
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++) {
} return $count; } }$count += func_get_arg($i);
echo countList(1, 5, 9); // 15
在 PHP 5.6 及以上的版本中,由 `...` 语法实现。<br />访问变量参数中使用:
function sum(…$numbers) { $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; }
echo sum(1, 2, 3, 4)
传递过程中使用:
<?php function add($a, $b) { return $a + $b; }
echo add(…[1, 2]).”\n”; // 3
$a = [1, 2]; echo add(…$a); // 3 ?>
### 类型提示
当定义一个函数时,你可以要求一个参数是一个特定的类,或是继承自一个特定的接口的实例,一个数组或者一个回调。并在 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.
在 PHP 7 中还增加了对函数返回值的的类型提示(这下彻底支持强类型了)
function mySuperFunction(): int { return “5”; }
echo mySuperFunction(); // 5
### 返回值
函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。
function returnTwo() { return array(“Fred”, 35); }
从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 `&` :
$names = array(“Fred”, “Barney”, “Wilma” ,”Betty”);
function &findOne($n) { global $names;
return $names[$n];
}
$person =& findOne(1); echo $person, $names[1]; // Barney Barney $person = “Barnetta”; echo $person, $names[1]; // Barnetta Barnetta
在 PHP 7 中增加了对返回值类型声明的支持。
function sum($a, $b): float { return $a + $b; }
// Note that a float will be returned. var_dump(sum(1, 2)); // float(3)
## 可变函数
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()
如果没有为这个变量存在的函数,则代码执行时会产生一个运行错误。可以使用 `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) 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。
## 匿名函数(闭包)
有些时候,一些函数是局部的和临时的。为了反映回调函数的短暂特性,允许临时创建一个没有指定名字的函数:匿名函数(或也称为闭包)。<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;
usort($array, function($a, $b) use ($sortOption){
if ($sortOption == "random"){
// 通过随机返回( -1, 0, 1)进行随机排序
return rand(0,2) - 1;
}else{
// 按照字符长度惊喜排序
return strlen($a) - strlen($b);
}
});
print_r($array);
} print_r(sortNonrandom($array)); // 正常排序
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”
```
感谢你看到了这里。如果文章有错误,请评论指正,谢谢!