2013-02-28 24 views
5

Giới thiệu

Tôi đang làm việc thông qua mô-đun Quản trị viên có thể sử dụng lại; chịu trách nhiệm xử lý Xác thực và ACL. Mô-đun này đi kèm với bộ điều khiển cơ sở mà bất kỳ mô-đun nào khác được triển khai có thể kế thừa. Vì vậy, bộ điều khiển này là Cp\AdminController và không thể truy cập được, nhưng được tất cả các bộ điều khiển khác kế thừa.Zend Framework 2 - Phần tử biểu mẫu đầu ra, các đối tượng dưới dạng các trường HTML

Vấn đề

Tôi có một bộ điều khiển mặc định/home Cp\HomeController rằng có một vài hành động; đăng nhập, đăng xuất và quên/đặt lại mật khẩu. Hiện tại tôi đang làm việc trên Cp\HomeController::indexAction. Trong phương pháp này, tôi chỉ đơn giản là làm như sau:

// ... 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 ... 

Vấn đề ở đây là, Cp\HomeController theo mặc định, sử dụng ./module/Cp/view/cp/home/index.phtml mẫu; và trông giống như:

<h1>Authorisation Required</h1> 

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

tôi đã mở rộng Zend\Form với hình thức lớp học của riêng tôi ./module/Cp/src/Cp/Form.php, thì đây được mở rộng bởi bất kỳ lớp học mẫu. _Trong tâm trí, tôi sẽ di chuyển lớp này vào ứng dụng để nó hoàn toàn tách rời và hoàn toàn có thể tái sử dụng được.

<?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); 
    } 
} 

Tôi kế thừa lớp biểu mẫu này để tạo biểu mẫu Đăng nhập, trường địa chỉ email và mật khẩu chuẩn, một thứ có thể được sử dụng lại ở bất kỳ nơi nào xác thực có thể xảy ra.

<?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); 
    } 
} 

Phương pháp được thừa kế __toString sẽ lấy chế độ xem biểu mẫu đã xác định và hiển thị. Điều này là là vấn đề của tôi và câu hỏi của tôi xảy ra. Trong khung nhìn (xem bên dưới) Tôi đang cố gắng tạo biểu mẫu, bằng cách sử dụng khung công tác, mà không cần mã hóa cứng các phần tử HTML. Vì lớp Cp\Form\Login có thể được mở rộng và sửa đổi, với một trường khác hoặc các trường bổ sung, tùy chọn hoặc bắt buộc hoặc có điều kiện.

Có cách nào để nhanh chóng, có được Zend tạo HTML sau không? Không sử dụng chế độ xem một phần hoặc viết một cách vật lý <input type="<?= ... ?>" name="<?= ... ?>" />. Điều này là do các thuộc tính có thể được định nghĩa hoặc ghi đè bên trong các bộ điều khiển, do đó, các thuộc tính chưa được biết tại thời điểm này; và nên cởi mở với sự linh hoạt.

<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> 

Hy vọng điều này rõ ràng hơn trước đây.

+0

Nếu đó là về render một hình thức mà không biết làm thế nào nó được xây dựng, bạn có thể đơn giản là 'echo $ this-> form ($ form);'. Bạn có thể làm rõ câu hỏi chính xác là gì? – Ocramius

+0

Tôi đã cập nhật câu hỏi, tôi hy vọng câu hỏi của tôi, và ý định rõ ràng hơn – ash

Trả lời

4

Tôi không chắc chắn câu hỏi thực tế của bạn là gì. Bạn có thể chỉ định rõ ràng không?

Zend\Form được thiết kế sao cho nó không làm cho chính nó, nhưng được đưa ra bởi những người giúp đỡ xem:

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

Bạn dĩ nhiên có thể viết một helper điểm cho rằng thực hiện điều này cho bạn.

Ngoài ra, bạn có thể viết một helper điểm cho rằng có một danh sách các yếu tố để render và viết một helper điểm cho rằng làm điều gì đó như thế này:

<?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; 
    } 
} 

Sau đó, tất cả các bạn cần trong view script của bạn là để gọi renderForm() .

+0

Tôi nghĩ Ash đang yêu cầu một cách để hiển thị biểu mẫu mà không cần sử dụng người trợ giúp, chẳng hạn như đóng gói nó vào mô hình xem của riêng mình mô hình xem đang sử dụng trình kết xuất đồ họa khác) – Ocramius

+0

oh! Cách dễ nhất để làm điều đó là làm cho biểu mẫu ServiceManager nhận biết và sau đó truy xuất PHPRenderer trong phương thức render() và sử dụng trình trợ giúp xem ở đó. –

+0

Xin lỗi các bạn, tôi đã viết lại bài viết của mình, tôi hy vọng nó rõ ràng hơn một chút. Tôi nghĩ rằng câu hỏi ban đầu của tôi _was_ mơ hồ. @Ocramius - đó chính xác là những gì tôi đang cố gắng hoàn thành. – ash

0

Sử dụng phản ứng của Rob, tôi đã xây dựng helper của riêng tôi để làm cho các lĩnh vực khác nhau như văn bản (ví dụ là một dãy Foundation 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; 
    } 
} 
Các vấn đề liên quan