Проблемы с повторным выделением классов при использовании PHP class_alias в функциональном тесте - PullRequest
3 голосов
/ 03 августа 2010

Я использую class_alias в PHP 5.3 для помощи в обработке форм Symfony 1.4 (Doctrine). Я использую одно действие для обработки нескольких страниц формы, но использую инструкцию switch для выбора класса формы для использования.

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 ответ на второй запрос со следующей ошибкой:

последний запрос вызвал необработанное исключение RuntimeException: PHP отправил предупреждение об ошибке в /.../apps/frontend/modules/.../actions/actions.class.php строке 225 (невозможно переопределить класс FormAlias)

Это очень затрудняет тестирование представлений форм (которые обычно отправляются обратно самим себе).

Предположительно, это потому, что тестер Symfony не очищал пропускную способность таким же образом. Есть ли способ «unalias» или иным образом разрешить такого рода переопределение?

Ответы [ 3 ]

2 голосов
/ 03 августа 2010

В качестве альтернативного решения вы можете назначить имя класса для создания экземпляра переменной и добавить новое:

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

Это не использует class_alias, но сохраняет создание экземпляра в одном месте.

1 голос
/ 03 августа 2010

Я точно не знаю, возможно ли это, но, судя по Руководству, я бы сказал, нет. Как только у класса есть псевдоним, нет способа сбросить его или повторно объявить его с другим именем. Но опять же, зачем вообще использовать псевдоним?

Из вашего кода я предполагаю, что вы делаете псевдонимы в каждом дополнительном блоке case. Но если это так, вы можете просто создать экземпляр формы в этих блоках, например,

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

Вы все равно жестко кодируете имена классов в блоке switch / case при использовании 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);
}

Если вы используете DI-контейнер Symfony Components , вы также можете избавиться от жестко закодированной заводской зависимости и просто использовать служебный контейнер для получения формы. Это был бы самый чистый подход ИМО. По сути, использование class_alias кажется мне здесь неуместным.

0 голосов
/ 03 августа 2010
function class_alias_once($class, $alias) {
    if (!class_exists($alias)) {
        class_alias($class, $alias);
    }
}

Это не решает саму проблему, но с помощью этой функции гарантируется, что вы не получите ошибку. Может быть, этого будет достаточно для вашей цели.

...