2010-08-03 47 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