思考:在開發(fā)過程中會(huì)有很多代碼其實(shí)是重復(fù)的,只是其中有一點(diǎn)點(diǎn)數(shù)據(jù)的變化敌厘,那么這樣的代碼我們是通過復(fù)制-粘貼-修改部分的方式來實(shí)現(xiàn)嗎糠亩?
引入:通過復(fù)制-粘貼-修改,的確能夠達(dá)到實(shí)現(xiàn)很多代碼重復(fù)利用的可能鲁驶,但是這種形式莫過于臃腫鉴裹,而且在后期維護(hù)的時(shí)候,如果有一點(diǎn)邏輯的修改钥弯,就需要修改所有使用了重復(fù)代碼的地方径荔,這樣的操作太過繁瑣。所以PHP提供了一種能夠讓代碼重復(fù)利用變得簡(jiǎn)單便捷的方式脆霎,那就是函數(shù)总处。
函數(shù)概念【掌握】
定義:PHP中函數(shù)其實(shí)是一個(gè)具有復(fù)雜邏輯的代碼塊,而這種代碼塊通尘χ耄可以在很多地方重復(fù)使用鹦马。函數(shù)是使用了一種特殊的結(jié)構(gòu)來將要重復(fù)使用的代碼進(jìn)行包裹,后期可以通過定義的函數(shù)名字來直接實(shí)現(xiàn)重復(fù)代碼塊的調(diào)用忆肾。
1.函數(shù)結(jié)構(gòu):函數(shù)是一種特殊的結(jié)構(gòu)荸频,包括多個(gè)要素:關(guān)鍵字function,自定義函數(shù)名客冈,參數(shù)結(jié)構(gòu)旭从,函數(shù)體和返回值5部分。
- function關(guān)鍵字:PHP內(nèi)置的一種關(guān)鍵字郊酒,用來申明結(jié)構(gòu)的本質(zhì)
- 自定義函數(shù)名:緊跟function關(guān)鍵字遇绞,是一種見名知意的字符串,由字母燎窘、數(shù)字和下劃線組成摹闽,其中不能使用數(shù)字開頭(和變量一樣),不區(qū)分大小寫
- 參數(shù)結(jié)構(gòu):是一種外部對(duì)函數(shù)內(nèi)部數(shù)據(jù)進(jìn)行調(diào)整的機(jī)制(數(shù)據(jù)輸入)褐健,分為形參(定義結(jié)構(gòu)時(shí)使用的參數(shù))和實(shí)參(調(diào)用函數(shù)時(shí)傳入的實(shí)際數(shù)據(jù))付鹿,可以沒有參數(shù)
- 函數(shù)體:函數(shù)的核心邏輯部分澜汤,用來實(shí)現(xiàn)某個(gè)功能的具體代碼,在函數(shù)體中可以寫普通的業(yè)務(wù)邏輯實(shí)現(xiàn)代碼
返回值:return + 數(shù)據(jù)舵匾,將函數(shù)得到的結(jié)果對(duì)外返回俊抵,誰調(diào)用返回給誰(數(shù)據(jù)輸出),可以沒有返回值坐梯,系統(tǒng)默認(rèn)返回NULL
2.函數(shù)基礎(chǔ)語法
function 函數(shù)名(形參列表){
//函數(shù)體
return 返回值;
}
<?php
//定義一個(gè)簡(jiǎn)單函數(shù)
function display(){
//該函數(shù)沒有參數(shù)
echo 'hello world';
//該函數(shù)沒有返回值
}
?>
3.函數(shù)調(diào)用:指的是通過找到函數(shù)對(duì)應(yīng)的內(nèi)存地址(函數(shù)名尋找)徽诲,然后實(shí)現(xiàn)函數(shù)內(nèi)部代碼執(zhí)行的過程。調(diào)用方式是通過函數(shù)名字+()的形式實(shí)現(xiàn)
<?php
//調(diào)用函數(shù):函數(shù)名字必須能夠找到函數(shù)定義的結(jié)構(gòu)
display(); //輸出hello world
?>
4.函數(shù)內(nèi)存原理
- 函數(shù)不會(huì)自動(dòng)運(yùn)行吵血,必須通過調(diào)用才會(huì)執(zhí)行函數(shù)內(nèi)部的代碼塊
- 函數(shù)是一種結(jié)構(gòu)谎替,PHP會(huì)先編譯結(jié)構(gòu)加載到內(nèi)存(代碼段),然后才會(huì)從第一行開始執(zhí)行代碼(函數(shù)的定義與調(diào)用沒有順序關(guān)系:PHP特殊)
<?php
//先調(diào)用函數(shù)
display(); //可以調(diào)用(不建議)
//后定義函數(shù)
function display(){
echo 'hello world';
}
?>
- 函數(shù)的調(diào)用是在棧中開辟內(nèi)存運(yùn)行
- 函數(shù)運(yùn)行結(jié)束后蹋辅,會(huì)自動(dòng)釋放函數(shù)所占用的所有內(nèi)存(即函數(shù)內(nèi)部的數(shù)據(jù)變量不能在函數(shù)外訪問)
5.練習(xí):定義一個(gè)函數(shù)實(shí)現(xiàn)九九乘法表的打印輸出钱贯,然后調(diào)用函數(shù)
總結(jié):函數(shù)的目的是實(shí)現(xiàn)代碼的復(fù)用(重復(fù)利用),能夠幫助程序員快速實(shí)現(xiàn)迭代開發(fā)侦另。
思考:函數(shù)的結(jié)構(gòu)是固定的秩命,代碼一旦寫完,以后都是調(diào)用褒傅。那么如何保證函數(shù)能夠根據(jù)用戶的需求來產(chǎn)生實(shí)際所需的結(jié)果呢弃锐?
引入:函數(shù)內(nèi)部結(jié)構(gòu)是固定的,只是表明函數(shù)要實(shí)現(xiàn)的功能以及具體實(shí)現(xiàn)的算法是固定的樊卓,但是就數(shù)據(jù)而言拿愧,可以通過外部傳入來得到數(shù)據(jù)變化的目標(biāo)。這種數(shù)據(jù)的傳入稱之為參數(shù)碌尔。
參數(shù)說明【掌握】
定義:函數(shù)的參數(shù)浇辜,是指函數(shù)在定義過程中所要考慮的外部數(shù)據(jù)的變化來影響最終結(jié)果而定義的虛擬變量(不代表任何真實(shí)數(shù)據(jù):形參),以及實(shí)際調(diào)用過程中外部傳入主導(dǎo)數(shù)據(jù)運(yùn)行的實(shí)際數(shù)據(jù)(實(shí)參)
1.函數(shù)的參數(shù)分為兩種:定義結(jié)構(gòu)的時(shí)候虛擬的數(shù)據(jù)唾戚,叫做形式參數(shù)(形參)柳洋,以及調(diào)用函數(shù)時(shí)傳入的實(shí)際參數(shù)(實(shí)參)
<?php
//定義一個(gè)函數(shù):輸出該數(shù)據(jù)的3次方
function cube($n){
//$n是在函數(shù)定義時(shí)作為數(shù)據(jù)代表的一種虛擬形式(沒有任何值)
echo $n * $n * $n;
}
//調(diào)用函數(shù)
cube(5); //125,5是真實(shí)參與運(yùn)算的數(shù)據(jù)
cube(3); //27
?>
2.函數(shù)形參與實(shí)參的關(guān)系和工作原理
- 形參:是一種形式叹坦,是用來保存函數(shù)調(diào)用時(shí)外部出來的實(shí)際數(shù)據(jù)在函數(shù)內(nèi)部運(yùn)行的變量
- 實(shí)參:是一種數(shù)據(jù)熊镣,可以是數(shù)據(jù)值也可以是變量代表的數(shù)據(jù)
- 工作原理:實(shí)參在函數(shù)調(diào)用時(shí),將數(shù)據(jù)或者變量代表的數(shù)據(jù)傳遞給形參募书,而函數(shù)一旦運(yùn)行結(jié)束绪囱,內(nèi)部的形參所代表的實(shí)際數(shù)據(jù)就會(huì)消失
3.函數(shù)一定在定義時(shí)設(shè)定了形參,那么調(diào)用時(shí)就必須傳入對(duì)應(yīng)的實(shí)際參數(shù)莹捡,否則會(huì)報(bào)錯(cuò)鬼吵;但是實(shí)參可以比形參多,系統(tǒng)會(huì)自動(dòng)忽略(本質(zhì)沒有忽略篮赢,接收了但是不用而已)
<?php
//定義一個(gè)函數(shù):輸出該數(shù)據(jù)的3次方
function cube($n){
echo $n * $n * $n;
}
//調(diào)用函數(shù)
cube(); //錯(cuò)誤:因?yàn)?n沒有任何值齿椅,所以系統(tǒng)提示沒有未定義變量$n
cube(2,3,4); //8琉挖,取第一個(gè)參數(shù)(因?yàn)橹挥幸粋€(gè)形參)
?>
4.練習(xí):定義一個(gè)函數(shù),能夠?qū)崿F(xiàn)不同層級(jí)的空心菱形的打印
總結(jié):參數(shù)是函數(shù)能夠?qū)崿F(xiàn)復(fù)用的重要因素涣脚,在定義一個(gè)可復(fù)用函數(shù)的時(shí)候示辈,一定要考慮清楚,哪些內(nèi)容是可以改變的遣蚀,那么就需要為這類內(nèi)容定義參數(shù)矾麻,通過外部調(diào)用控制來實(shí)現(xiàn)函數(shù)價(jià)值的更大化。
思考:函數(shù)的參數(shù)在定義時(shí)規(guī)定好后妙同,在調(diào)用時(shí)如果傳入不夠就會(huì)報(bào)錯(cuò)射富,但是在某些情況下,絕大部分的時(shí)候不是每次調(diào)用函數(shù)對(duì)應(yīng)的參數(shù)都不同粥帚,那么這個(gè)時(shí)候有沒有好的方式能夠解決這個(gè)問題呢?
引入:函數(shù)定義的參數(shù)目的就是為了方便調(diào)用時(shí)改變限次,如果某個(gè)數(shù)據(jù)其實(shí)很多時(shí)候是不需要改變的芒涡,那么可以采用參數(shù)的默認(rèn)值來解決。
參數(shù)默認(rèn)值
定義:參數(shù)默認(rèn)值卖漫,即函數(shù)在定義的時(shí)候费尽,發(fā)現(xiàn)有些數(shù)據(jù)是外部可變,但是不需要經(jīng)常改變的數(shù)據(jù)的時(shí)候羊始,可以對(duì)形參指定一個(gè)對(duì)應(yīng)的數(shù)據(jù)旱幼,這樣用戶在調(diào)用的時(shí)候,即便不給對(duì)應(yīng)的形參傳遞實(shí)參突委,形參也會(huì)有數(shù)據(jù)去支持函數(shù)運(yùn)行柏卤。
1.函數(shù)參數(shù)默認(rèn)值的指定方式就是在定義的時(shí)候給定默認(rèn)值
<?php
//定義函數(shù):輸出數(shù)值的平方
function square($n = 1){
echo $n ** 2; //**代表指數(shù)
}
?>
2.默認(rèn)值的使用:如果在調(diào)用函數(shù)的時(shí)候指定了對(duì)應(yīng)的參數(shù),那么系統(tǒng)會(huì)使用用戶傳入的參數(shù)匀油,如果用戶沒有傳入?yún)?shù)缘缚,系統(tǒng)才會(huì)使用默認(rèn)參數(shù)
<?php
//調(diào)用
square(10); //100
square(); //1,不會(huì)報(bào)錯(cuò)敌蚜,正確執(zhí)行:使用到了默認(rèn)值
?>
3.默認(rèn)值使用注意事項(xiàng)
- 函數(shù)形參可以沒有默認(rèn)值也可以有多個(gè)默認(rèn)值
- 函數(shù)有默認(rèn)值的參數(shù)必須定義在所有參數(shù)的最后(系統(tǒng)把實(shí)參傳遞給形參是按順序給)
4.練習(xí):定義一個(gè)函數(shù)輸出指定位置的實(shí)際斐波那契數(shù)據(jù)值桥滨,如第4個(gè)是5,給定默認(rèn)值為第10個(gè)
總結(jié):默認(rèn)值是一種給用戶提供方便的參數(shù)方式弛车,合理的使用默認(rèn)值可以節(jié)省一些調(diào)用層面的操作齐媒。
思考:實(shí)參給形參賦值的時(shí)候會(huì)不會(huì)改變實(shí)參本身的數(shù)據(jù)?
引入:實(shí)參給形參賦值的時(shí)候纷跛,默認(rèn)是采用變量的值傳遞方式喻括,也就是說是把實(shí)參的值給形參(新的變量同樣的值),在函數(shù)內(nèi)部運(yùn)行的是形參變量代表的數(shù)據(jù)忽舟,不會(huì)改變外部實(shí)參的數(shù)據(jù)双妨,但是也可以采用引用傳遞(傳址)來讓形參和實(shí)參共用一塊內(nèi)存地址淮阐,從而實(shí)現(xiàn)內(nèi)部改變外部。
參數(shù)傳值方式【了解】
定義:參數(shù)傳值是指函數(shù)在調(diào)用時(shí)刁品,實(shí)參到底是如何傳遞給形參的泣特,他們之間的傳值方式是在函數(shù)定義時(shí)決定的,傳值方式就是變量的傳值方式挑随。默認(rèn)的傳值方式是值傳遞状您。
1.函數(shù)參數(shù)傳值方式:值傳遞,就是將變量的值傳遞給形參兜挨,從而是兩個(gè)不同變量膏孟;引用傳值,就是將實(shí)參的內(nèi)存地址傳遞給形參拌汇,兩個(gè)變量指向同一個(gè)地址柒桑。
<?php
function changeValue($a,&$b){
//&就是地址符號(hào),表示獲取的是外部參數(shù)的地址
$a++;
$b++;
}
$a = 10; //注意:形參的名字與外部定義的變量名字沒有沖突關(guān)系噪舀,只是“恰巧”同名而已
$b = 10;
changeValue($a,$b);
echo $a; //10魁淳,值傳遞,所以不改變外部變量本身
echo $b; //11与倡,引用傳遞界逛,所以內(nèi)部修改影響外部變量
?>
總結(jié):參數(shù)傳值方式默認(rèn)是值傳遞,在實(shí)際開發(fā)中纺座,基本上都是值傳遞息拜。引用傳遞可以在某些特定情況下使用,通常比較底層的開發(fā)使用的比較多净响。
思考:函數(shù)是一種結(jié)構(gòu)少欺,那么這種結(jié)構(gòu)內(nèi)部可以做什么呢?還是什么都能做别惦?
引入:函數(shù)的目的是什么狈茉?是為了實(shí)現(xiàn)某一個(gè)功能定義的代碼塊,而且能夠?qū)崿F(xiàn)復(fù)用掸掸。所以在函數(shù)內(nèi)部去使用一些解決業(yè)務(wù)邏輯的代碼都是可行的氯庆。
函數(shù)體【了解】
定義:函數(shù)體就是在函數(shù)結(jié)構(gòu){}所包含的所有代碼,包括業(yè)務(wù)邏輯實(shí)現(xiàn)代碼和返回值代碼扰付。
1.函數(shù)體中可以使用的代碼或者結(jié)構(gòu)
- 函數(shù)體中可以定義變量保存數(shù)據(jù)
- 函數(shù)體中可以使用分支結(jié)構(gòu)進(jìn)行邏輯判斷
- 函數(shù)體中可以使用循環(huán)實(shí)現(xiàn)數(shù)據(jù)迭代
- 函數(shù)體中可以調(diào)用函數(shù)(與外部調(diào)用方式一樣)
- 函數(shù)體中可以定義函數(shù)(匿名函數(shù))
- 函數(shù)體中可以調(diào)用類(高級(jí))
2.函數(shù)體要做什么:函數(shù)的本質(zhì)是要為了解決某個(gè)特定的問題而生堤撵,所以函數(shù)內(nèi)部的代碼要實(shí)現(xiàn)的功能就是解決一個(gè)問題(通常不要太大),每個(gè)問題都應(yīng)該有對(duì)應(yīng)的函數(shù)來解決羽莺。大問題是通過調(diào)用小問題解決方案(函數(shù))來實(shí)現(xiàn)解決的实昨,這樣能夠最大的實(shí)現(xiàn)代碼的復(fù)用。
總結(jié):函數(shù)體是為了解決某個(gè)特定的小功能的盐固,因此一個(gè)功能應(yīng)該有一個(gè)對(duì)應(yīng)的函數(shù)荒给,盡量不要讓函數(shù)太大丈挟,每個(gè)函數(shù)都可以獨(dú)立解決某個(gè)問題就好。
思考:函數(shù)為了解決某個(gè)問題寫了很多代碼志电,外部調(diào)用函數(shù)即可曙咽,但是外部如何知道函數(shù)是不是真正解決了問題呢?
引入:函數(shù)通常都是用來運(yùn)算得出一個(gè)解決(不局限于數(shù)學(xué)運(yùn)算)挑辆,函數(shù)不對(duì)結(jié)果負(fù)責(zé)塞祈,只做專業(yè)的事情鳍寂,所以函數(shù)會(huì)把執(zhí)行的結(jié)果返回給使用者,使用者再去根據(jù)結(jié)果來進(jìn)行其他邏輯判定利朵。這就是函數(shù)返回值坯临。
函數(shù)返回值【掌握】
定義:函數(shù)返回值是函數(shù)內(nèi)部運(yùn)算的結(jié)果特咆,根據(jù)實(shí)際每個(gè)函數(shù)的功能而定的虚吟,但是返回方式都一樣邀摆,就是使用return + 結(jié)果的形式。函數(shù)可以沒有返回值洁奈,是因?yàn)楹瘮?shù)默認(rèn)返回NULL派撕。
1.函數(shù)一定有返回值:如果用戶指定就會(huì)返回指定結(jié)果,否則返回NULL
<?php
function display(){
echo 'hello world'; //該函數(shù)目標(biāo)是數(shù)據(jù)輸出睬魂,所以不需要返回值
}
var_dump(display()); //NULL,說明函數(shù)最終還是返回了結(jié)果NULL
function getBack(){
return 100;
}
var_dump(getBack()); //100
?>
2.接收返回值:返回值是返回到函數(shù)調(diào)用出镀赌,因此可以通過變量來接收函數(shù)的返回值
<?php
functiton getBack(){
return 100;
}
//接收返回值
$res = getBack();
echo $res; //100
?>
3.return關(guān)鍵字功能:return雖然在函數(shù)中使用的多氯哮,但是它擁有多個(gè)功能
- 在函數(shù)內(nèi)部使用return + 數(shù)據(jù),可以返回?cái)?shù)據(jù)結(jié)果
- 在函數(shù)內(nèi)部使用return代表函數(shù)體執(zhí)行到這行結(jié)束(如果后面還有代碼都不再執(zhí)行)
- return可以代表文檔返回值(這個(gè)在文件包含的時(shí)候才講)
4.練習(xí):定義函數(shù)求出1到100以內(nèi)的所有質(zhì)數(shù)商佛,并以數(shù)組形式返回
總結(jié):函數(shù)返回值屬于函數(shù)的重要組成部分喉钢,絕大部分的函數(shù)都應(yīng)該有返回值,但是通常不會(huì)在函數(shù)內(nèi)部替外部做決定良姆,只是負(fù)責(zé)求出目標(biāo)結(jié)果肠虽。return關(guān)鍵字在函數(shù)內(nèi)代表著函數(shù)結(jié)束,也代表著數(shù)據(jù)的返回玛追。
思考:函數(shù)隨著return出現(xiàn)或者函數(shù)體運(yùn)行完就會(huì)自動(dòng)結(jié)束税课,內(nèi)部的所有數(shù)據(jù)都會(huì)清空,函數(shù)即便調(diào)用N次都會(huì)是一樣的效果痊剖,如果想實(shí)現(xiàn)函數(shù)同一個(gè)函數(shù)多次調(diào)用都能夠共用一些數(shù)據(jù)的話韩玩,該怎么實(shí)現(xiàn)呢?
引入:函數(shù)是個(gè)獨(dú)立的運(yùn)行體陆馁,其所占內(nèi)存控制只在函數(shù)運(yùn)行期有效(即函數(shù)調(diào)用開始到函數(shù)運(yùn)行結(jié)束)找颓。如果想要數(shù)據(jù)能夠在函數(shù)多次調(diào)用都有共用的話,函數(shù)也提供了一種解決方案叮贩,就是靜態(tài)變量击狮。
靜態(tài)變量【掌握】
定義:靜態(tài)變量佛析,即在函數(shù)內(nèi)部使用static關(guān)鍵字修飾的變量,這種變量是在函數(shù)第一次調(diào)用時(shí)執(zhí)行彪蓬,而且只執(zhí)行一次寸莫,在函數(shù)再次調(diào)用時(shí),會(huì)自動(dòng)跳過這一行(不會(huì)再次執(zhí)行)寞焙。這種變量能夠在同一個(gè)函數(shù)多次調(diào)用共享數(shù)據(jù)的變化储狭。
1.基本語法:使用static關(guān)鍵字修飾變量,通常靜態(tài)變量都會(huì)在定義的時(shí)候進(jìn)行初始化(即給定值)
<?php
function getStatic(){
static $c = 0; //靜態(tài)變量
$var = 0; //普通變量
}
?>
2.靜態(tài)變量與函數(shù)內(nèi)定義的普通變量的區(qū)別在于捣郊,初始化那行只會(huì)執(zhí)行一次
<?php
function getStatic(){
static $c = 0; //靜態(tài)變量
$var = 0; //普通變量
//自增輸出
echo $c++,$var++;
}
//調(diào)用
getStatic(); //0,0:第一次調(diào)用辽狈,$c初始化,兩個(gè)都是0開始呛牲,輸出后都變成1
getStatic(); //1,0:第二次調(diào)用刮萌,$c不再初始化,所以是1娘扩,而$var繼續(xù)初始化為0着茸,所以最終輸出變成1,0,$c變2
?>
3.靜態(tài)變量的作用范圍:雖然靜態(tài)變量允許跨函數(shù)共享數(shù)據(jù)琐旁,但是靜態(tài)變量只允許在當(dāng)前函數(shù)內(nèi)部使用涮阔,其他任何地方都用不了
4.練習(xí):制作一個(gè)函數(shù)計(jì)數(shù)器,每次函數(shù)調(diào)用時(shí)灰殴,都提示當(dāng)前函數(shù)是第幾次被調(diào)用
總結(jié):靜態(tài)變量是函數(shù)內(nèi)部的一種特殊變量敬特,它允許同一個(gè)函數(shù)多次調(diào)用時(shí)實(shí)現(xiàn)數(shù)據(jù)共享,但是又規(guī)定只能在函數(shù)內(nèi)部使用牺陶。
思考:函數(shù)外部定義好的變量伟阔,為什么還要通過參數(shù)傳到函數(shù)里面去使用呢?
引入:在PHP中掰伸,任何變量都是有其有效的邊界的皱炉,我們把這種PHP變量能夠工作的邊界叫做作用域
作用域【掌握】
定義:作用域(scope),指的是變量所定義的環(huán)境決定的能夠被訪問的工作區(qū)域狮鸭。在PHP中變量的作用域分為三種:全局作用域合搅、局部作用域和超全局作用域
1.全局作用域:用戶自定義全局變量,但是是在函數(shù)外部定義的變量怕篷。全局作用域的變量能夠在函數(shù)外部的任何地方使用历筝,其生命周期是從定義直到腳本執(zhí)行結(jié)束(手動(dòng)釋放除外)
2.局部作用域:用戶在函數(shù)內(nèi)部定義的局部變量。局部變量只能在函數(shù)內(nèi)部訪問廊谓,函數(shù)外部不能夠訪問梳猪,其生命周期是函數(shù)運(yùn)行時(shí)
3.超全局作用域:能夠在PHP腳本的任何地方使用,包括函數(shù)內(nèi)部(以后還包含在類內(nèi)部)。是系統(tǒng)定義的超全局變量春弥,生命周期是腳本周期
<?php
//作用域
$a = 100; //全局變量呛哟,在全局作用域中訪問
$_GET['age'] = 1; //超全局變量:借助系統(tǒng)變量$_GET
function display(){
$b = 50; //局部變量,只能在局部作用域訪問(函數(shù)自身內(nèi)部)
//echo $a; //錯(cuò)誤:系統(tǒng)提示該變量未定義
echo $_GET['age'];//1:能夠訪問
}
//echo $b; //錯(cuò)誤匿沛,系統(tǒng)提示該變量未定義
echo $_GET['age']; //1扫责,能夠訪問
?>
4.作用域的劃分是為了更好的管理變量的訪問,如果想要在局部作用域(函數(shù)內(nèi)部)訪問全局變量的解決方案如下:
- 所有用戶定義的全局變量都會(huì)放到
GLOBALS是一個(gè)超全局變量鳖孤,可以在任意地方訪問
<?php
$global = '全局變量';
function getGlobal(){
//echo $global; //錯(cuò)誤:直接訪問不了,提示未定義變量
echo $GLBOALS['global']; //全局變量:使用超全局變量可以訪問所有全局變量
}
?>
- 可以通過函數(shù)的參數(shù)將外部變量傳遞到函數(shù)內(nèi)部抡笼,如果想要函數(shù)內(nèi)部訪問且改變的話苏揣,可以采用引用傳值
<?php
$global = '全局變量';
function getGlobal(&$out){ //引用傳值
echo $out;
$out = '局部變量'; //修改引用傳值進(jìn)來的變量,即修改外部變量
}
echo $global; //全局變量
getGlobal($global); //全局變量
echo $global; //局部變量:被函數(shù)內(nèi)部修改過
?>
- 可以使用global關(guān)鍵字在函數(shù)內(nèi)部進(jìn)行引入:global關(guān)鍵字是一個(gè)全局引用/定義變量推姻,如果是引入全局變量平匈,必須使用global定義一個(gè)外部同名變量(global只能聲明變量,不能賦值)
<?php
$out = '全局變量';
function getOut(){
//聲明全局變量
global $out; //不能賦值
echo $out; //全局變量
$out = '局部變量';
}
echo $out; //全局變量
getOut(); //全局變量
echo $out; //局部變量
?>
5.如果函數(shù)內(nèi)部定義的局部變量想在外部全局作用域訪問藏古,解決方案如下:
- 引用傳值:內(nèi)部能訪問外部增炭,固然外部也能訪問內(nèi)部
- 使用global關(guān)鍵字:global關(guān)鍵字的特性是如果全局作用域存在同名變量,則引入拧晕;否則創(chuàng)建一個(gè)對(duì)應(yīng)的全局變量
<?php
function getIn(){
//聲明全局變量
global $out;
$out = 'out';
$in = 'in'; //局部變量
}
//echo $out; //錯(cuò)誤:未定義變量(函數(shù)沒有執(zhí)行過)
getIn();
echo $out; //out
?>
總結(jié):在PHP中作用域的劃分是很清晰的隙姿,外部定義的默認(rèn)只能外部訪問(全局),內(nèi)部定義的就內(nèi)部訪問(局部)厂捞,系統(tǒng)定義的就隨便訪問(超全局)孟辑。通常我們不會(huì)特別的去跨作用域訪問用戶自定義變量,但是系統(tǒng)變量一定會(huì)到處使用的蔫敲。
思考:前面學(xué)過數(shù)據(jù)類型,數(shù)據(jù)類型是進(jìn)行數(shù)據(jù)操作的基礎(chǔ)炭玫,我們不應(yīng)該相信任何外來數(shù)據(jù)奈嘿,那么函數(shù)內(nèi)部如何確定外部數(shù)據(jù)一定是需要的類型的呢?
引入:PHP是一種弱類型語言吞加,因此在函數(shù)真實(shí)業(yè)務(wù)邏輯開發(fā)的時(shí)候裙犹,如果調(diào)用函數(shù)所傳遞的數(shù)據(jù)無法確保是確定的類型(程序員調(diào)用時(shí)明確數(shù)據(jù)是函數(shù)能夠接受的類型除外),那么在函數(shù)內(nèi)部的確需要進(jìn)行數(shù)據(jù)的判定以保證數(shù)據(jù)是安全可靠可操作的(當(dāng)然衔憨,數(shù)據(jù)類型的自動(dòng)轉(zhuǎn)換會(huì)幫助代碼在執(zhí)行時(shí)不會(huì)出大錯(cuò))叶圃。而實(shí)際上PHP7中也提供了一種強(qiáng)制類型的限定,來保證程序拿到的數(shù)據(jù)是有效的践图。
PHP強(qiáng)制類型【了解】
定義:強(qiáng)制類型掺冠,顧名思義,就是在數(shù)據(jù)進(jìn)行操作前就明確數(shù)據(jù)必須是某種指定的格式码党,一旦格式不符合德崭,那么系統(tǒng)就會(huì)報(bào)錯(cuò)斥黑。PHP7中針對(duì)函數(shù)的強(qiáng)制類型分為兩種:強(qiáng)類型參數(shù)和強(qiáng)類型返回值。
1.強(qiáng)類型參數(shù):就是在定義函數(shù)給定形參的時(shí)候眉厨,根據(jù)函數(shù)功能的需求锌奴,強(qiáng)制要求參數(shù)是對(duì)應(yīng)的類型
<?php
function get1($a,$b){
return $a + $b; //$a和$b應(yīng)該是數(shù)值,但是實(shí)際調(diào)用時(shí)可以傳入字符串
}
echo get1('a','1b'); //1憾股,雖然系統(tǒng)會(huì)警告鹿蜀,但是系統(tǒng)也還是會(huì)自己處理結(jié)果
function get2(int $a,int $b){//定義時(shí)規(guī)定參數(shù)必須是整形
return $a + $b;
}
echo get2('a','1b'); //致命錯(cuò)誤:傳入的類型與要求的類型不符
?>
2.強(qiáng)類型返回值:同樣是在定義函數(shù)結(jié)構(gòu)的時(shí)候指定返回值的類型
<?php
function get1(int $a,int $b){
return $a + $b; //沒有強(qiáng)調(diào)返回值:返回值類型根據(jù)$a + $b的結(jié)果而定,$a和$b是整形服球,所以返回值是整形
}
//強(qiáng)制返回值類型
function get2(int $a,int $b):float{ //此處指定返回值類型為float
return $a + $b;
}
var_dump(get1(1,1)); //(int)2
var_dump(get2(1,1)); //(float)2
?>
3.通常在進(jìn)行強(qiáng)制類型控制的時(shí)候茴恰,會(huì)在最上面(所有代碼都沒有寫之前)頂格寫上一行代碼,表示后續(xù)使用強(qiáng)制類型有咨。declare(strict_types = 1)琐簇,但是這句實(shí)際上實(shí)用價(jià)值不高,即便沒有這句座享,聲明的強(qiáng)制類型依然有效婉商。(官方給出的解釋是能夠節(jié)省運(yùn)行時(shí)間,但是沒有實(shí)際的效率說明)
<?php
//使用強(qiáng)制類型
declare(strict_types = 1);
//定義函數(shù)
?>
總結(jié):PHP7中強(qiáng)制類型的出現(xiàn)有利有弊渣叛,利在于明確類型可以提升PHP代碼的運(yùn)行效率丈秩;弊在于PHP本身是一種弱類型語言,強(qiáng)類型的加入會(huì)讓很多程序員不習(xí)慣淳衙,且代碼無法向下兼容(PHP7以前不支持強(qiáng)類型)蘑秽,而且PHP中本身內(nèi)部有很強(qiáng)大的自動(dòng)轉(zhuǎn)換功能,就這個(gè)強(qiáng)類型本身而言不會(huì)出現(xiàn)太大性能提升(PHP中的強(qiáng)類型是在執(zhí)行階段箫攀,而不是在編譯階段)
思考:有的時(shí)候肠牲,需要在函數(shù)內(nèi)部調(diào)用函數(shù)的時(shí)候,無法明確知道外部會(huì)提供什么函數(shù)(尤其是調(diào)用系統(tǒng)函數(shù)的時(shí)候)靴跛,而函數(shù)的調(diào)用又需要通過函數(shù)名來解決缀雳。這個(gè)時(shí)候該怎么辦呢?
引入:在PHP中梢睛,函數(shù)名字調(diào)用函數(shù)的目的是在于通過函數(shù)名去找到函數(shù)的內(nèi)存地址肥印,然后運(yùn)行。也就是說绝葡,如果能夠找到函數(shù)所在地址深碱,就可以實(shí)現(xiàn)函數(shù)的運(yùn)行。在實(shí)際開發(fā)當(dāng)中藏畅,尤其是很多系統(tǒng)已經(jīng)定義的函數(shù)里敷硅,通常會(huì)需要用戶將自己定義的函數(shù)告知系統(tǒng)函數(shù),然后系統(tǒng)函數(shù)去調(diào)用。那么這種實(shí)現(xiàn)的機(jī)制在PHP中用可變函數(shù)解決竞膳。
可變函數(shù)【了解】
定義:可變函數(shù)航瞭,并不是函數(shù)可以變化,而是函數(shù)的名字具有不確定性坦辟,是通過變量來保存函數(shù)名字刊侯,然后也是通過變量+()的方式來實(shí)現(xiàn)函數(shù)的訪問。
1.基本語法
<?php
//定義函數(shù)
function display(){
echo 'hello world';
}
//定義一個(gè)變量:保存一個(gè)字符串與函數(shù)名同名
$var = 'display';
//使用可變函數(shù)訪問函數(shù)
$var(); //display:$var代表的結(jié)果就是display锉走,然后與()結(jié)合就是display()滨彻,所以運(yùn)行display函數(shù)
?>
2.可變函數(shù)通常不是看到一個(gè)函數(shù),然后刻意用變量去訪問挪蹭,而是在不確定函數(shù)名叫做什么的時(shí)候才用這種方式
<?php
//定義一個(gè)函數(shù):獲取N的3次方
function cube($n){
return $n ** 3;
}
//定義函數(shù):函數(shù)內(nèi)部需要通過調(diào)用一個(gè)外部的函數(shù)來輔助操作
function getCube($n,$func_name){
//系統(tǒng)認(rèn)定$func_name一定要是一個(gè)函數(shù)(回調(diào)函數(shù))
echo $func_name($n); //調(diào)用外部函數(shù)亭饵,同時(shí)傳入?yún)?shù)
}
getCube(10,'cube'); //1000,將cube這個(gè)外部函數(shù)名傳入給一個(gè)函數(shù)梁厉,函數(shù)在內(nèi)部調(diào)用cube(回調(diào)函數(shù)的原理就是如此)
?>
總結(jié):可變函數(shù)一般不會(huì)用辜羊,但是在一些大的函數(shù)(實(shí)現(xiàn)功能比較復(fù)雜,需要多個(gè)函數(shù)執(zhí)行)或者系統(tǒng)函數(shù)或者對(duì)外提供接口時(shí)词顾,會(huì)用到這個(gè)知識(shí)八秃。
思考:在開發(fā)過程中,是不是所有的功能都需要自己開發(fā)肉盹?有沒有一些現(xiàn)成的函數(shù)呢昔驱?如果有該怎么去找到,以及怎么用呢上忍?
引入:一個(gè)成熟的編程語言骤肛,其強(qiáng)大之處無外乎兩種:一是自己有強(qiáng)大的庫(kù),能夠支持幾乎各種業(yè)務(wù)開展窍蓝;還有一種就是擁有強(qiáng)大的擴(kuò)展腋颠,提供很多操作接口。PHP作為一種有資歷吓笙、成熟且市場(chǎng)應(yīng)用率極高的語言秕豫,這兩種強(qiáng)大都有。
PHP常用系統(tǒng)函數(shù)【掌握】
定義:系統(tǒng)函數(shù)观蓄,即系統(tǒng)已經(jīng)在開發(fā)的時(shí)候就考慮到一些常見的功能,并且系統(tǒng)開發(fā)者已經(jīng)將這些通用的功能進(jìn)行了函數(shù)封裝祠墅,一般都會(huì)放到對(duì)應(yīng)的操作手冊(cè)中侮穿,并且告訴開發(fā)者怎么用。用戶只需要在開發(fā)手冊(cè)中找到這些函數(shù)就可以參照使用了毁嗦。
1.操作手冊(cè)一般是官方開發(fā)提供亲茅,提供了系統(tǒng)中的很多操作要素。函數(shù)作為其中一種常見的幫助,有很詳細(xì)的講解和使用克锣。操作手冊(cè)PHP格式較多的是chm文件茵肃。PHP操作手冊(cè)的使用通常分為三種:明確尋找,半模糊匹配袭祟,功能檢索
- 明確尋找:指明確知道自己要找的是什么樣的擴(kuò)展里的函數(shù)验残,那么可以通過對(duì)應(yīng)的“函數(shù)參考”來尋找,進(jìn)入到對(duì)應(yīng)的擴(kuò)展功能分類中即可(這種通常是有一定熟練度)
PHP操作手冊(cè)2.png
- 半模糊匹配:指通過索引功能巾乳,使用自己已經(jīng)知道(或者猜測(cè)您没,如數(shù)組應(yīng)該是array開頭)部分開頭或者分類的,但是不確定是不是有或者具體是哪個(gè)胆绊,可以輸入部分氨鹏,然后會(huì)自動(dòng)匹配合適的,再去選擇自己想要的即可(不能是中堅(jiān)部分压状,一定要開頭)
PHP操作手冊(cè)3.png
- 功能檢索:這個(gè)是完全不知道有沒有或者什么開頭仆抵,然后看看能不能匹配上。在搜索欄中輸入自己想要功能的關(guān)鍵字(越準(zhǔn)確越好种冬,可以使用中文匹配:前提是中文操作手冊(cè))
- 函數(shù)查看:查看函數(shù)的目的在于函數(shù)如何用镣丑,能夠解決需要解決的問題。因此函數(shù)的查看主要看三部分:返回值碌廓,函數(shù)參數(shù)數(shù)量及其類型
PHP操作手冊(cè)5.png
2.常見輸出類:幫助程序員進(jìn)行數(shù)據(jù)輸出或者調(diào)試數(shù)據(jù)
- echo:一種語法結(jié)構(gòu)传轰,不是函數(shù),不需要使用括號(hào)
- print_r:輸出變量的結(jié)構(gòu)谷婆,方便查看
- var_dump:也是一種語法結(jié)構(gòu)慨蛙,詳細(xì)打印變量的結(jié)構(gòu)和數(shù)據(jù)
- exit/die:輸出消息并終止腳本執(zhí)行
3.時(shí)間日期類:幫助程序員進(jìn)行時(shí)間操作管理
- time:獲取當(dāng)前時(shí)間的時(shí)間戳(從格林威治時(shí)間1970年1月1日0點(diǎn)0分0秒開始)
- date:按照指定格式輸出時(shí)間,可以是當(dāng)前時(shí)間也可以是指定時(shí)間戳
- strtotime:將任何英文文本日期時(shí)間描述轉(zhuǎn)換成時(shí)間戳
- microtime:獲取時(shí)間戳和微妙數(shù)(精度高)
4.數(shù)學(xué)類:幫助程序員進(jìn)行數(shù)學(xué)操作
- max:獲取多個(gè)數(shù)中最大的(可以是數(shù)組)
- min:獲取多個(gè)數(shù)中最小的(可以是數(shù)組)
- floor:舍去法取整(向下取整)纪挎,獲取不大于當(dāng)前數(shù)值的最大整數(shù)
- ceil:進(jìn)一取整(向上取整)期贫,獲取不小于指定數(shù)值的最小整數(shù)
- mt_rand:獲取指定區(qū)間或者0到最大數(shù)之間的一個(gè)隨機(jī)整數(shù)
- round:根據(jù)指定的小數(shù)位進(jìn)行四舍五入
5.字符串類:幫助程序員對(duì)字符串進(jìn)行基本操作
- addslashes:對(duì)ASCII中的特殊字符進(jìn)行轉(zhuǎn)義,通常對(duì)用戶輸入的內(nèi)容進(jìn)行特殊處理
- htmlsmpecialchars:將HTML特殊符號(hào)轉(zhuǎn)換成實(shí)體
- htmlspecialchars_decode:將實(shí)體符號(hào)轉(zhuǎn)換成普通字符
- chr:將ASCII對(duì)應(yīng)的數(shù)值轉(zhuǎn)換成對(duì)應(yīng)的符號(hào)
- ord:將ASCII字符轉(zhuǎn)換成對(duì)應(yīng)的數(shù)值
- explode:將字符串按照指定的符號(hào)分隔异袄,得到一個(gè)數(shù)組
- implode:將一個(gè)數(shù)組按照指定的符號(hào)連接成一個(gè)字符串
- md5:使用md5算法對(duì)數(shù)據(jù)進(jìn)行加密
- str_repeat:將字符串重復(fù)指定次數(shù)
- str_replace:字符串替換
- str_shuffle:隨機(jī)打亂一個(gè)字符串
- str_split:按照指定長(zhǎng)度將數(shù)組分割通砍,返回?cái)?shù)組
- strip_tags:去除HTML和PHP標(biāo)記
- strlen:獲取字符串的長(zhǎng)度(字節(jié)長(zhǎng)度)
- stripos/strpos:查找字符串中首次出現(xiàn)目標(biāo)字符串的位置
- substr:從字符串中截取指定位置和長(zhǎng)度的子字符串
- trim:去除字符串兩邊的空格(默認(rèn)是空格,也可以是其他字符)
- ucfirst:將字符串首字母大寫
- strtolower:將所有字母小寫
- strtoupper:將所有字母大寫
- strstr:獲取字符串中某個(gè)字符首次出現(xiàn)到最后的字符串
6.數(shù)組函數(shù):幫助程序員對(duì)數(shù)據(jù)進(jìn)行操作
- array_key_exists:判斷下標(biāo)是否在數(shù)組中存在
- array_keys:獲取數(shù)組全部下標(biāo)烤蜕,或某個(gè)確定值的下標(biāo)
- array_merge:合并數(shù)組元素(相同字符串下標(biāo)元素是覆蓋)
- array_pop:從數(shù)組最后彈出一個(gè)元素(原數(shù)組元素減少)
- array_push:從數(shù)組最后加入一個(gè)元素(原數(shù)組元素增加)
- array_unshift:從數(shù)組最前面加入一個(gè)元素(原數(shù)組元素增加)
- array_shift:從數(shù)組最前面彈出一個(gè)元素(原數(shù)組元素減少)
- shuffle:將原始數(shù)組打亂
- in_array:判斷元素是否在數(shù)組中存在
- range:生成一個(gè)規(guī)則數(shù)值數(shù)組
- current:獲取當(dāng)前數(shù)組指針?biāo)谖恢玫闹?/li>
- next:將數(shù)組元素指針向后移動(dòng)一位封孙,并獲取新元素的值
- prev:與next相反,向前移動(dòng)
- end:指針移動(dòng)到最后一個(gè)元素讽营,并獲取元素值
- reset:重置數(shù)組指針(回到第一個(gè)元素)
- list:語法結(jié)構(gòu)虎忌,從數(shù)組中獲取數(shù)據(jù),并且將數(shù)據(jù)賦值給變量