2012-04-06 27 views
2

在一個類中,我有一個處理方法,它根據什麼post/get變量可用來執行操作。下面是一個簡單的例子:

public function handleAll(array $vars) { 
    if (isset($vars['var1'])) { 
     $this->doThisAction($vars['var1']); 
    } else if (isset($vars['var2'])) { 
     $this->doAnotherAction($vars['var2']); 
    } 
} 

所以在運行時的方法可以這樣調用$handler->handleAll($_POST)。 問題是存儲在$ vars數組中的變量必須命名爲「var1」&「var2」等。這意味着處理代碼與html表單元素的名稱相結合或者在url中獲取變量(或者實際上鍵任何數組傳入)。

允許注入任何變量的數組使得該方法具有靈活性,這是必要的,因爲它也是多態的。類繼承此方法並用它來調用它自己的操作。這樣做的結果是,外部處理方法所需的功能並不明顯。這意味着必須檢查實現,找出它的功能(除非我將代碼複製到phpdoc中,這很愚蠢)。

我不知道如何解決這個問題。索引頁面(來自多個這樣的類)暴露出巨大的if/case語句會導致非常混亂的代碼,因此最好將所有這些封裝在方法中。此外,將它作爲負責調用操縱它自己狀態的行爲的類的一種方法是有意義的(責任驅動設計)。我想過把每個變量作爲方法的一個參數,但是對於某些類來說,參數列表會非常大。同樣,這意味着不同類的handleAll()方法不能自動調用,因爲每次調用都需要顯式注入所有參數,從而消除多態性方面。

總結我需要保持多態的方法,但我需要某種方式從HTML表單或網址的用戶輸入解耦處理代碼。這樣做也許有一種將接口與實現分開的方法。我很驚訝,我無法找到任何解決方案,這似乎是一個普遍的問題。

+0

而不是'handleAll'處理所有事情,爲什麼你沒有單獨的方法處理他們期望的特定後期數據變量? – 2012-04-06 19:53:38

+0

如果我要爲每個方法提供post變量,那麼我會在任何地方都獲得大量的if/else代碼。此外,多態性將被刪除,這意味着每個類都需要顯式調用每個類,這意味着許多對handleAll()的調用無法在循環中進行。如果我想使每種方法都能與特定的後置變量一起工作,所以不能注入依賴關係,那麼耦合問題依然存在。 – Jonathan 2012-04-06 20:08:08

+0

你不能使用很多MVC框架之一嗎?他們默認提供你想要的。基本上你需要在應用程序中「分割」控制器,每個控制器都有自己的責任。國際海事組織目前的方法是多形態的。它更像是一個前端控制器。 – MikeSW 2012-04-06 20:55:14

回答

1

我不確定您所描述的內容是否可以避免。

如果您的代碼需要特定的參數(無論是包含某些值還是其他任何值的數組),該函數將始終取決於正確填充的參數。

如果我有function foo($a, $b, $c),我將始終填寫參數。如果他們來自POST,那麼我需要從POST中取出它們。即使該功能採用array('a' => ..., 'b' => ..., 'c' => ...)代替,也是如此。然而,如果你想從表單中解耦你的表單,你可以使用一個簡單的函數將POST數組轉換成你的處理函數所期望的格式。儘管如此,我並沒有看到任何理由,因爲如果您不需要,爲什麼會增加額外的複雜性?

如果您希望更好地定義您的處理程序需要什麼類型的數組,您可以考慮讓它需要一個對象。這種方法有時被稱爲parameter object

使用參數對象的好處在於,您可以在構造函數中輕鬆設置所需的參數,並使用setter作爲可選參數。任何使用你的代碼的人都可以看看你的對象的接口,看看需要什麼值。

如果您的處理程序使用的值實際上是相互關聯的,我會考慮創建一個實際的業務邏輯類型對象。使用來自POST的數據創建它,並將處理值的代碼移動到對象中的方法中。

+0

這是一個很好的答案和一個很好的解決方案。唯一的問題是你的建議基本上是目前班級的責任。它是一個控制器,它接收/獲取被驗證的信息並將其轉換爲模型的對象(例如數據庫表的CRUD)。我將驗證封裝在控制器中,以便它可以輸出關於它正在發送的信息的反饋(例如,視圖輸出特定於該問題的無效輸入消息)。如果我將所有這些驗證移至業務邏輯對象,那麼您認爲保留該功能的最佳方式是什麼? – Jonathan 2012-04-07 01:08:05

+1

是的,一個控制器將是與POST等耦合的部分,所以這是正確的。至於驗證,如果你只需要它在控制器中,你可以保留它。如果你決定把它移動到其他地方,你可以考慮製作一個驗證對象的方法,並且可能會返回一個包含錯誤(如果有的話)的數組或者沿着這些行的東西。 – 2012-04-07 01:23:29

+0

我已經有業務邏輯對象,所以我會給他們另一個構造函數(靜態方法,返回自我的一個實例),在其中注入一個數組($ _POST/$ _ GET/whatever),其他參數可以是數組鍵。例如'fromArr($ _ POST, '標題', '體')'。你可以在界面中定義一個方法,使用不同數量的參數嗎?在Java中,我通常會超載。我想我會重新定義handleAll作爲'route($ action,Item $ item)',但是繼承路由的子類不能定義'route($ action,SpecificItem $ item)'。在Java中我會使用泛型'Controller '。 – Jonathan 2012-04-07 11:45:19

0

解耦和自動化處理方法,也可能是縮小範圍的痛苦方法。但是沒有太多的選擇,除了爲事物創建處理程序之外。不過,我想添加一些東西。允許默認值和支持變體

function handlePOST() { } 
function handleGET() { } 
function handleArr() { } 

現在,這些函數可以代表它們代替函數的變體。

但是,它們並不是編寫所有處理程序的更好方法。但是開關會縮短它們,並使用單獨的功能進行處理。

switch($_POST['var1']) { 
    case "value1": callPostValue1(); break; 
    default: callPostDefaultHandler(); break; 
}