2017年12月5日 星期二

PHP 學習筆記 : 自訂函數

最近在改寫 PHP 專案時遇到需要寫一個自訂函數來簡化爬蟲程式的結構, 這才發現已經快把 PHP 忘光了, 所以又重新複習一遍自訂函數寫法, 順便整理筆記如下 :

一. PHP 自訂函數語法格式 :

function 函數名稱([參數1, 參數 2, .... 參數 n]) {
  函數內容;
  [return 傳回值];
  }

自訂函數用法摘要 :
  1. 函數名稱只能由英數字元或底線組成, 但第一個字元不可以是數字. 參數名稱命名方式與變數相同, 即必須以 $ 開頭, 然後與函數名稱一樣是英文字母或底線帶領的任意長度英數字或底線字元.
  2.  函數名稱與參數名稱都分大小寫, Func() 與 func() 是不同函數, $var 與 $Var 是不同參數. 參數名稱不可使用保留字. 
  3. 傳入參數不是必要, 多個參數用逗號隔開. 參數可以設定預設值, 呼叫時若未傳入該參數即以該預設值代替, 例如 :
    function f($var1=1, $var2="ok") {...}
    沒有預設值的參數一定要相當型別的傳入值, 否則會出現執行錯誤. 
  4. 參數為函數內之區域變數, 與函數外的全域變數即使同名也不相干, 因此在函數內部存取到的是區域變數, 而不是同名的函數外全域變數. 在函數內若要存取外部全域變數須在變數前面加 global 或使用全域陣列 $GLOBALS[] :
    $var=1;   //全域變數
    func() {
      global $var=2;  //或者 $GLOBALS['var']=2;
      echo $var;    //輸出2
      }
    echo $var;    //輸出2 (被函數改了)
  5. 函數內之一般變數均為區域變數, 函數結束時即被釋放, 若欲在函數執行完畢後保留函數內之變數, 可用 static 宣告其為靜態變數 :
    function f() {
      static $var=0;
      echo ++$var;
      }
    f();  //輸出 1 ($var 被保留下來)
    f();  //輸出 2
  6. 預設的呼叫方式為傳值呼叫, 若要用傳址呼叫須在全域變數前面加 "&", 傳入參數之值可能會被函數修改 :
    $var=1;
    $val1=func($var);  //傳值呼叫 ($var 不會被修改)
    $val2=func(&$var);  //傳址呼叫 ($var 可能會被修改)
  7. 傳回值不是必要, 傳回值可以是任何型別之資料. 
  8. 在 PHP4 之後的版本, 函數可以放在程式的任何地方, 不一定要放在呼叫之前. 


二. 變動長度的參數列 : 

PHP 的函數可以在定義函數時不指定參數個數, 而在呼叫函數時透過下列三個內建函數來處理傳入之參數 :

 函數名稱 說明
 func_num_args() 傳回傳入函數之參數個數
 func_get_arg(n) 傳回傳入函數的第 n+1 個參數內容
 func_get_args() 傳回傳入函數之所有參數組成之陣列

注意, 此三內建函數只能在自訂函數內呼叫, 否則會出現錯誤.


三. 可變動函數 : 

在 PHP 我們可以設定一個字串變數的值為函數名稱, 利用此變數名稱當函數名稱, 就可以動態地呼叫不同的函數, 例如 :

$f1() {echo "這是 f1()";}
$f2() {echo "這是 f2()";}
$f3() {echo "這是 f3()";}
$fname="f1";
$fname();   //呼叫 f1() 輸出 "這是 f1()"
$fname="f2";
$fname();   //呼叫 f2() 輸出 "這是 f2()"
$fname="f3";
$fname();   //呼叫 f3() 輸出 "這是 f3()"

這樣就可以用單一介面呼叫不同函數了.

但是若字串變數值弄錯的話就可能會因為呼叫一個不存在的變數而發生錯誤, 這時可先呼叫內建函數 function_exists() 來檢查, 傳入參數為代表函數名稱的字串變數, 例如 :

if (function_exists($fname)) {$fname();}


四. 遞迴函數 :

PHP 的函數也可以呼叫本身形成遞迴, 典型的範例為階乘函數, 例如 :

function factorial($n) {
  if ($n >= 0) {
    if ($n == 0) {return 1;}
    else {
      $ret=1;
      for ($i = $n; $n > 0; $n--) {$ret *= $n;}
      return $ret;
      }
    }
  }

echo "5 階乘=".factorial(5);  //輸出 120

沒有留言 :