5

序章

再利用可能な管理モジュールを使用しています。認証とACLの処理を担当します。このモジュールには、実装されている他のモジュールが継承できるベースコントローラーが付属しています。したがって、このコントローラーはCp\AdminControllerアクセス可能ではありませんが、他のすべてのコントローラーに継承されます。

問題

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>

うまくいけば、これは以前よりも明確になります。

4

2 に答える 2

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()です。

于 2013-02-28T07:50:54.083 に答える
0

Robの応答を使用して、さまざまなフィールドをテキストとしてレンダリングする独自のヘルパーを作成しました(例は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;
    }
}
于 2014-07-02T09:29:15.593 に答える