2013-02-28 3 views
5

Введение

Я работаю с повторно используемым модулем администратора; ответственный за обработку аутентификации и ACL. Этот модуль поставляется с базовым контроллером, который может реализовать любой другой реализованный модуль. Таким образом, этот контроллер является Cp\AdminController и недоступен, но унаследован всеми другими контроллерами.Zend Framework 2 - Элемент выходной формы, объекты как HTML-поля

Проблема

У меня есть по умолчанию/домашний контроллер Cp\HomeController в том, что есть несколько действий; логин, выход из системы и пароль забытого/сброса. В настоящее время я работаю над Cp\HomeController::indexAction. В рамках этого метода я просто сделать следующее:

// ... controller logic ... 
public function indexAction() 
{ 
    if ($this->getAuth()->hasIdentity()) { 
     # XXX: This is the authorised view/dashboard. 
    } else { 
     # XXX: This is the unauthorised view; login page. 

     $loginForm = new Form\Login(); 

     # XXX: validation, and login form handling here. 

     return array(
      'form' => $loginForm 
     ); 
    } 
} 
// ... controller logic ... 

Проблема здесь есть, Cp\HomeController по умолчанию, использует ./module/Cp/view/cp/home/index.phtml шаблон; и выглядит следующим образом:

<h1>Authorisation Required</h1> 

<section id="admin-login"> 
    <?= $form ?> 
</section> 

я продлил Zend\Form с моей формой класса ./module/Cp/src/Cp/Form.php, это продолжается по любой форме классов. _Выберете в виду, что я переместлю этот класс в приложение, чтобы он был полностью развязан и полностью повторно использован.

<?php 
// @file: ./module/Cp/src/Cp/Form.php 

namespace Cp; 

use Zend\Form\Form as ZendForm; 
use Zend\Form\Fieldset; 
use Zend\InputFilter\Input; 
use Zend\InputFilter\InputFilter; 
use Zend\View\Model\ViewModel; 
use Zend\View\Renderer\PhpRenderer; 
use Zend\View\Resolver; 

class Form extends ZendForm 
{ 
    /** 
    * Define the form template path. 
    * @var String 
    */ 

    protected $__templatePath; 

    /** 
    * Define the view variables. 
    * @var Array 
    */ 

    protected $__viewVariables = array(); 

    /** 
    * Set the view variable. 
    * @param String $key The index for the variable. 
    * @param Mixed $value The value for the view variable. 
    * @return Cp\Form 
    */ 

    public function set($key, $value) 
    { 
     $this->__viewVariables[$key] = $value; 
     return $this; 
    } 

    /** 
    * Set the template path. 
    * @param String $path The path for the template file. 
    * @return Cp\Form 
    */ 

    public function setTemplatePath($path) 
    { 
     $this->__templatePath = $path; 
     return $this; 
    } 

    /** 
    * When the object is buffered in output, we're going to generate the view 
    * and render it. 
    * @return String 
    */ 

    public function __toString() 
    { 
     // Define our template file as form for resolver to map. 
     $map = new Resolver\TemplateMapResolver(array(
      'form' => $this->__templatePath 
     )); 

     // Define the render instance responsible for rendering the form. 
     $renderer = new PhpRenderer(); 
     $renderer->setResolver(new Resolver\TemplateMapResolver($map)); 

     // The form view model will generate the form; parsing the vars to it. 
     $view = new ViewModel(); 
     $view->setVariable('form', $this); 
     $view->setTemplate('form'); 

     foreach ($this->__viewVariables as $key => $value) { 
      if (! property_exists($view, $key)) { 
       $view->setVariable($key, $value); 
      } 
     } 

     return $renderer->render($view); 
    } 
} 

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

<?php 

namespace Cp\Form; 

use Zend\Form\Element; 

class Login extends \Cp\Form 
{ 
    public function __construct($name = 'Login', $action) 
    { 
     // Parse the form name to our parent constructor. 
     parent::__construct($name); 

     // Override default template, defining our form view. 
     $this->setTemplatePath(MODULE_DIR . 'Cp/view/cp/form/login.phtml'); 

     // Create our form elements, and validation requirements. 
     $email = new Element\Email('email'); 
     $email->setLabel('E-mail Address'); 

     $password = new Element\Password('password'); 
     $password->setLabel('Password'); 

     $submit = new Element\Submit('login'); 

     $this->setAttribute('action', $action) 
      ->setAttribute('method', 'post') 
      ->setAttribute('autocomplete', 'autocomplete') 
      ->add($email) 
      ->add($password) 
      ->add($submit); 
    } 
} 

Какой унаследованный __toString метод будет принимать определенный вид формы, и делают это. Это, где моя проблема, и мой вопрос возникает. В представлении (см. Ниже) я пытаюсь создать форму, используя фреймворк, без жесткого кодирования элементов HTML. Поскольку класс Cp\Form\Login может быть расширен и изменен, с другим полем или дополнительными полями, необязательными или обязательными или условными.

Есть ли способ быстро получить Zend для создания следующего HTML? Без использования частичных представлений или физической записи <input type="<?= ... ?>" name="<?= ... ?>" />. Это связано с тем, что атрибуты могут быть определены или перезаписаны внутри контроллеров, поэтому в данный момент атрибуты неизвестны; и должны быть открыты для гибкости.

<section class="authentication-form"> 
    <h2>Authentication Required</h2> 

    <!-- How-to: Generate the <form> tag and all it's attributes. --> 
    <?= $form->openTag() ?> 

    <? if ($ipAllowed): ?> 
     <p>Please choose an account to log in through.</p> 

     <fieldset> 
      <?= $form->get('email') ?> 
     </fieldset> 
    <? else: ?> 
     <p>Please log in using your e-mail address and password.</p> 

     <fieldset> 
      <?= $form->get('email') ?> 
      <?= $form->get('password') ?> 
     </fieldset> 
    <? endif ?> 

    <div class="action"> 
     <!-- How-To: Generate the <input type="submit" name="" ... attributes ... /> 
     <?= $form->get('login') ?> 
    </div> 

    <!-- How-To: Generate the form close tag. 
    <?= $form->closeTag() ?> 
</section> 

Надеюсь, это более понятно, чем раньше.

+0

Если речь шла об оказании форму, не зная, как он будет построен, вы могли бы просто 'echo $ this-> form ($ form);'. Не могли бы вы уточнить, что такое точный вопрос? – Ocramius

+0

Я обновил вопрос, я надеюсь, что мой вопрос и намерения более ясны. – ash

ответ

4

Я не уверен, каков ваш реальный вопрос. Не могли бы вы указать его явно, пожалуйста?

Zend\Form разработан таким образом, что он не делает сам, но оказывает просмотреть помощникам:

<?php 
echo $this->form()->openTag($this->form); 
echo $this->formCollection($this->form); 
echo $this->form()->closeTag($this->form); 

Вы могли бы, конечно, написать вспомогательный вид, что делает это для вас.

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

<?php 
namespace MyModule\View\Helper; 

use Zend\View\Helper\AbstractHelper; 


class RenderForm extends AbstractHelper 
{ 
    public function __invoke($fieldsToRender, $form) 
    { 
     $html = $this->view->form()->openTag($form) . PHP_EOL; 

     foreach ($fieldsToRender as $fieldName) { 
      $element = $form->get($fieldName); 
      $html .= $this->view->formRow($element) . PHP_EOL; 
     } 

     $html .= $this->view->form()->closeTag($form) . PHP_EOL; 

     return $html; 
    } 
} 

Тогда все, что вам нужно в своем скрипте, чтобы позвонить renderForm() ,

+0

Я думаю, что Эш просит способ визуализации формы без использования помощников, например, инкапсулировать ее в свою собственную модель представления (установить как дочерний элемент модель представления, использующая другой визуализатор) – Ocramius

+0

oh! Самый простой способ сделать это - открыть форму ServiceManager, а затем извлечь PHPRenderer в метод render() и использовать там помощники вида. –

+0

Извините, ребята, я переписал свою статью, надеюсь, что это немного яснее. Я думаю, что мой оригинальный вопрос был неоднозначным. @Ocramius - это именно то, что я пытаюсь выполнить. – ash

0

Используя ответ Роба, я построил свой собственный помощник для визуализации различных полей в виде текста (например, является фонд 5 строк):

namespace MyApp\View\Helper; 

use Zend\Form\View\Helper\FormRow; 
use Zend\Form\ElementInterface; 


class RenderForm extends AbstractHelper 
{ 
    public function __invoke(ElementInterface $element) 
    { 

     $html = ''; 
     $value = ''; 

     $attributes = $element->getAttributes(); 

     $type = $attributes['type']; 
     $label = $element->getLabel(); 

     if($type == 'text' or $type == 'textarea' or $type == 'datetime' or $type == 'hidden'){ 
      $value = $element->getValue(); 
     } 

     if($type == 'select'){ 
      $selectedValue = $element->getValue(); 
      if(is_bool($selectedValue)){ 
       $selectedValue = (int) $selectedValue; 
      } 
      $options = $element->getValueOptions(); 
      $values = ''; 
      foreach($options as $value => $option){ 
       if((!empty($value) or $value == 0) and $value === $selectedValue){ 
        $values .= $option . '<br />'; 
       } 
      } 
      $value = $values; 
     } 

     if($type == 'multi_checkbox' ){ 
      $selectedOptions = $element->getValue(); 
      $options   = $element->getValueOptions(); 
      $values = ''; 
      foreach($options as $option){ 
       $optionValue = $option[ 'value' ]; 
       if( in_array($optionValue, $selectedOptions)){ 
        $values .= $option[ 'label' ]. '<br />'; 
       } 
      } 

      $value = $values; 
     } 

     if($value == ''){ 
      $value = 'N/A'; 
     } 

     $html .= '<div class="row"> 
         <div class="small-12 column"> 
          <div class="row"> 
           <div class="small-3 columns"><label class="right inline" for="tag_id">' . $label . '</label></div> 
           <div class="small-9 columns left" style="padding-top:10px">' . $value . '</div> 
          </div> 
         </div> 
        </div>'; 
     return $html; 
    } 
} 
Смежные вопросы