函數(shù)的定義
函數(shù)是什么?
函數(shù)(function
)是一段完成指定任務(wù)的已命名代碼塊。函數(shù)可以遵照給它的一組值或參數(shù)完成特定的任務(wù)厕宗,并且可能返回一個(gè)值。在PHP中有兩種函數(shù):自定義函
數(shù)與系統(tǒng)函數(shù)
灵巧。
函數(shù)的優(yōu)越性:
- 控制程序設(shè)計(jì)的復(fù)雜性
- 提高軟件的可靠性
- 提高軟件的開(kāi)發(fā)效率
- 提高軟件的可維護(hù)性
- 提高程序的重用性
自定義函數(shù)
自定義函數(shù)語(yǔ)法格式:
創(chuàng)建函數(shù)
function 函數(shù)名稱(chēng)([參數(shù)1 [,參數(shù)2 [,…]]]){
程序內(nèi)容敘述(也叫函數(shù)體)抬虽;
[return 返回值;] //如需函數(shù)有返回值時(shí)使用
}
調(diào)用函數(shù):
函數(shù)名稱(chēng)([參數(shù)1 [,參數(shù)2 [,…]]];
1.自定義函數(shù)的名稱(chēng):
它是函數(shù)在程序代碼中的識(shí)別名稱(chēng)刑峡,函數(shù)名可以是以字母或下劃線開(kāi)頭后跟零個(gè)或多個(gè)字母洋闽、下劃線和數(shù)字的任何字符串。函數(shù)名不區(qū)分大小寫(xiě)突梦。命名函數(shù)時(shí)不可使用已聲明的函數(shù)诫舅,或PHP內(nèi)建的函數(shù)名稱(chēng)。
2.參數(shù):
所謂的參數(shù)就是用來(lái)把數(shù)值由函數(shù)外部傳入函數(shù)體中宫患,并用來(lái)加以運(yùn)算處理刊懈。參數(shù)之間用“ ,”號(hào)隔開(kāi)。當(dāng)函數(shù)不需要任何數(shù)值傳入時(shí)虚汛,可以省略參數(shù)匾浪。
3.返回值:
當(dāng)調(diào)用函數(shù)時(shí)需要它返回一些數(shù)值,那么就要函數(shù)體中用return語(yǔ)句實(shí)現(xiàn)卷哩。格式如下:
return 返回值蛋辈; //返回值也可以是一個(gè)表達(dá)式
exit(); //無(wú)返回值 void
實(shí)例:
<?php
echo “用函數(shù)求累加:<br>";
function test($a)
{
$sum=0;
for($i=0;$i<=$a;$i++)
$sum+=$i;
return $sum;
}
echo "50的累加是:".test(50)."<br>";
echo "100的累加是:".test(100)."<br>";
?>
在PHP中,函數(shù)可以在被調(diào)用之前定義将谊,也可以在被調(diào)用之后定義冷溶。
function_exists()
- - 判斷函數(shù)是否存在。
PHP變量的范圍
變量的范圍
當(dāng)主程序調(diào)用函數(shù)時(shí)尊浓,PHP 會(huì)暫時(shí)停止目前主要程序流程的運(yùn)行挂洛,并傳遞必要的運(yùn)算參數(shù)給目標(biāo)函數(shù)使用,以執(zhí)行函數(shù)的程序碼片段眠砾。
在函數(shù)執(zhí)行結(jié)束后虏劲,函數(shù)會(huì)回傳執(zhí)行結(jié)果所得的數(shù)值,并將執(zhí)行流程轉(zhuǎn)回原本主程序中斷的地方褒颈,繼續(xù)執(zhí)行運(yùn)作柒巫。
變量的能見(jiàn)度
所謂變量的能見(jiàn)度,意指變量在程序中的可作用范圍谷丸。當(dāng)一個(gè)變量執(zhí)行賦值動(dòng)作后堡掏,會(huì)隨著聲明局部的差異,而有不同的作用范圍刨疼。大致上來(lái)說(shuō)變量會(huì)依據(jù)聲明的局部分為下列兩種:局部變量和全局變量
局部變量(內(nèi)部變量)
在函數(shù)之中聲明的變量就是局部變量泉唁,并且該變量只有在函數(shù)范圍之中才能加以使用。如果其它程序局部需要調(diào)用使用該變量值時(shí)揩慕,必須透過(guò)「return」指令亭畜,來(lái)將其傳回至主程序區(qū)塊以作后續(xù)處理。
<?php
$a=0;
function print_A(){
$a = 3; //定義局部變量
echo "在函數(shù)中顯示局部變量 a 值: $a <p>";
return $a;
}
$b = print_A();
echo "在函數(shù)外顯示局部變量 b 值: $b <br>";
echo $a;
?>
全局變量
在函數(shù)范圍之外所聲明的變量就是全局變量迎卤。由于函數(shù)可以視為單獨(dú)的程序片段拴鸵,所以局部變量會(huì)復(fù)蓋全局變量的能見(jiàn)度,因此在函數(shù)中并無(wú)法直接調(diào)用使用全局變量蜗搔。
函數(shù)中若要使用全局變量時(shí)劲藐,必須要利用global
關(guān)鍵字定義目標(biāo)變量,以告訴函數(shù)主體此變量為全局樟凄。
<?php
$A=“Hello !!”; //定義全局變量
function print_A() { //定義函數(shù) print_A()
global $A; //利用 global 關(guān)鍵字聲明變量 A 為全局變量
echo $A;
}
print_A();
?>
也可以使用預(yù)定義的全局變量數(shù)組$GLOBALS
.這是一個(gè)特殊變量在程序運(yùn)行時(shí)自動(dòng)創(chuàng)建聘芜。格式:echo $GLOBALS[“A”];
注意事項(xiàng)
在函數(shù)中聲明全局變量時(shí),其名字要與全局變量一致
通過(guò)unset($var)可以手動(dòng)刪除變量缝龄,變量會(huì)在內(nèi)存中被釋放汰现,也就不在全局作用域中了挂谍。
使用require與include包含不會(huì)影響作用域
通過(guò)參數(shù)列表傳遞給函數(shù)的變量,對(duì)于函數(shù)來(lái)說(shuō)是局部變量服鹅,除非在傳遞時(shí)帶有&引用符號(hào)
靜態(tài)變量
靜態(tài)變量只存在于函數(shù)作用域內(nèi)。一般的函數(shù)內(nèi)變量在函數(shù)結(jié)束后會(huì)釋放百新,比如局部變量企软,但是靜態(tài)變量卻不會(huì)。就是說(shuō)饭望,下次再調(diào)用這個(gè)函數(shù)的時(shí)候仗哨,該變量的值會(huì)保留下來(lái)。
只要在變量前加上關(guān)鍵字static铅辞,該變量就成為靜態(tài)變量了厌漂。
<?php
function test()
{
static $nm = 1;
$nm = $nm * 2;
print $nm."<br />";
}
// 第一次執(zhí)行,$nm = 2
test();
// 第一次執(zhí)行斟珊,$nm = 4
test();
// 第一次執(zhí)行苇倡,$nm = 8
test();
?>
聲明及應(yīng)用各種形式的PHP函數(shù)
無(wú)論是使用系統(tǒng)函數(shù)還是自定義的函數(shù),我們都要可通過(guò)如下函數(shù)的三要素來(lái)了解一個(gè)函數(shù):
- 函數(shù)的功能描述
- 函數(shù)的參數(shù)
- 函數(shù)的返回值
常規(guī)參數(shù)的函數(shù)
常規(guī)參數(shù)的函數(shù)格式說(shuō)明:
string example(string name,int age,double height)
所謂的常規(guī)參數(shù)的函數(shù)囤踩,就是實(shí)參和形參應(yīng)該個(gè)數(shù)相等旨椒、類(lèi)型一致。就像C或Java等強(qiáng)類(lèi)型型語(yǔ)言堵漱。
上面函數(shù)有三個(gè)參數(shù)综慎,調(diào)用時(shí)傳遞的參數(shù)個(gè)數(shù)和順序必須一致。
string chr(int $ascii) //返回指定的字符
float ceil(float $value) //進(jìn)一法取整
array array_combine(array $keys,array $values)//合并一個(gè)數(shù)組
string implode(string $glue,array $pieces)
偽類(lèi)型參數(shù)的函數(shù)
偽類(lèi)型參數(shù)的函數(shù)格式說(shuō)明:
mixed funName(mixed $a, number $b, callback $c)
PHP是弱類(lèi)型語(yǔ)言勤庐,不僅在聲明變量時(shí)不需要指定類(lèi)型示惊,當(dāng)然在聲明函數(shù)時(shí)也不需要指定類(lèi)型,所以在PHP中函數(shù)的每個(gè)參數(shù)愉镰,都可以為其傳遞任意類(lèi)型的值米罚。
三種偽類(lèi)型: mixed
、number
和 callback
丈探。
bool empty(mixed $var) //檢查一個(gè)變量是否為空
bool usort(array &$array,callback $cmp_function)
//使用用戶(hù)自定義的比較函數(shù)對(duì)數(shù)組中的值進(jìn)行排序
number abs(mixed $number) //絕對(duì)值
引用參數(shù)的函數(shù)
引用參數(shù)的函數(shù)格式說(shuō)明:
void funName(array &args)
相對(duì)于按值傳遞模式阔拳,并不會(huì)將父程序中的指定數(shù)值或目標(biāo)變量傳遞給函數(shù),而是把該數(shù)值或變量的內(nèi)存儲(chǔ)存區(qū)塊相對(duì)地址導(dǎo)入函數(shù)之中类嗤。因此當(dāng)該數(shù)值在函數(shù)中有任何變動(dòng)時(shí)糊肠,會(huì)連帶對(duì)父程序造成影響。
注意:如果在函數(shù)的形參中使用“&“修飾的參數(shù)遗锣,在調(diào)用該函數(shù)時(shí)必須傳入一個(gè)變量給這個(gè)參數(shù)货裹,而是不能傳遞一個(gè)值。
<?php
//使用常規(guī)參數(shù)傳值
function test($arg) {
$arg = 200; //在函數(shù)中改變參數(shù)$a的值為200
}
$var = 100; //在父程序中聲明一個(gè)全局變量$var精偿,初值為100
test($var); //調(diào)用test函數(shù)弧圆,并將變量$var的值100傳給函數(shù)的參數(shù)$arg
echo $var; //輸出100赋兵。$var的值沒(méi)有變化
//使用“&”引用參數(shù)傳值
function test( &$arg ) {
$arg = 200; //改變參數(shù)$a的值為200,$arg是引用參數(shù),外部變量$var也被修改
}
$var = 100; //在父程序中聲明一個(gè)全局變量$var搔预,初值為100
test($var); //調(diào)用test函數(shù)霹期,并將變量$var的引用傳給函數(shù)的參數(shù)$arg
echo $var; //輸出200。$var的值在函數(shù)中修改變量$arg時(shí)被修改
?>
默認(rèn)參數(shù)的函數(shù)
默認(rèn)參數(shù)(“[ ]”中的)的函數(shù)格式說(shuō)明:
mixed funName(string name [,string value [,int num]])
在php中拯田,支持函數(shù)的默認(rèn)方式調(diào)用历造。如果在調(diào)用函數(shù)時(shí)沒(méi)有指定參數(shù)的值,在函數(shù)中會(huì)使用參數(shù)的默認(rèn)值船庇。
注意:默認(rèn)參數(shù)必須列在所有沒(méi)有默認(rèn)值參數(shù)的后面吭产。
<?php
/**
自定義一個(gè)函數(shù)名稱(chēng)為person,用于打印一個(gè)人的屬性
@param string $name 人的名子屬性字符串鸭轮,默認(rèn)值為"張三"
@param int $age 人的年齡屬性臣淤,默認(rèn)值為20
@param string $sex 人的性別屬性,默認(rèn)值為"男"
*/
function person( $name="張三", $age=20, $sex="男" ){
echo "我的名字是:{$name}, 我的年齡為:{$age}, 性別: {$sex} <br>";
}
person(); //在調(diào)用函數(shù)時(shí)三個(gè)參數(shù)都沒(méi)有傳值窃爷,全部使用默認(rèn)參數(shù)
person("李四"); //第一個(gè)默認(rèn)參數(shù)被傳入的值覆蓋邑蒋,后兩個(gè)參數(shù)使用默認(rèn)參數(shù)
person(“王五”, 22); //前兩個(gè)默認(rèn)參數(shù)被傳入的值覆蓋,最后一個(gè)使用默認(rèn)參數(shù)
person("賈六", 18, "女"); //在調(diào)用函數(shù)時(shí)按厘,三個(gè)默認(rèn)參數(shù)都被傳入的值覆蓋
?>
可變個(gè)數(shù)參數(shù)的函數(shù)
可變個(gè)數(shù)參數(shù)的函數(shù)格式說(shuō)明:
mixed funName(string arg1 [,string ...] )
通常用戶(hù)定義函數(shù)時(shí)寺董,設(shè)置的參數(shù)數(shù)量是有限的。如果希望函數(shù)可以接受任意數(shù)量的參數(shù)刻剥,需使用以下函數(shù):
func_get_args() //返回一個(gè)數(shù)組遮咖,包含所有參數(shù)
func_num_args() //返回參數(shù)總數(shù)
func_get_arg() //接收一個(gè)數(shù)字參數(shù),返回指定參數(shù)
<?php
/**
聲明一個(gè)函數(shù)more_args()造虏,用于打印參數(shù)列表的值
雖然沒(méi)有聲明參數(shù)列表御吞,但可以傳入任意個(gè)數(shù),任意類(lèi)型的參數(shù)值
*/
function more_args() {
$args = func_get_args(); //將所有傳遞給腳本函數(shù)的參數(shù)當(dāng)做一個(gè)數(shù)組返回
for($i=0; $i<count($args); $i++) { //使用for循環(huán)遍歷數(shù)組$args
echo "第".$i."個(gè)參數(shù)是".$args[$i]."<br>"; //分別輸出傳入函數(shù)的每個(gè)參數(shù)
}
}
more_args("one", "two", "three", 1, 2, 3); //調(diào)用函數(shù)并輸入多個(gè)參數(shù)
function more_args() {
for($i=0; $i<func_num_args(); $i++) { //使用for循環(huán)遍歷數(shù)組$args
echo "第".$i."個(gè)參數(shù)是".func_get_arg($i)."<br>";//分別輸出傳入函數(shù)的每個(gè)參數(shù)
}
}
more_args("one", "two", "three", 1, 2, 3); //調(diào)用函數(shù)并輸入多個(gè)參數(shù)
?>
回調(diào)函數(shù)
回調(diào)函數(shù)格式說(shuō)明:
mixed funName(callback arg)
所謂回調(diào)函數(shù)漓藕,就是指調(diào)用函數(shù)時(shí)并不是傳遞一個(gè)標(biāo)準(zhǔn)的變量作為參數(shù)陶珠,而是將另一函數(shù)作為參數(shù)傳遞到調(diào)用的函數(shù)中。
- 變量函數(shù)
- 使用變量函數(shù)聲明和應(yīng)用的回調(diào)函數(shù)
- 借助call_user_func_array()函數(shù)自定義回調(diào)函數(shù)
- 類(lèi)靜態(tài)函數(shù)和對(duì)象的方法回調(diào)
變量函數(shù)
<?php
/** 聲明第一個(gè)函數(shù)one, 計(jì)算兩個(gè)數(shù)的和
@param int $a 計(jì)算和的第一個(gè)運(yùn)算元
@param int $b 計(jì)算和的第二個(gè)運(yùn)算元
@return int 返回計(jì)算后的結(jié)果
*/
function one( $a, $b ) {
return $a + $b;
}
/** 聲明第二個(gè)函數(shù)two, 計(jì)算兩個(gè)數(shù)的平方和
*/
function two($a, $b) {
return $a*$a + $b*$b;
}
$result = "one"; //將函數(shù)名"one"賦給變量$result, 執(zhí)行$result()時(shí)則調(diào)用函數(shù)one()
//$result = "two"; //將函數(shù)名"two"賦給變量$result, 執(zhí)行$result()時(shí)則調(diào)用函數(shù)two()
echo “運(yùn)算結(jié)果是:”.$result(2, 3); //變量$result的函數(shù)名值享钞,就調(diào)用哪個(gè)函數(shù)
?>
回調(diào)函數(shù)
<?php
// 聲明回調(diào)函數(shù)filter, 在0-100的整數(shù)中通過(guò)自定義條件過(guò)濾不要的數(shù)字
function filter( $fun ) {
for($i=0; $i <= 100; $i++) {
//將參數(shù)變量$fun加上一個(gè)圓插號(hào)$fun(), 則為調(diào)用和變量$fun值同名的函數(shù)
if( $fun($i) )
continue;
echo $i.'<br>';
}
}
//聲明一個(gè)函數(shù)one, 如果參數(shù)是3的倍數(shù)就返回true, 否則返回false
function one($num) {
return $num%3 == 0;
}
// 聲明一個(gè)函數(shù)two, 如果參數(shù)是一個(gè)回文數(shù)(翻轉(zhuǎn)后還等于自己的數(shù))返回true, 否則返回false
function two($num) {
return $num == strrev($num);
}
filter("one"); //打印出100以?xún)?nèi)非3的倍數(shù)揍诽,參數(shù)"one"是函數(shù)one()的名稱(chēng)字符串,是一個(gè)回調(diào)
echo '--------------------<br>';
filter('two'); //打印出100以?xún)?nèi)非回文數(shù)栗竖,參數(shù)"two"是函數(shù)two()的名稱(chēng)字符串暑脆,是一個(gè)回調(diào)
?>
借助call_user_func_array()函數(shù)自定義回調(diào)函數(shù)
<?php
/** 聲明一個(gè)函數(shù)fun(), 功能只輸出兩個(gè)字符串,目的是作為call_user_func_array()回調(diào)參數(shù)
@param string $msg1 需要傳遞一個(gè)字符串作為參數(shù)
@param string $msg2 需要傳遞另一個(gè)字符串作為參數(shù)
*/
function fun($msg1, $msg2) {
echo '$msg1 = '.$msg1;
echo '<br>';
echo '$msg2 = '.$msg2;
}
/** 通過(guò)系統(tǒng)函數(shù)call_user_func_array() 調(diào)用函數(shù)fun()
第一個(gè)參數(shù)為函數(shù)fun()的名稱(chēng)字符串
第二個(gè)參數(shù)則是一個(gè)數(shù)組狐肢,每個(gè)元素值會(huì)按順序傳遞給調(diào)用的fun()函數(shù)參數(shù)列表中
*/
call_user_func_array('fun', array('canshu1', 'canshu2'));
?>
匿名函數(shù)
匿名函數(shù)(Anonymous functions)添吗,也叫閉包函數(shù)(closures),允許 臨時(shí)創(chuàng)建一個(gè)沒(méi)有指定名稱(chēng)的函數(shù)份名。最經(jīng)常用作回調(diào)函數(shù)(callback)參數(shù)的值碟联。當(dāng)然妓美,也有其它應(yīng)用的情況。
<?php
$greet = function($name){
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
遞歸函數(shù)
- 所謂的函數(shù)遞歸調(diào)用鲤孵,就是函數(shù)可以在其聲明的執(zhí)行敘述之中調(diào)用執(zhí)行自己壶栋。
- 通常在此類(lèi)型的函數(shù)之中會(huì)附加一個(gè)條件判斷敘述,以判斷是否需要執(zhí)行遞歸調(diào)用普监,并且在特定條件下終止函數(shù)的遞歸調(diào)用動(dòng)作贵试,把目前流程的主控權(quán)交回上一層函數(shù)執(zhí)行。因此當(dāng)某個(gè)執(zhí)行遞歸調(diào)用的函數(shù)鹰椒,沒(méi)有附加條件判斷敘述時(shí)可能會(huì)造成無(wú)限循環(huán)的錯(cuò)誤情形.
- 函數(shù)遞歸調(diào)用最大的好處在于可以精簡(jiǎn)程序中繁雜重復(fù)調(diào)用程序锡移,并且能以這種特性來(lái)執(zhí)行一些較為復(fù)雜的運(yùn)算動(dòng)作呕童。
<?php
/**
聲明一個(gè)名稱(chēng)為test的函數(shù)漆际,用于測(cè)試遞歸
$param int $n 需要一個(gè)整數(shù)作為參數(shù)
*/
function test( $n ) { //聲明一個(gè)名為test的函數(shù),有一個(gè)參數(shù)
echo $n." "; //在函數(shù)開(kāi)始處輸出參數(shù)的值和兩個(gè)空格
if($n>0){ //判斷參數(shù)是否大于0
test($n-1); //如果參數(shù)大于0則調(diào)用自己夺饲,并將參數(shù)減1后再傳入
}else{ //判斷參數(shù)不大于0
echo " <--> "; //輸出分界字符串
}
echo $n." "; //在函數(shù)結(jié)束處輸出參數(shù)的值和兩個(gè)空格
}
test(10); //調(diào)用test()函數(shù)將整數(shù)10傳給參數(shù)
?>
使用自定義函數(shù)庫(kù)
代碼重用:
- 通過(guò)重復(fù)使用已有的代碼奸汇,提高開(kāi)發(fā)效率,降低成本
include( )
和require( )
函數(shù)往声。 - require( )將一個(gè)文件在預(yù)處理期間被導(dǎo)入擂找,像把該文件粘貼到使用函數(shù)的地方。
- include( )與require ( )幾乎等價(jià)浩销,區(qū)別在于在腳本執(zhí)行時(shí)包含贯涎,當(dāng)處理失敗時(shí),include( )產(chǎn)生一個(gè)警告而require( )則導(dǎo)致一個(gè)致命錯(cuò)誤慢洋。
include_once( )和require_once( )函數(shù)##
兩個(gè)函數(shù)在腳本執(zhí)行期間包括并運(yùn)行指定文件塘雳。與include( )語(yǔ)句及require( )類(lèi)似,唯一區(qū)別是如果該文件中的代碼已經(jīng)被包括了普筹,則不會(huì)再次包括败明,只會(huì)包括一次。這兩個(gè)函數(shù)應(yīng)該用于在腳本執(zhí)行期間同一個(gè)文件有可能被包括超過(guò)一次的情況下太防,你想確保它只被包括一次以避免函數(shù)重定義妻顶,變量重新賦值等問(wèn)題。
Have a try
使用循環(huán)語(yǔ)句實(shí)現(xiàn)下列代碼:要求時(shí)間的每個(gè)圖像(要求圖像的都使用函數(shù)定義)