2014-02-10 32 views
0

今天,當創建一個Silex的應用程序的簡單控制,我發現了一些操作方法幾乎相同的代碼:操作方法的代碼重用

public function someAction() 
{ 
    $id = $this->request->attributes->get('id') 
    if($id) 
    { 
     $data = getMyDataFromDatabaseWithThisID($id); 

     //do something with data 

     $this->app->json($data, 200); 
    } 
    else 
    { 
     //do error stuff 
    } 
} 

public function someOtherAction() 
{ 
    $id = $this->request->attributes->get('id') 
    if($id) 
    { 
     $data = getMyDataFromDatabaseWithThisID($id); 

     //do something else with data 

     $this->app->json($data, 200); 
    } 
    else 
    { 
     //do error stuff 
    } 
} 

每種方法的骨頭幾乎是完全相同。我想如果我有三種或四種方法遵循相同的模式,我應該抽出一些代碼。

我的第一個直覺是有一個大的executeAction($ action)方法,但我不知道從Silex路由傳遞變量到被調用的控制器動作的方法。其次,我認爲用一個大規模的方法取代許多小的方法是在尋求麻煩。

我的下一個想法是創建一個executeAction(Closure $ action)方法,該方法由現有操作方法調用,並通過需要的任務傳遞閉包。

所以操作方法,如updateAction()可以通過封閉來executeAction()告訴它更新所需的資源:

public function updateAction 
{ 
    $this->executeAction(function($resource, $request) { 
     $resource->doSomethingToUpdateItFromInfoInRequest($request->get('data')); 
    }); 
} 

public function executeAction(Closure $action) 
{ 
    $id = $this->request->attributes->get('id') 
    if($id) 
    { 
     $data = getMyDataFromDatabaseWithThisID($id); 

     //execute closure action 
     $action($data, $this->request); 

     $this->app->json($data, 200); 
    } 
    else 
    { 
     //do error stuff 
    } 
} 

在表面上來看,這看起來挺乾淨的。不管是否使用執行行動,它也是靈活的,因爲它取決於每種單獨的方法。我有這個想法的問題是,我需要確保閉包中的任何事情都能夠在閉包之外正確地反映出來(即正確更新變量/對象等)。它也不覺得正確的做法。雖然這可能是由於PHP中的閉包對我來說相當新穎(在使用Silex之前,我從未在我的PHP代碼中使用它們)。

第三個選項是一些公用部分的減少自己的方法 - 比如

public function getResourceById($id) 
{ 
    //do stuff 
    return $resource; 
} 

public function errorStuff($code, $message) 
{ 
    //do stuff 
} 

//then in action method 
public function updateAction() 
{ 
    $data = $this->getResourceById($this->request->get('id'); 
    if($data) 
    { 
     //do stuff 
    } 
    else 
    { 
     $this->errorStuff(1001, 'uh oh!'); 
    } 
} 

的方法看起來較小,但存在同樣的問題 - 我有幾種方法,看起來幾乎相同如果有變化(方法名稱等),將需要更新。

因此,鑑於我正在使用Silex和Silex控制器類,哪些方法(如果有的話)是避免代碼重複的更好選擇?任何人都可以完全提出一個不同的解

回答

1

上面的代碼對我來說看起來不像一個silex代碼庫,更像symfony控制器。
所以我不會評論這個特別的。

不過,我建議您熟悉閉包,因爲您已經重新使用過,因爲它們在Silex中大量使用。

爲了您的目的,您可能需要查看Param Converters的Silex實施。
他們可以把你的的一部分getMyDataFromDatabaseWithThisID函數。此外,他們還可以處理錯誤。在你的Silex控制器

$app['findOr404'] = $app->protect(function($id, $message = null) use ($app) { 
    //get the data or abort with 404 
} 

,並用它作爲ParamConverter:

您可以在您的應用程序註冊一個findOr404方法

$app->get("/get/{id}", function (Data $data) { 
    // ... 
})->convert("id", $app['findOr404']($id); 

這個例子是由該Blog Post靈感在這裏你可以找到一些更多的技巧。

如果你在關門時迷失方向,還可以看看如何包裹你的controller in classes。這可能會更熟悉一些。

+0

我在我的Silex項目中使用控制器類。我喜歡Silex使用簡單閉包作爲動作的能力(我使用簡單的動作),但我喜歡將相關動作組合到一個控制器中。 我從來沒有想過要查看參數轉換器,所以感謝您引起他們的注意。我認爲建議'findOr404'方法是一個好主意,可以幫助我擺脫很多重複。它可以在所有操作和控制器中重用,也是一大優勢! – Etzeitet