Есть ли способ генерировать представления из Zend_Form? (Только для чтения)

Мне было интересно, если есть простой способ генерировать представления из объектов формы при работе с CRUD.

Я имею в виду, когда у нас есть эти варианты: VIEW | РЕДАКТИРОВАТЬ | УДАЛИТЬ Мне нужна моя опция VIEW, такая как опция EDIT, но без элементов формы, только значения.

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

Кто-то знает что-то подобное?

5 ответов

Решение

Гектор из Набл, покажи мне это, что кажется лучшим способом:

class Default_View_Helper_FormView extends Zend_View_Helper_Abstract
{
    public function formView(Zend_Form $form)
    {
        $html = "<dl>";
        foreach ($form->getElements as $element) {
            $html .= "<dt>{$element->getLabel()}</dt>";
            $html .= "<dd>{$element->getValue()}</dd>";
        }
        $html .= "</dl>";
        return $html;
    }
}

В моем последнем проекте у меня тоже была эта дилемма. Мое решение, возможно, не самое элегантное, но оно сделало свою работу. Имейте в виду, я использую декоратор виджета Form вместо полного сгенерированного декоратором элемента. Но вы можете настроить этот пример для использования декораторов, которые я предполагаю. То, что я показываю, является очень простым примером, чтобы дать вам общее представление. Вот что я сделал:

class Cms_Form_Page extends Zend_Form
{
  const FOR_CREATE = 'forCreate';
  const FOR_READ   = 'forRead';
  const FOR_UPDATE = 'forUpdate';
  const FOR_DELETE = 'forDelete';

  protected $_name = 'page';

  private $_for;

  private $_viewScripts = array(
    self::FOR_CREATE => 'page-manager/partials/form-page-create.phtml',
    self::FOR_READ => 'page-manager/partials/form-page-read.phtml',
    self::FOR_UPDATE => 'page-manager/partials/form-page-update.phtml',
    self::FOR_DELETE => 'page-manager/partials/form-page-delete.phtml'
  );

  public function __construct( $for = self::FOR_CREATE, $options = null )
  {
    $this->_for = $for;

    parent::__construct( $options );
  }

  public function init()
  {
    $this->setName( $this->_name )
        ->setAttribs( array( 'accept-charset' => 'utf-8' ) )
        ->setDecorators( array(
            'PrepareElements',
            array( 'ViewScript', array( 'viewScript' => $this->_viewScripts[ $this->_for ] ) ),
            'Form'
        ) );

    $elements = array();

    swith( $this->_for )
    {
      case self::FOR_CREATE:
        $title = new Zend_Form_Element_Text( 'title' );
        $elements[] = $title;
        break
      case self::FOR_READ:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        break;
      case self::FOR_UPDATE:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        $title = new Zend_Form_Element_Text( 'title' );
        $elements[] = $title;
      break;
        case self::FOR_DELETE:
        $id = new Zend_Form_Element_Hidden( 'id' );
        $elements[] = $id;
        break;
      default:
        throw new Exception( 'invalid Form type' );
    }

    $submit = new Zend_Form_Element_Button( 'submit' );
    $elements[] = $submit;

    $this->addElements( $elements );
  }
}

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

Например, для создания у вас может быть поле выбора формы выпадающего списка, где вы выбираете Locale, где для удаления это будет скрытое поле (не показано в моем примере, кстати).

Надеюсь, что это дало вам некоторые идеи.

PS:
В одном из выбранных сценариев просмотра вы можете просто показать значение элемента (вместе с рендерингом скрытого элемента тоже), например:

<?
  $form = $this->element;
?>

... some html

// let's presume id and locale are hidden form fields for current form type 
// (Cms_Form_Page::FOR_UPDATE for instance)
<?= $form->id->renderViewHelper(); ?>
<?= $form->locale->renderViewHelper(); ?>

// and here we simply output the current locale value
// of course, you should have populated the values in the form somewhere first
<dt>Current locale:</dt>
<dd><?= $form->locale->getValue(); ?></dd>

...etc

Итак, я думаю, что вам лучше всего использовать декораторы viewscript для формы, или вы можете свернуть свой собственный декоратор элементов формы, который отображает скрытое поле (если необходимо) и просто показывает его значение в некотором HTML-теге.

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

class Default_View_Helper_FormView extends Zend_View_Helper_Abstract
{
  public function formView( Zend_Form $form )
  {
    $html = '<dl>';

    foreach ( $form->getElements() as $element ) {

      if( $element instanceof Zend_Form_Element_Submit ) {
        continue;
      }

      $html .= '<dt>' . $element->getLabel() . '</dt>';

      $value = $element->getValue();

      if( $element instanceof Zend_Form_Element_Checkbox ) {
        $value = ($value) ? 'Yes' : 'No';
      }
      else if( $element instanceof Zend_Form_Element_Select ) {
        $value = $element->getMultiOption($value);
      }

      $html .= '<dd>' . $value . '</dd>';
    }

    $html .= '</dl>';

    return $html;
  }
}

Единственная проблема с принятым ответом состоит в том, что вы создаете все элементы, а затем игнорируете их.

Используя логику управления из ответа fireeyedboy, вы можете вместо этого переключить все элементы на Zend_View_Helper_FormNote который делает то же самое.

Просто зависит от того, имеет ли значение оптимизация.

Я не уверен, что понимаю, но я думаю, что для опции просмотра вы можете просто получить данные из вашей модели. Нет необходимости получать к ним доступ через Zend_Form.

Но если вы хотите, чтобы ваша форма была доступна только для чтения, вы можете добавить атрибут readonly (setAttrib('readonly', 'readonly')) к вашим элементам.

Другие вопросы по тегам