1.爲何要使用函數?php
除了內建的PHP函數,咱們能夠建立咱們本身的函數。
函數是能夠在程序中重複使用的語句塊。
使代碼邏輯更清晰
避免過多的全局變量
封裝後避免相同邏輯重複代碼,只需調用寫好的函數便可
便於維護,僅需修改函數邏輯便可完成全部調用該函數的邏輯修改,不須要多處修改
頁面加載時函數不會當即執行,函數只有在被調用時纔會執行。html
2.函數的結構分析編程
//定義函數 function aa (){ //代碼段 } //調用函數 aa();
3.函數的命名規則
函數的命名規範和變量名的命名規範相同。一般函數都是執行一個動做的,所以函數命名時,通常函數中會包含動詞閉包
//這是一個簡單的命名示例 function aa(){ echo "this is function name aa"; } aa();
4.函數的返回值函數
//用return實現返回 function fan($height,$width){ $area=$height*$width; return $area; } $total=fan(4,3); echo $total ; //結果12,由於3*4=12
5.函數的形參與實參
形參是指function後面小括號裏面的參數。
實參是指調用function函數的時候寫的參數.性能
function abc($a) //這個$a是形參 { $a++; echo $a; } $a=2; abc($a); //這個$a是實參 輸出:3 echo $a; //輸出:2 由於傳進abc裏的是它的一副本 要想在函數內改變該值,能夠用引用傳遞
6.函數的默認值
在php編程中,爲自定義函數設定默認值,當用戶調用該函數時,若是不給參數指定值,參數會用默認值頂替。ui
function printMe($param = NULL) { print $param; } printMe("This is morenzhi function "); printMe(); //This is morenzhi function
7.函數的強類型參數this
function sum($a,$b) { return $a+$b; } var_dump(sum(1,2)); var_dump(sum(1,2.5)); //int(3) float(3.5)
8.函數的可變參數列表spa
//必須在5.6以上版本才能夠運行 function sum(...$numbers) { $acc = 0; foreach( $numbers as $number ) { $acc += $number; } return $acc; } echo sum(1,2,3,4); //輸出 //10
9.函數值傳遞與引用傳遞
區別
(1)按值傳遞:函數範圍內對值的任何改變在函數外部都會被忽略
(2)按引用傳遞:函數範圍內對值的任何改變在函數外部也能反映出這些修改
優缺點:
A:按值傳遞時,php必須複製值。特別是對於大型的字符串和對象來講,這將會是一個代價很大的操做。
B.按引用傳遞則不須要複製值,對於性能提升頗有好處。code
header('content-type:text/html;charset=utf-8'); $hero = array('no1'=>'蝙蝠俠', 'no2'=>'超人'); $hero2 = &$hero; $hero2['no1'] = '蜘蛛俠'; echo '<pre>'; var_dump($hero); var_dump($hero2); $a = null; $b = &$a; $b = 'abc'; var_dump($a, $b); //結果 /* array(2) { ["no1"]=> string(9) "蜘蛛俠" ["no2"]=> string(6) "超人" } array(2) { ["no1"]=> string(9) "蜘蛛俠" ["no2"]=> string(6) "超人" } string(3) "abc" string(3) "abc" */
10.函數變量做用域
在全部函數外定義的變量擁有全局做用域,在函數內部聲明的變量是局部變量,僅能在函數內部訪問。要在一個函數中使用全局變量,須要使用global關鍵字。
//使用global關鍵字 <?php $x=10; $y=20; function test(){ global $x,$y; $y=$x+$y; } test(); echo $y;//輸出30
11.複雜函數-可變函數
若是一個變量名後面有括號,PHP將尋找與該變量值同名的函數,而且嘗試執行它。PHP"可變函數"能夠用來實現包括回調函數、函數表在內的一些用途。
」可變函數「不能用於語言結構,如echo(),print(),unset(),isset(),empty(),include(),require()等,須要使用自定義的包裝函數來將這些結構用做可變函數。
function echoString($str){ echo($str); } $varFun="echoString"; $varFun=("Output String");//輸出"Output String"
12.複雜函數-嵌套函數
嵌套函數,是一種有條件全局,你能夠控制,在什麼狀況下提供這樣的全局函數給用戶使用。但也須要注意,過多的全局函數則會產生「全局污染」,因此,不可多用
function foo() { function bar() { echo "this is qiantao function"; } } /* 如今還不能調用bar()函數,由於它還不存在 */ foo();//結果空 /* 如今能夠調用bar()函數了,由於foo()函數 的執行使得bar()函數變爲已定義的函數 */ bar();//結果this is qiantao function
13.複雜函數-遞歸函數
什麼是遞歸函數?
一個函數在它的函數體內調用它自身稱爲遞歸調用。 這種函數稱爲遞歸函數。
php 遞歸函數的三種實現方式
(1).利用引用作參數
函數之間原本也是各行其是,即使是同名函數。遞歸函數是考慮將引用做爲參數,成爲一個橋樑,造成兩個函數間的數據共享。雖然兩個函數見貌似操做的是不一樣地址,可是實際上操做的是一起內存地址。
function test($a=0,&$result=array()){ $a++; if ($a<10) { $result[]=$a; test($a,$result); } echo $a; return $result; }
本例比較有意思的是 "echo $a" 的值。相信不少人認爲是 12345678910 吧? 其實否則,是 1098765432。爲何呢?由於函數還沒執行"echo $a "前就進行了下一次的函數遞歸。真正執行echo 是$a<10條件不知足的時候,echo 返回a,返回result, 對於上一層而言,執行完遞歸函數,開始執行本層的echo $a,依次類推。
(2).利用全局變量
利用全局變量完成遞歸函數,請確保你確實理解什麼是全局變量。global在函數內申明變量不過是外部變量的同名引用。變量的做用範圍仍然在本函數範圍內。改變這些變量的值,外部同名變量的值天然也改變了。但一旦用了&(引用),同名變量再也不是同名引用。利用全局變量實現遞歸函數不必理解到這麼深的一層,還保持原有對全局變量的見解就能夠瓜熟蒂落理解遞歸函數。
function test1($a=0,$result=array()){ global $result; $a++; if ($a<10) { $result[]=$a; test1($a,$result); } return $result; }
(3).利用靜態變量
咱們經常在類中見到static,今天咱們把它利用到遞歸函數中。請記住static的做用:僅在第一次調用函數的時候對變量進行初始化,而且保留變量值。
function test(){ static $count=0; echo $count; $count++; } test(); test(); test(); test(); test();
請問這一段代碼的執行結果是多少?是 00000 麼?必然不是。 是 01234。 首先第一次調用test(), static對 $count 進行初始化, 其後每一次執行完都會保留 $count 的值, 再也不進行初始化,至關於直接忽略了 static $count=0; 這一句。
於是將static應用到遞歸函數做用可想而知。在將須要做爲遞歸函數間做爲「橋樑"的變量利用static進行初始化,每一次遞歸都會保留"橋樑變量"的值。
function test3($a=0){ static $result=array(); $a++; if ($a<10) { $result[]=$a; test3($a); } return $result; }
總結
所謂遞歸函數,重點是如何處理函數調用自身,是如何保證所須要的結果,得以在函數間合理"傳遞",固然也有不須要函數之間傳值得遞歸函數
14. 複雜函數-匿名(閉包)函數
匿名函數
提到閉包就不得不想起匿名函數,也叫閉包函數(closures),貌似PHP閉包實現主要就是靠它。聲明一個匿名函數是這樣
$func = function() { };//帶結束符
能夠看到,匿名函數由於沒有名字,若是要使用它,須要將其返回給一個變量。匿名函數也像普通函數同樣能夠聲明參數,調用方法也相同:
$func = function( $niming ) { echo $niming; }; $func( 'this is niming function' ); //輸出:this is niming function
實現閉包
將匿名函數在普通函數中當作參數傳入,也能夠被返回。這就實現了一個簡單的閉包。
下邊有三個例子
//例一 //在函數裏定義一個匿名函數,而且調用它 function bibao() { $func = function( $str ) { echo $str; }; $func( 'tihs is bibao' ); } bibao(); //輸出 //tihs is bibao
//例二 //在函數中把匿名函數返回,而且調用它 function getPrintStrFunc() { $func = function( $str ) { echo $str; }; return $func; } $printStrFunc = getPrintStrFunc(); $printStrFunc( 'this is niming function fanhui' ); //輸出 //this is niming function fanhui
//例三 //把匿名函數當作參數傳遞,而且調用它 function callFunc( $func ) { $func( 'this is niming function canshu chuandi' ); } $printStrFunc = function( $str ) { echo $str; }; callFunc( $printStrFunc ); //輸出 //this is niming function canshu chuandi //也能夠直接將匿名函數進行傳遞。若是你瞭解js,這種寫法可能會很熟悉 callFunc( function( $str ) { echo $str; } ); //輸出 //this is niming function canshu chuandi
鏈接閉包和外界變量的關鍵字:USE
閉包能夠保存所在代碼塊上下文的一些變量和值。PHP在默認狀況下,匿名函數不能調用所在代碼塊的上下文變量,而須要經過使用use關鍵字。
有人可能會想到,是否能夠在匿名函數中改變上下文的變量,但我發現是不能夠的:
function getMoney() { $rmb = 1; $func = function() use ( $rmb ) { echo $rmb; //把$rmb的值加1 $rmb++; }; $func(); echo $rmb; } getMoney(); //輸出: //1 //1
原來use所引用的也只不過是變量的一個副本而已。可是我想要徹底引用變量,而不是複製。
要達到這種效果,其實在變量前加一個 & 符號就能夠了:
function getMoney() { $rmb = 1; $func = function() use ( &$rmb ) { echo $rmb; //把$rmb的值加1 $rmb++; }; $func(); echo $rmb; } getMoney(); //輸出: //1 //2