2010-08-03 21 views
3

我使用PHP 5.3的class_alias來幫助處理我的Symfony 1.4(Doctrine)表單。我使用單個動作來處理多個表單頁面,但使用switch語句來選擇要使用的表單類。在功能測試中使用PHP的class_alias時重​​新聲明類的問題

public function executeEdit(sfWebRequest $request) { 
    switch($request->getParameter('page')) { 
    case 'page-1': 
     class_alias('MyFormPage1Form', 'FormAlias'); 
    break; 
    ... 
    } 
    $this->form = new FormAlias($obj); 
} 

瀏覽網站時,該工作出色,但沒有我的功能測試,因爲當一個頁面加載不止一次,像這樣:

$browser->info('1 - Edit Form Page 1')-> 

    get('/myforms/edit')-> 
    with('response')->begin()-> 
    isStatusCode(200)-> 
    end()-> 

    get('/myforms/edit')-> 
    with('response')->begin()-> 
    isStatusCode(200)-> 
    end(); 

我得到一個500響應第二請求,出現以下錯誤:

last request threw an uncaught exception RuntimeException: PHP sent a warning error at /.../apps/frontend/modules/.../actions/actions.class.php line 225 (Cannot redeclare class FormAlias)

這使得很難測試表單提交(通常會自行發回)。

大概這是因爲Symfony的測試儀還沒有以相同的方式清除吞吐量。 有沒有辦法'unalias'或以其他方式允許這種重新聲明?

回答

2

作爲一個替代的解決方案,您可以指定名稱的類的實例化一個變量,新認爲:

public function executeEdit(sfWebRequest $request) { 
    $formType; 
    switch($request->getParameter('page')) { 
    case 'page-1': 
     $formType = 'MyFormPage1Form'; 
    break; 
    ... 
    } 
    $this->form = new $formType(); 
} 

這不使用class_alias但保持實例化一個單點。

+0

整潔。不知道這是可能的。似乎使class_alias有點多餘。我假設有一個性能差異。 – kenneth 2010-08-03 14:02:30

+0

class_alias必須保留別名類的記錄,這會引入一個局部變量。不知道哪個更具影響力。 由於某種原因,class_alias必須添加到5.3.0,但我想不出來。 – Kwebble 2010-08-03 22:21:49

0
function class_alias_once($class, $alias) { 
    if (!class_exists($alias)) { 
     class_alias($class, $alias); 
    } 
} 

這並不能解決問題本身,但通過使用此功能可以確保您不會收到錯誤。也許這會滿足你的目的。

+1

Jep,你完全正確。 parsekit和classkit都沒有這種方法。從我的答案中刪除了該部分。 – NikiC 2010-08-03 11:06:11

1

我不確定是否有可能,但從手冊判斷,我會說不。一旦該類別被別名,就無法重置它或以不同的名稱重新聲明它。但是再一次,爲什麼要使用別名呢?

從你的代碼我假設你正在做每個額外case塊別名。但如果是這樣的話,你可以簡單地在這些塊中實例化表單,例如

public function executeEdit(sfWebRequest $request) { 
    switch($request->getParameter('page')) { 
    case 'page-1': 
     $form = new MyFormPage1Form($obj); 
    break; 
    ... 
    } 
    $this->form = $form; 
} 

在使用class_alias時,您正在將類名硬編碼到開關/大小寫塊中。使用它沒有優勢。如果你想動態地實現它,你可以創建一個從'page'到'className'的數組映射,然後簡單地查找適當的類。

public function executeEdit(sfWebRequest $request) { 
    $mapping = array(
     'page-1' => 'MyFormPage1Form', 
     // more mappings 
); 
    $form = NULL; 
    $id = $request->getParameter('page'); 
    if(array_key_exists($id, $mapping)) { 
     $className = $mapping[$id]; 
     $form = new $className($obj); 
    } 
    $this->form = $form; 
} 

這樣,你也可以把整個映射放在配置文件中。或者你可以創建FormFactory。

public function executeEdit(sfWebRequest $request) { 
    $this->form = FormFactory::create($request->getParameter('page'), $obj); 
} 

如果您使用的是Symfony Components DI Container,你也可以擺脫硬編碼的工廠的依賴,只是使用服務容器來獲得的形式。這將是國際海事組織最清潔的做法。基本上,使用class_alias只是感覺不適合我。

+0

這個函數更復雜一些,我沒有在這個例子中顯示出使別名更有用的例子。 但是,當然,映射看起來是一個更好的方式來處理它。 – kenneth 2010-08-03 14:04:49