web-dev-qa-db-ja.com

Zend Formライブラリを正しく使用していますか? (私はコントローラーとビューで作業を効果的に複製しています)

簡単な要約

この質問は、各フォーム要素(コントローラー側)を構築する方法と各要素(ビュー側)をレンダリングする方法を指定できる_Zend Form_ライブラリを処理する方法に関するガイダンスを求めています。各フォーム要素が1回だけ処理される非Zend-Formアプローチと比較すると-ビューのみ

Zendフォームの動作

コントローラ側では、Zend Formを使用して各フォーム要素を構築できます。注:コードでは、オブジェクト指向のHTML要素を構築し、それらの値と属性(後でレンダリングするCSS属性を含む)をすべてコントローラーコード内にプログラムで入力できることを示します。

別紙A-Zendフォームコントローラ側

_    //create checkbox
    $checkbox = new Element\Checkbox('construction');
    $checkbox->setLabel("Construction: ");
    $checkbox->setChecked(true);
    $checkbox->setAttribute('onclick', 'return false'); // disable checkbox

    // Set up
    $listPrice = new Element\Text('listprice');
    $listPrice->setLabel("List Price: ");
    $listPrice->setValue('123.00');
    $listPrice->setAttribute('disabled', 'disabled');
    $listPrice->setAttribute('style', 'color:black;text-align:right');
    $listPrice->setAttribute('size', 9);

    // Assemble Form
    $form = new Form('form');
    $form->add($checkbox);
    $form->add($listPrice);

    // return rendered HTML
    return $this->partial("form.phtml", array(
        'form' => $form
    ));
_

それから私の見解

まず、ビューでZF2sometimesが実際のHTMLフォームのレンダリングの大部分を占めており、多くのことを行う必要がないことを最初に示したいと思います。つまり、$this->form()->render($form)を使用してフォーム全体をレンダリングできますが、必要に応じて各要素にカスタムスタイルを配置することはできません。また、すべての要素が1つの行にレンダリングされるため、めったに必要ありません。

私の場合、次の次のコードブロックでは、レンダリングプロセス中に_<p></p>_などの独自のHTML要素を追加できるように、フォームをより半自動でレンダリングする必要がありました。つまり、openTagおよびcloseTagおよびformRowメソッドなどを使用する必要がありました。

図B-Zendフォームビュー側

_/**
 * inside view template - with custom HTML 
 * custom HTML is one that contains form_row class
 * It will not render if I use $this->form()->form($form)
 * to render out complete form in one go.
 *
 * @var $this \Zend\View\Renderer\PhpRenderer
 * @var $form \Zend\Form\Form
 */
$form = $this->form;
?>
<style>
.form_row {
    margin-bottom: 14px;
    margin-top: 14px
}
</style>
<fieldset>
    <?php
    //renders <form ... >
    echo $this->form()->openTag($form);

    //loops through each form element, and passes it to "formrow" method
    //that renders out full element in HTML    
    foreach ($form as $element)
        $formContent .= '<p class="form_row">' . $this->formrow($element) . '</p>';

    echo $formContent;

    //renders </form>
    echo $this->form()->closeTag();
    ?>
</fieldset>
_

しかし、深く行くほど、より多くのコードを記述しなければなりません。カスタムスタイルのeach要素が必要な場合は、ビューの各要素を手動で参照する必要があります

Zendフォームを使用したカスタムスタイルの個別要素のレンダリング

_<label>
    <span><?=$this->formLabel($form->get('listPrice'));?></span>
    <?=$this->formInput($form->get('listPrice'));=>
    <?=$this->formElementErrors($form->get('listPrice'));?>

    <div id="custom_form_div_between_elements">
        Custom div that would not be rendered inside this form, 
        if I left ZF2 on auto-pilot like in a previous example
    </div>

</label>
_

eachフォーム要素に対して上記を行うことを想像してください。

したがって、基本的にはコードを記述します。両方とも、プログラムでControllerのフォーム要素を定義してから、ビューにレンダリングするコードを記述します。 ダブルワーク。二重コード

質問

各フォーム要素を処理する方法(コントローラーとビューの両方)でコードを2回記述することはあまりありません。

代わりに、すべてをビュースクリプトに配置することで、より良い結果を得ることができます。

別紙C-_Zend Form_を使用しない例(独自の要素のレンダリング)

_<label>
    <span>List Price: </span>
    <input name="listprice" disabled="disabled" 
        style="color:black;text-align:right" size="9" 
        value="<?=$price?>" type="text">
</label>
_

図D-_Zend Form_)を使用しない場合の完全な「実際のコード」[選択]の例

_<select name="id" id="modelid" class="validate[required]">
    <option>blank</option>
<?
$sql = "SELECT distinct(model), id FROM product GROUP BY model";
$result = db_query($sql);

for ($i = 0; $i < db_num_rows($result); $i ++)
{
    $row = db_fetch_array($result);
    ?>
    <option value="<?=$row['id']?>"
        <?=$productid == $row['id'] ? ' selected="selected"' : ''?>>
            <?=$row['model']?>
    </option>
    <?
}
?>
</select>
_

質問の要約

ZF2では、_Zend Form_コードを使用してコントローラーでフォーム要素を作成し、それらに値を入力してから、さまざまなZend機能を使用してビューで要素をレンダリングできます。取得したい詳細に応じて(つまり、要素ごとにカスタムスタイルを設定する場合)、要素ごとにかなりの作業を行っています。これは、重複しているように感じます。コントローラーの各要素を処理する必要があります。そしてあなたのビューで。確かに、一部の作業はより簡単です。つまり、_<select>_または_<input type="radio">_要素では、選択ボックスを確認するためにPHPとHTMLをハックアップする必要はありません)選択した特定の値で表示されます。Zendが自動的に処理します。

ネイティブのデフォルトのZend Form機能を使用して、提供するものを何でも出力するのは素晴らしいことです。その後、コントローラでのみ作業を行います。しかし、カスタムスタイリングが必要になった瞬間に、ビューで追加の作業を行います。コントローラーの場合と同じように、ビュー内のフォームの各要素のコードと同じくらい多くのコードがある場合があります。

ボーナス質問

  • Zend Formは、コントローラーとビューのコードを分割することでどのような問題を解決しますか?これを正しく使用していますか? (この2倍の仕事は正当化されますか?)

  • Zendフォームのすべてのコードコントローラをに移動して、すべての「2xコード」をビューに表示するなどの方法をとればよいでしょうか?

7
Dennis

表示されている例は正しいですが、Zend\Formはコントローラーで使用したいものとは異なります。私は_Exhibit A_について話している。2つの要素を持つフォームを作成、入力、およびスタイルするためのコードの量を示している。そのようにフォームを作成するのは退屈です。

コントローラーをフォームファクトリに変換しないようにするには、必要なフォームを作成するファクトリを作成する必要があります(例:AppFormFactory)。したがって、コントローラーは次のようになります。

_$product = Model::getRandomProduct();
$form = AppFormFactory::create('ProductForm');
$form->bind($product);
_

Zend\Form関連のコードはAppFormFactoryの実装内にあります。または、Zend\Form\Factoryを使用して、プログラムでフォームを作成する代わりに、構成配列を渡してフォームを作成することもできます。

もう1つ指摘したいのは、モデルと構成済みのフォームがある場合、ご覧のように、フォーム内のすべての要素の値を設定する代わりに$form->bind($product)を実行できることです。これは、多くの要素を含むフォームで作業する場合に役立ちます(例:製品フォームの編集)。

アノテーションを使用して、すべての配線(検証、ハイドレーションなど)を含むフォームを作成することもできます。 Zend\Formドキュメント の最後のセクションを確認してください。最後のコメントとして、スタイリングの部分(フォントサイズ、色)は、CSSの一部でなければなりません。

1
imel96

例を試してみて、私はそれを正しく使用していると思います。つまり、ビューをneaterおよびより標準化するという点で、Zend Formを使用することにはいくつかの利点がありますそして、私が当初考えていたほどの作業ではありませんでした。

フォーム要素を設定する「バルク」は、実際にはコントローラーにシフトされます。ビューでは、Zendフォームビューヘルパーメソッド呼び出しを使用してラベルと要素自体をレンダリングするだけです。これは、すべての要素で同じです(標準化されています)。これにより、ビューもきれいになります。したがって、非プログラマーである誰かがビューを編集している場合、問題の「別紙D」の混乱を見て、処理する必要はありません。

以下の質問の「別紙D」と比較してください。

コントローラ(ゼンドフォーム)

    $result = $this->em->createQuery('SELECT m.name from Entity\Product m')
        ->getScalarResult();
    $options = array();
    foreach ($result as $key => $value)
        $options[$value['name']] = $value['name'];

    $productSelect = new Element\Select('product_name');
    $productSelect->setLabel('Product Name');
    $productSelect->setValueOptions($options);
    $productSelect->setValue('143AT');

ビュー(Zendフォーム)

    <?=$this->formLabel($form->get('product_name'));?>
    <?=$this->formSelect($form->get('product_name'));?>
0
Dennis