PHP 函數(shù)

碎碎念

初學PHP發(fā)現(xiàn)其作用域的概念與Javascript有很大不同,所以記下這些,以免后面搞混了。

變量類別

PHP的變量分為全局變量與局部變量:

局部變量

  1. 函數(shù)體內(nèi)部聲明的變量
  2. 局部變量還分為動態(tài)變量靜態(tài)變量
  3. 局部變量的作用域僅限于函數(shù)體內(nèi)部,外部是訪問不到的

動態(tài)變量

函數(shù)執(zhí)行完畢后會立即釋放。

靜態(tài)變量

  1. 可以通過static關(guān)鍵字聲明
  2. 其在第一次調(diào)用函數(shù)時相當于初始化靜態(tài)變量,但函數(shù)執(zhí)行完畢后靜態(tài)變量并沒有被釋放,而是被保存在靜態(tài)內(nèi)存中,當再次調(diào)用這個函數(shù)時,首先從靜態(tài)內(nèi)存中取出變量的值繼續(xù)執(zhí)行。
function test() {
  static $j = 1;
  echo $j."<br>";
  ++$j;
}
test(); // 初次調(diào)用 1
test(); // 2
test(); // 3
test(); // 4

// 如果$j不是static聲明,則每次調(diào)用后$j變量都會被釋放,會得到4個1 => 局部變量中的動態(tài)變量
// 加上了static后,每次調(diào)用后變量并未釋放,而是存進了靜態(tài)變量 => 局部變量中的靜態(tài)變量

全局變量

  1. 函數(shù)體外部聲明的變量
  2. 函數(shù)體內(nèi)部通過global關(guān)鍵字聲明的變量
$m = 3;
$n = 4;
function test() {
  var_dump($m, $n); // 此時無法獲取$m,$n
}

// 直接在函數(shù)內(nèi)部訪問全局變量是無法得到的
// 方法1 global關(guān)鍵字
function test1() {
  global $m; // 使用全局的變量
  global $n;
  // global $m, $n; 
  var_dump($m, $n);
  $m = 7; // 此時修改的是全局變量了
  $n = 8;
}
test(); // 3 4
var_dump($m, $n); // int 7, int 8

function test1() {
  global $i, $j; // 創(chuàng)建全局變量,在全局訪問
  $i = 9;
  $j = 10;
}
test1();
var_dump($m, $n);

// 方法2 $GLOBALS超全局變量
$username="gaohang";
$age=12;
$mail="isaackao@foxmail.com";
print_r($GLOBALS);
function test2() {
  echo "用戶名是".$GLOBALS['username']."<br>";
  echo "年齡是".$GLOBALS['age']."<br>";
  echo "郵箱是".$GLOBALS['mail']."<br>";
}
test2();
// 用戶名是gaohang 年齡是12 郵箱是isaackao@foxmail.com

只能通過兩種方式,在函數(shù)體內(nèi)部訪問全局變量。

  1. 通過global關(guān)鍵字
  2. 通過$GLOBALS超全局變量

傳值與傳引用

PHP與Javascript類似,也有值傳遞和引用傳遞的概念,類似js傳入簡單類型的值,不會改變函數(shù)外的值,傳入復雜類型則會改變其自身

默認情況下,函數(shù)參數(shù)都是傳值的。所以在函數(shù)體內(nèi)改變參數(shù)的值也不會影響到函數(shù)外部的值。此外,可以通過再參數(shù)前面加上&符號,代表通過引用內(nèi)存地址傳遞參數(shù),在函數(shù)內(nèi)部對其所作的操作影響。

function test3(&$j) { // 注意&符號
  $j+=20;
  var_dump($j);
}
$k = 5;
test3($k);
var_dump($k); 
// int(25) int(25)

注意這里只有變量才能被當作引用被傳遞,如果按照test3(5)調(diào)用則無效!

可變函數(shù)

// 可變函數(shù) 把函數(shù)名賦給一個變量 變量調(diào)用時會被當作函數(shù)解析
$funcName = 'md5';
echo $funcName("gaohang");
echo "<br>";
echo md5("gaohang");
// 074f69168405a5e892f1d02f12896f3f
// 074f69168405a5e892f1d02f12896f3f

可變函數(shù)不能用于像echo、print、unset()、isset()、empty()、include、require以及類似的結(jié)構(gòu),需要封裝實現(xiàn)。

自定義函數(shù)

function custom() {
    echo "this is a test function!";
}
$customFunc = 'custom';
var_dump($customFunc); // string(6) "custom"
$customFunc(); // this is a test function!
$customFunc = 'hahahah';
var_dump($customFunc); // "hahahah"
$customFunc(); // Fatal error: Uncaught Error: Call to undefined function hahahah() in xxxx

所以我們可以定義一個函數(shù),然后將函數(shù)名賦值給變量,用變量來調(diào)用函數(shù)??梢酝ㄟ^get_defined_function()來獲取所有系統(tǒng)變量(internal)和用戶自定義變量(user),一個關(guān)聯(lián)數(shù)組。

回調(diào)函數(shù)

回調(diào)函數(shù)說白了就是把一個函數(shù)當作參數(shù)傳遞進另一個函數(shù),并在函數(shù)內(nèi)調(diào)用!我們可以通過可變函數(shù)的形式進行調(diào)用,或者是call_user_func()call_user_func_array()進行調(diào)用;

  • call_user_func():Calls the callback given by the first parameter and passes the remaining parameters as arguments.
<php?
function increment(&$var)
{
    $var++;
}

$a = 0;
call_user_func('increment', $a);
echo $a."\n";

// You can use this instead
call_user_func_array('increment', array(&$a)); // 注意這里參數(shù)是使用數(shù)組進行傳遞的
echo $a."\n";
?>

匿名函數(shù)

也就是閉包,臨時創(chuàng)建一個沒有指定名稱的函數(shù),最經(jīng)常用作回調(diào)函數(shù)參數(shù)的值。此外,匿名函數(shù)也可以作為變量的值來使用。

// 匿名函數(shù) 注意要加分號
$func = function() {
  return "this is a function";
};
// 通過可變函數(shù)的形式進行調(diào)用
echo $func();

// 通過create_function創(chuàng)建匿名函數(shù)
create_function(參數(shù)列表,函數(shù)體)
$func = create_function('','"this is a function";');
$func();

// 匿名函數(shù)作為參數(shù)傳入
$array=array(1,2,3,4,5);
$res=array_map(function($var) {return $var*2;}, $array);
call_user_func(function($var) {echo "Hello {$var}";}, 'gaohang');

遞歸函數(shù)

如果函數(shù)A需要調(diào)用函數(shù)B,而發(fā)現(xiàn)函數(shù)B的代碼實現(xiàn)與函數(shù)A完全相同,以此類推,此時就需要封裝成遞歸函數(shù)。
直白的說,就是函數(shù)自己調(diào)用自己,以特殊條件結(jié)束執(zhí)行。
比如PHP實現(xiàn)遍歷目錄,目錄的復制,刪除非空目錄等等操作必須通過遞歸函數(shù)實現(xiàn)。無限極分類(電商網(wǎng)站的分類項目)也必須通過遞歸實現(xiàn)。

// 簡單的遞歸
function test($i) {
  echo $i."<br>";
  --$i;
  if ($i>=0) {
    test($i);
  }
}
test(5);
5
4
3
2
1
0
image.png

使用遞歸時要注意兩個原則:

  1. 能不用遞歸就不要使用
  2. 注意遞歸的結(jié)束條件,防止無限遞歸

使用自定義函數(shù)

對于多次使用的自定義函數(shù),我們可以使用require/require_once/inculde/include_once來引用自定義函數(shù),避免多處書寫重復的函數(shù)被。

通過require/require_once包含文件不存在會產(chǎn)生一個致命錯誤和警告,且程序會終止運行。用include則會產(chǎn)生兩個警告,不會終止程序運行。

require與require_once的區(qū)別在于后者只會出現(xiàn)1次包含。

此外,要注意代碼順序,require和include必須出現(xiàn)在調(diào)用之前,注意代碼順序。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容