PHP一種友善的函數傳參模式設計,有需要的朋友可以參考下。
當一個類別的建構函式函數中,需要傳入的參數較多時,程式設計師在編碼時由於傳入的順序和寫法難記憶,容易出現編譯錯誤,或是出現值傳給錯誤參數(弱型別語言)的情況.
友善的功能設計
程式設計師在實例化一個class時,傳入的參數應該滿足以下 友善目標:
1. 能夠只傳入部分參數
2. 能夠不依序傳入參數
3. 能夠不區分參數的大小寫
4. 能夠及時準確的提示傳參時產生的錯誤
改進流程
例1-在成員變數中賦預設值
請看以下程式碼,函數的預設值在成員變數中賦予,這樣在只傳入部分參數時,系統會產生notice,即不滿足"友善目標"中的第一條.
- class FileUpload
- {
-
- private $filepath; //指定檔案儲存的路徑
- private $allowtype = array("gif", "jpg" ", "jpeg", "png"); //允許的類型
- private $maxsize = 1000000; //允許上傳的檔案大小1M
- private $israndname = true; //是否重新命名檔案
-
- function __construct($filepath, $allowtype, $maxsize, $israndname)
- {
- $this->filepath = $filepath;
- $this->allowtype = $allowtype;
- $this->maxsize = $maxsize;
- $this->israndname = $israndname;
-
- var_dump($this);
- }
- }
}n複製程式碼
例2-在建構函式中賦預設值
這次,為了消除上例的notice,實作可以傳入任意數量的參數,沒有傳入的參數使用預設值,將程式改為:在建構函式中設定預設值.
又一個問題出現:當程式設計師傳入參數為(“/upload”,array(“jpg”,”gif”),false)時,即程式設計師忘記傳入了maxsize參數,這時系統會錯誤的將false賦值給maxsize而不是israndname,系統沒有任何錯誤輸出,為後續工作留下隱患!
-
- class FileUpload
- {
-
- private $filepath;
- private $allowtype;
- private $maxsize; 🎜>
- function __construct(
- $filepath = "/upload",
- $allowtype = array("gif", "jpg", "jpeg", "png"),
- $maxsize = 1000000,
- $israndname = true)
-
- {
- $this->filepath = $filepath;
- $this->allowtype = $allowtype;
- $this->maxsize = $maxsize;
- $this->israndname = $israndname;
-
- var_dump($this);
- }
-
複製代碼
例3-使用陣列封裝參數
為解決例2的問題,我們可以對傳入的值進行檢查來防止賦值錯位的情況發生(反正一般情況下我們都會對傳入的值進行檢查).然而這並不是解決問題的方法,因為我們要實現的功能還有使程式設計師可以不按順序傳值.
在弱型別語言中,解決這個問題可以使用 數組 的特殊性,將所有傳遞的參數封裝到數組中,以key=>value鍵值對的形式保存.請看如下碼:
class FileUpload- {
-
- private $filepath;
- private $allowtype;
- private $maxsize; 🎜>
- function __construct($options=array([預設值]))
- {
- //解析傳入的陣列
- foreach($options as $key=>$value){
- $this->$key = $value;
- }
- }
-
-
- 複製程式碼
這樣就解決了傳入參數的順序問題,同時也解決了只傳部分參數的問題.
然而新的問題出現了,這時程式設計師需要輸入一個陣列作為參數,如下:
$up = new $FileUpload(array( "filepath" => "/upload", "israndname" => false,- "maxsize" => 2000000
- ));
-
-
- 複製程式碼
例4-解決參數的大小寫
在使用陣列封裝參數之後,這時需要程式設計師手動輸入變數的名字,這就會因為風格不同導致MaxSize, maxSize, maxsize 這樣的寫法問題,解決這個問題只需要在宣告成員變數時都統一用小寫,然後在建構子裡加一行:
foreach($options as $key=>$value){ $key = strtolower($key);
- ...
- }
-
- 複製程式碼
到這裡,我們的設計已經滿足了 友善目標 中的前三點,整體程式碼如下:
- class FileUpload {
-
- private $filepath;
- private $allowtype;
- private $maxsize
- privateis; 🎜> "$filepath" => "./",
- "$allowtype" => array("txt","jpg"),
- "$maxsize " => 1000000,
- "$israndname" => true
- )){
- //解析傳入的陣列
- foreach($options as $key=>$value){
- $key = strtolower($key);
- $this->$key = $value;
- }
- }
- }
-
-
- 複製代碼
例5-處理傳入key的錯誤
在上例中,如果程式設計師傳入了一個類別中根本沒有的參數,系統會報錯,這裡我們有兩種處理方案:
1. 忽略無效參數,僅執行有效參數
2. 友善的提示出你傳入的某個參數無效
個人認為為了程式的健全性,不能輕易容許錯誤的程式碼存在,故選擇第二者,我們將這個錯誤友善的提示給呼叫者.
foreach($options as $key=>$value){ $key = strtolower($key); //判斷類別中是否有這個變數- if(in_array($key, get_class_vars(get_class($this)))) {
- $this->$key = $value;
- }else{ //提示錯誤位置與參數
- echo "Error when init class ".get_class($this)." with key: ".$key." in array !";
- exit;
- }
- }
-
-
- 複製程式碼
例6-檢查傳入value是否合法
至此,預期的4個目標均已實現,且為了使__construct()函數具有復用性,使用時可以直接paste,我們將對value的檢查抽象化成一個函數,請看修改後的程式碼:
class FileUpload { //變數名稱皆使用小寫- private $filepath;
- private $allowtype; private $size; 🎜> private $israndname;
-
- //在建構子中賦予預設值
- function __construct($options=array(
- "$filepath" => "./",
- " $allowtype" => array("txt","jpg"),
- "$maxsize" => 1000000,
- "$israndname" => true
- )){
- //解析傳入的陣列
- foreach($options as $key=>$value){
- $key = strtolower($key);
- //判斷key是否在類別中宣告
- if(in_array( $key, get_class_vars(get_class($this)))) {
- //檢查value是否符合要求
- if(checkValue($key,$value)) {
- $this->$key = $ value;
- } else {
- //提示錯誤位置與參數
- echo "Invalid value".$value."found when init class ".get_class($this)." with key: ".$ key." in array !";
- exit;
- }
- }else{
- //提示錯誤位置與參數
- echo "Error when init class ".get_class($this). " with key: ".$key." in array !";
- exit;
- }
- }
- }
-
- function checkValue{
- if(){
- ...
- return true;
- }
- return false;
- }
- }
-
-
-
- 複製代碼
-
PHP
|