function Func_1(){ } //合法 function func1(){ } //合法 function _func1(){ } //合法 function Func-1(){ } // 非法,不能包含 '-' function 1_func(){ }// 非法,不能以數字開頭
在此所說的字母是 a-z,A-Z,以及 ASCII 字符從 127 到 255(0x7f-0xff)。
所以實際上使用中文變量名也是合法的。
甚至使用中文的標點符號做爲變量名都是合法的。
只是通常都不推薦這樣用。
// 使用中文函數名和變量名 function 面積($長, $寬){ return $長 * $寬; } echo 面積(2, 3); // 合法,輸出 '6' // 中文符號函數名 function ?。……(){ return '中文符號'; } echo ?。……(); // 合法,輸出 '中文符號'
function Func(){ return 'Func'; } echo func(); // 輸出 'Func'
函數名不區分大小寫,不過在調用函數的時候,使用其在定義時相同的形式是個好習慣。php
函數中包含其餘函數express
function foo() { function bar() { echo "I don't exist until foo() is called."; } } /* 如今還不能調用bar()函數,由於它還不存在 */ foo(); /* 如今能夠調用bar()函數了,由於foo()函數的執行使得bar()函數變爲已定義的函數 */ bar(); // 輸出 'I don't exist until foo() is called.'
函數中包含類編程
function foo() { class Bar{ public $a = 1; } } /* 如今還不能實例化 Bar 類,由於它還不存在 */ foo(); $bar = new Bar(); echo $bar->a; // 輸出 '1'
示例見上面兩個例子
foo(); // 輸出 'foo' function foo() { echo 'foo'; }
定義 foo()
函數的代碼不會被執行數組
foo(); // PHP Fatal error: Uncaught Error: Call to undefined function foo() if (false) { function foo() { echo 'foo'; } }
function foo(){ echo 0; } function foo() { echo 1; } // PHP Fatal error: Cannot redeclare foo() (previously declared
function recursion($a) { if ($a <= 5) { echo "$a\n"; recursion($a + 1); } } echo recursion(0);
輸出閉包
0 1 2 3 4 5
要避免遞歸函數/方法調用超過 100-200 層,由於可能會使堆棧崩潰從而使當前腳本終止。 無限遞歸可視爲編程錯誤。
遞歸次數過多app
function recursion($a) { if ($a <= 300) { echo "$a\n"; recursion($a + 1); } } echo recursion(0); // PHP Fatal error: Uncaught Error: Maximum function nesting level of '256' reached, aborting!
function square($num = 0) { echo $num * $num; } echo square(3), "\n"; echo square(), "\n";
輸出函數
9 0
function sum(...$numbers) { $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; } echo sum(1); // 輸出 1 echo sum(1, 2); // 輸出 3 echo sum(1, 2, 3); // 輸出6
經過參數列表能夠傳遞信息到函數,多個參數之間以逗號做爲分隔符。參數是從左向右求值的。ui
PHP 支持經過值傳遞參數(默認),經過引用傳遞參數以及參數默認值。也支持可變長度的參數列表。this
默認狀況下,函數參數經過值傳遞,即便在函數內部改變參數的值,它並不會改變函數外部的值。.net
function addition($num) { $num++; } $num = 1; addition($num); echo $num; // 輸出 1
若是但願函數能夠修改傳入的參數值,必須經過引用傳遞參數。
若是但願函數的一個參數經過引用傳遞,能夠在定義函數時該參數的前面加上符號 &
。
function addition(& $num) { $num++; } $num = 1; addition($num); echo $num; // 輸出 2
使用引用傳遞參數,調用函數是隻能傳變量,不能直接傳值。
function addition(& $num) { $num++; } addition(1); // PHP Fatal error: Only variables can be passed by reference
function makecoffee($type = "cappuccino") { return "Making a cup of $type.\n"; } echo makecoffee(); // Making a cup of cappuccino. echo makecoffee(null); // Making a cup of . echo makecoffee("espresso"); // Making a cup of espresso.
function makecoffee($types = ["cappuccino"], $coffeeMaker = NULL) { $device = is_null($coffeeMaker) ? "hands" : $coffeeMaker; return "Making a cup of ".join(", ", $types)." with $device.\n"; } echo makecoffee(); // Making a cup of cappuccino with hands. echo makecoffee(["cappuccino", "lavazza"], "teapot"); // Making a cup of cappuccino, lavazza with teapot.
function makecoffee($type = "cappuccino", $coffeeMaker) { return "Making a cup of {$type} with {$coffeeMaker}."; } echo makecoffee(null, 'Jack'); // Making a cup of with Jack. echo makecoffee('Jack'); // PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function makecoffee(), 1 passed in XX and exactly 2 expected in XX
類型聲明容許函數在調用時要求參數爲特定類型。 若是給出的值類型不對,那麼將會產生一個錯誤: 在PHP 5中,這將是一個可恢復的致命錯誤,而在PHP 7中將會拋出一個TypeError異常。
爲了指定一個類型聲明,類型應該加到參數名前。這個聲明能夠經過將參數的默認值設爲NULL來實現容許傳遞NULL。
類型 | 描述 | 最小PHP版本 |
---|---|---|
Class/interface name | 該參數必須是給定類或接口的實例(instanceof)。 | PHP 5.0.0 |
self | 參數必須是當前方法所在類的實例(instanceof)。只能在類和實例方法上使用。 | PHP 5.0.0 |
array | 參數必須是數組(array) | PHP 5.1.0 |
callable | 參數必須是有效的 callable | PHP 5.4.0 |
bool | 參數必須是布爾值 | PHP 7.0.0 |
float | 參數必須是浮點數 | PHP 7.0.0 |
int | 參數必須是整數 | PHP 7.0.0 |
string | 參數必須是字符串 | PHP 7.0.0 |
默認狀況下,若是能作到的話,PHP將會強迫錯誤類型的值轉爲函數指望的標量類型。
例如,一個函數的一個參數指望是string,但傳入的是integer,最終函數獲得的將會是一個string類型的值。
function toString(string $var) { return $var; } var_dump(toString(1)); // string(1) "1"
能夠基於每個文件開啓嚴格模式。
在嚴格模式中,只有一個與類型聲明徹底相符的變量纔會被接受,不然將會拋出一個TypeError。 惟一的一個例外是能夠將integer傳給一個指望float的函數。
可使用 declare 語句和strict_types 聲明來啓用嚴格模式:啓用嚴格模式同時也會影響返回值類型聲明。
declare(strict_types=1); function toString(string $var) { return $var; } toString(1); // PHP Fatal error: Uncaught TypeError: Argument 1 passed to toString() must be of the type string, integer given
將integer傳給一個指望float的函數
declare(strict_types=1); function toFloat(float $var) { return $var; } $int = 1; var_dump($int); // int(1) var_dump(toFloat($int)); // double(1)
嚴格類型適用於在啓用嚴格模式的文件內的函數調用,而不是在那個文件內聲明的函數。一個沒有啓用嚴格模式的文件內調用了一個在啓用嚴格模式的文件中定義的函數,那麼將會遵循調用者的偏好(弱類型),而這個值將會被轉換。嚴格類型僅用於標量類型聲明,也正是由於如此,才須要PHP 7.0.0 或更新版本,由於標量類型聲明也是在這個版本中添加的。
PHP 在用戶自定義函數中支持可變數量的參數列表。在 PHP 5.6 及以上的版本中,由 ... 語法實現;在 PHP 5.5 及更早版本中,使用函數 func_num_args(),func_get_arg(),和 func_get_args() 實現。
...
(in PHP 5.6+)function sum(...$numbers) { $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; } echo sum(1); // 輸出 1 echo sum(1, 2); // 輸出 3 echo sum(1, 2, 3); // 輸出6
func_num_args()
,func_get_arg()
和 func_get_args()
(PHP 5.5)function sum() { $acc = 0; foreach (func_get_args() as $n) { $acc += $n; } return $acc; } echo sum(1); // 輸出 1 echo sum(1, 2); // 輸出 3 echo sum(1, 2, 3); // 輸出6
值經過使用可選的返回語句(return)返回
能夠返回包括數組和對象的任意類型。
返回語句會當即停止函數的運行,而且將控制權交回調用該函數的代碼行。
函數不能返回多個值,但能夠經過返回一個數組來獲得相似的效果。
若是省略了 return,則返回值爲 NULL。
function sum($a, $b) { $a + $b; } var_dump(sum(1, 2)); // NULL
若是在一個函數中調用 return 語句,將當即結束此函數的執行並將它的參數做爲函數的值返回。
return 也會終止 eval() 語句或者腳本文件的執行。
$expression = 'echo "我在return以前"; return; echo "我在return以後";'; eval($expression); // 輸出「我在return以前」
若是在全局範圍中調用 return,則當前腳本文件停止運行。
若是在主腳本文件中調用 return,則腳本停止運行。
若是當前腳本文件是被 include 或者 require 的,則控制交回調用文件。此外,return 的值會被看成 include 或者 require 調用的返回值。
a.php
<?php $b = require 'b.php'; $c = include 'c.php'; echo $b; echo $c; return; echo '我在a.php return以後';
b.php
<?php return "我是b.php\n"; echo '我在b.php return以後';
c.php
<?php return "我是c.php\n"; echo '我在c.php return以後';
運行 a.php,輸出結果爲:
我是b.php 我是c.php
若是當前腳本文件是在 php.ini 中的配置選項 auto_prepend_file 或者 auto_append_file 所指定的,則此腳本文件停止運行。
Note: 注意既然 return 是語言結構而不是函數,所以其參數沒有必要用括號將其括起來。一般都不用括號,實際上也應該不用,這樣能夠下降 PHP 的負擔。Note: 若是沒有提供參數,則必定不能用括號,此時返回 NULL。若是調用 return 時加上了括號卻又沒有參數會致使解析錯誤。
Note: 當用引用返回值時永遠不要使用括號,這樣行不通。只能經過引用返回變量,而不是語句的結果。若是使用 return ($a); 時其實不是返回一個變量,而是表達式 ($a) 的值(固然,此時該值也正是 $a 的值)。
從函數返回一個引用,必須在函數聲明和指派返回值給一個變量時,都使用引用運算符 &
function &myFunc() { static $b = 10; return $b; } $a = myFunc(); $a = 100; echo myFunc(); // 10; $a = &myFunc(); $a = 100; echo myFunc(); // 100;
PHP 支持可變函數的概念。
這意味着若是一個變量名後有圓括號,PHP 將尋找與變量的值同名的函數,而且嘗試執行它。
可變函數能夠用來實現包括回調函數,函數表在內的一些用途。
可變函數不能用於例如 echo,print,unset(),isset(),empty(),include,require 以及相似的語言結構。
須要使用本身的包裝函數來將這些結構用做可變函數。
function foo() { return "I'm foo()\n"; } // 使用 echo 的包裝函數 function echoit($string) { echo $string; } $func = 'foo'; echo $func(); // This calls foo(),輸出「I'm foo()」 $func = 'echoit'; $func($func); // This calls echoit(),輸出「echoit」 $func = 'echo'; echo($func); // 輸出「echo」 $func($func); // PHP Fatal error: Uncaught Error: Call to undefined function echo()
能夠用可變函數的語法來調用一個對象的方法
class Foo { function variable() { $name = 'bar'; $this->$name(); // This calls the Bar() method } function bar() { echo "This is Bar"; } } $foo = new Foo(); $funcName = "variable"; $foo->$funcName(); // This calls $foo->variable(),輸出「This is Bar」
當調用靜態方法時,函數調用要比靜態屬性優先
class Foo { static $variable = 'static property'; static function variable() { echo 'Method Variable called'; } } echo Foo::$variable; // 輸出 'static property'. $variable = "variable"; Foo::$variable(); // 調用 $foo->variable(),輸出「Method Variable called」
能夠調用存儲在標量內的 callable(PHP 5.4+)
class Foo { static function bar() { echo "bar\n"; } function baz() { echo "baz\n"; } } $func = ["Foo", "bar"]; $func(); // 輸出 "bar" $func = [new Foo, "baz"]; $func(); // 輸出 "baz" $func = "Foo::bar"; $func(); // 自 PHP 7.0.0 版本起會輸出 "bar"; 在此以前的版本會引起致命錯誤
匿名函數(Anonymous functions),也叫閉包函數(closures),容許 臨時建立一個沒有指定名稱的函數。
最常常用做回調函數(callback)參數的值。
匿名函數目前是經過 Closure 類來實現的。
PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。把一個 closure 對象賦值給一個變量的方式與普通變量賦值的語法是同樣的,最後也要加上分號。
$greet = function($name) { printf("Hello %s \n", $name); }; $greet('World'); // Hello World $greet('PHP'); // Hello PHP
任何此類變量都應該用 use 語言結構傳遞進去。
PHP 7.1 起,不能傳入此類變量: superglobals、 $this 或者和參數重名。
$message = 'hello'; // 沒有 "use" $example = function () { var_dump($message); }; echo $example(); // PHP Notice: Undefined variable: message // 繼承 $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"
$message = 'world'; $example = function ($arg) use ($message) { var_dump($arg . ' ' . $message); }; $example("hello"); // string(11) "hello world"
//聲明函數swap,做爲下面匿名函數的回調函數 function swap(&$x, &$y) { $temp = $x; $x = $y; $y = $temp; return; } //call_user_func調用的回調函數 function add($a, $b) { return $a + $b; } //匿名函數,即不聲明函數名稱而使用一個變量來代替函數聲明 $fuc = function ($fucName) { $x = 1; $y = 2; //調用回調函數 $fucName($x, $y); echo 'x=' . $x . ',y=' . $y, "\n"; //與$fucName($x, $y)相同效果 //這裏沒法調用swap方法,由於swap方法是對參數引用傳值 //call_user_func與call_user_func_array都沒法調用引用傳參形式的函數 echo call_user_func('add', $x ,$y); }; //調用 $fuc $fuc('swap');
輸出:
x=2,y=1 3
$var1 = 5; $var2 = 10; function foo(&$my_var) { global $var1; $var1 += 2; $var2 = 4; $my_var += 3; return $var2; } $my_var = 5; echo foo($my_var). "\n"; echo $my_var. "\n"; echo $var1; echo $var2; $bar = 'foo'; $my_var = 10; echo $bar($my_var). "\n";
第14行調用 foo()
方法
function foo(&$my_var) { global $var1; // 5 $var1 += 2; // 7 $var2 = 4; // 4 $my_var += 3; // 8 return $var2; // 4 } $my_var = 5; echo foo($my_var). "\n"; // 4
第14行到第17行輸出的值分別爲:
echo foo($my_var). "\n"; // 4 echo $my_var. "\n"; // 8 echo $var1; // 7 echo $var2; // 10
第20行再次調用foo()
方法
function foo(&$my_var) { global $var1; // 7 $var1 += 2; // 9 $var2 = 4; // 4 $my_var += 3; // 13 return $var2; // 4 } $bar = 'foo'; $my_var = 10; echo $bar($my_var). "\n"; // foo($my_var) => 4