web-dev-qa-db-ja.com

Zend Form:どうすれば自分の意志に合わせて曲げることができますか?

私は何度もマニュアルを読み、このテーマに関してGoogleが提供する投稿を精査し、ZFを扱った本を数冊購入しました。さて、なぜ私はまだ混乱しているのですか?

Zend_Formを使用して、検証と機能を正常に行うフォームを作成できます。私ができないことは、私が望んでいるエラーメッセージで見たいとまったく同じように見えるフォームを作成します。カスタムボタンが欲しい、ファンキーなレイアウトが欲しい、フォームの途中にテキストを挿入したいなど。

誰かがこの種のことを達成する簡単な方法を持っていますか?フレームワークがコストをかけるのではなく時間を節約しているように感じさせる何かがありますか? Zend Formを放棄することができます...独自のフォームを作成し、そのアクションをページにヒットさせて、投稿されたデータを検証および処理します。入力できる限り高速に実行できますが、これを「取得」して、明らかに意図されたとおりに使用する。

何かアドバイス?カスタムボタン、ファンキーなレイアウト、およびzendフォームを使用した基本的な(または難しい問題をスキップする基本的なチュートリアルがたくさんあるのでかなり高度な)「物事を成し遂げる」ための簡単な「ハウツー」はありますか?

42
rg88

バレットコンラッドのアドバイスは私が提案したであろうものです。また、フォームをレンダリングするためにフォームオブジェクトを使用する必要はないことに注意してください。

できることの1つは、フォームクラスと同じ名前の要素を持つフォームをビュースクリプトで作成することです。

HTMLフォーム:

<form action="/login/" method="post">
<fieldset>
    <label for="username">Username:</label>
    <input type="text" size="10" name="username" />
    <label for="password">Password:</label>
    <input type="password" size="10" name="password" />
    <input type="submit" />
</fieldset>
</form>

あなたのクラス:

class LoginForm extends Zend_Form
{
    public function init()
    {
        $username = $this->createElement('text','username');
        $username->setRequired(true);
        $this->addElement($username);

        $password = $this->createElement('password','password');
        $password->setRequired(true);
        $this->addElement($password);        
    }
}

フォームクラスはHTMLフォームを反映しており、クラスの各要素には独自のバリデーターと要件があります。アクションに戻ると、フォームクラスのインスタンスを作成し、そのフォームに対して投稿/取得変数を検証できます。

$form = new LoginForm();
if ($this->_request->isPost()) {
    if ($form->isValid($this->_request->getParams())) {
        // do whatever you need to do
    } else {
        $this->view->errors = $form->getMessages();
    }
}

この方法を使用すると、フォームの上部に1つのグループのエラーメッセージを表示できます。

これは基本的な例ですが、デコレータの使い方を学ぶために時間を費やすことなく、フォームの表示を完全に制御できます。私の意見では、Zend_Formの強みの多くは、検証とフィルタリングのプロパティにあります。これはあなたにその強さを与えます。このようなソリューションの主な欠点は、ビュースクリプトのHTMLフォームがフォームクラスと同期しなくなる可能性があることです。

26
Darcy Hastings

ビュー内の各要素を個別にレンダリングします-たとえば

<!-- view script here -->
<form method="POST">
Name: <?php echo $this->myForm->getElement('name')->render(); ?>
some other text between the fields
Birthdate: <?php echo $this->myForm->getElement('birthdate')->render(); ?>
<input type="submit" />
</form>

これにより、Zend_Formビューヘルパーを使用する機能(つまり、検証が失敗したときにエラーメッセージを表示し、フォームフィールドの値を維持する機能)が維持されますが、完全なカスタマイズ機能が提供されます。

さらに進みたい場合は、個々のフォーム要素のデフォルトのデコレータをオフにしてから、独自のデコレータをアタッチして、使用するタグを正確にカスタマイズするか(エラーメッセージとラベル用)、デコレータをまったく使用しない(その他フォーム要素自体をレンダリングするよりも)、周囲のすべてのHTMLを手動で記述します。フォームレベルとビューレベルの両方で、Zend_Formの利点を失うことなく完全なカスタマイズ機能。

11
mjh_ca

Matthew Weier O'Phinneyは、Zend_Formデコレータに関する一連のブログ投稿を開始しました。

  1. 最も単純なZend_Formデコレータ
  2. 裏返し:デコレータを重ねる方法
  3. Zend_Formデコレータを個別にレンダリングする
  4. 複合要素の作成
9
mercator

現在、新しくて光沢のあるZend\Formこれは古いコンポーネントよりもさらに複雑ですが、はるかに制御可能で、カプセル化され、強力です。したがって、以下で述べたことは当てはまりません。新しいコンポーネントは、IMHOの大幅な改善です。

  • ...フォームのレンダリング方法を完全に制御できます。もう少しビューコードを記述する必要がありますが、それだけの価値があります。
  • ...データ、ロジック、およびビューを可能な限り分離します
  • ... HTML5フォーム要素を利用します
  • ...フォームをどのように組み合わせるかについて、多くのオプションがあります。水分補給、注釈など。

Zend_Formに関する古い回答

まったく同じ問題を抱えているせいか、どうしようもありません。 Zend_Formデコレータは強力だと思いますが、これまでに見た中でプログラマーにやさしく、直感的ではないZFの一部であり、さまざまなプロジェクトでZFの大部分を使用しました。

それは私が私の経験からほんの少しのヒントを与えることができると言った:

  • フィルタはフォームを使用せずに簡単に使用できます
  • 達成したいことのすべてではないにしても、ほとんどはデコレータの助けを借りて行われます
  • 私は小さなフォームから始めて、少しずつ追加しましたが、結果が試行錯誤に基づいているため(主にデコレータで)、一部のフォームで行っていることの一部が得られません
  • Zendメーリングリストから、ウェブ上のどこにも見つからなかった情報を入手しました。

右側のこれに関連する質問から、特に直感的でない性質を考えると、Zend_Formの包括的なドキュメントが不足していることは明らかです。 Zend Frameworkが好きなだけ、ZFの人たちにこれについて何かしてもらいたいと思っています。

したがって、この答えはおそらく、この問題を抱えているのはあなただけではないことを知らせるためだけのものです。


または、代わりにジェダイマインドトリックもちろん使用することもできます!

5
markus

言われたことに追加するには:

デコレータを恐れないでください。Zend_Formを使い続けることにした場合は、デコレータをたくさん使用することになります。一度「取得」するとかなり簡単ですが、残念ながらドキュメントは弱く、そこに到達するためのほとんど唯一の方法はそれで遊ぶことです。

ViewScriptおよびViewHelperデコレータは、多くのパワーを提供します。

存在するさまざまなデコレータのソースを掘り下げて、それらがどのように動作しているかを確認することを恐れないでください(元のデコレータと道場のデコレータを比較してかなりの洞察を得ました)。

Seanが示唆していたのは、form-> renderを呼び出す必要はなく、ビュースクリプトでこのようなものを使用できるということだと思います。

 <someHtmlThingy name="blah" value="<?php echo $this->formInstance->getElement('whatever')->getValue(); ?>" />

私は1つのプロジェクト(Zend_Formより前)に取り組み、バリデーターのセットを作成し、標準のビュースクリプトをずっと使用しました。 Zend_Formを使用して要素を作成する場合と比較すると、少し手間がかかりましたが(エラーメッセージなどの配管作業)、過度ではありませんでした。

ViewScriptデコレータを使用せずにフォーム要素の前後に任意のマークアップを追加したい場合は、AnyMarkupデコレータを使用できます: http://www.zfsnippets.com/snippets/ view/id/62

たとえば、ラッパータグ内の画像を入力フィールドの前に追加する方法は次のとおりです(自動読み込みを正しく設定するには、パスを含める必要があります)。

 $ form-> addElement( 'text'、 'my_field'、array(
 'label' => '情報を入力:'、
 'デコレータ' => array(
 'ViewHelper'、
 array( 'AnyMarkup'、array(
 'markup' => '<span class = "imgwrapper">'。
 '<img src = "info.png" alt = "情報アイコン" /> </ span> ')、
'配置 '=>'先頭に '
)、
' HtmlTag ' 、
 'ラベル' 
)
); 
3
chiborg

whycantitbemorethan25cが上記で言及しましたが、 ViewScripts は、フォームをレンダリングするための非常にきめ細かい制御を提供します。 Zend_Formは高速であることが意図されているため、標準のデコレータなどの多くのデフォルトを想定し、フォームオブジェクトに追加された方法で要素を順序付けます。 ViewScriptを使用すると、その多くをスキップして、すべての要素を通常のHTML内に配置できます。

ただし、デコレータの概念を完全にスキップしないでください。後でViewScriptで使用される場合でも、個々の要素のスタイルを設定します。たとえば、他の人が示唆しているように、エラーメッセージにそれらを使用できます。

同様のアクションを持つ複数のデータポイントを持つ非常に複雑なフォームがある場合(それぞれにアクティブ/非アクティブボタンと削除ボタンがあるユーザーのリストを考えてください)、 Zend_Form_SubForm を検討する必要があります。サブフォームは、通常のフォームと同じようにViewScriptを利用できます。フォームを、独自のViewScriptを持つサブフォームを含むViewScriptとカスケードすると、単純なフォームよりもはるかに強力なロジックとプレゼンテーションが適切に含まれるようになります。

2
Barrett Conrad

フォーム全体のデコレータをスキップする(つまり、フォームの標準のビューヘルパーにすべてを処理するのではなく、フォームの個々の要素を印刷する)ことは、一連の制御を取り戻す1つの方法です。

もう1つのオプションは、フォームを手作業でコーディングし、ZFのみを使用して検証とフィルタリングを処理することです。

2

残念ながら、実際の特定の目的や目標を念頭に置いていない限り、例やハウツーを書くのは非常に難しいため、より複雑な問題はスキップされます。私はここで別の開発者を支援するためにしばらく時間を費やしましたSO誰が 非表示の要素の表示方法を変更する )詳細にダウン。

より複雑なタスクの大部分は、実際には特定のフィールドタイプのデフォルトヘルパーを拡張することになります。たとえば、検証エラーテキストを書き出す代わりに、フォームの送信後に検証に合格しなかったすべてのフィールドにクラス「エラー」を適用したいプロジェクトがありました。

_<label for="field">Label:</label>
<input type="text" name="field" id="field" class="error">
_

ビューヘルパーはデフォルトで実際のフォーム要素を使用できないため、かなり複雑なプロセスでした。そのため、ヘルパーは要素に検証エラーがあるかどうかを確認できません。だから私は次のプロセスに取り掛かりました:

  1. 「エラー」クラスを適用するフィールドタイプごとに、カスタマービューヘルパーを作成する必要がありました。その中で、formXXX()メソッドをオーバーライドし、要素にエラーがないかどうかを確認するチェックを追加します。さらに、デコレータが要素のインスタンスを設定するために呼び出すことができるsetElement()メソッドを追加して、ヘルパーがエラーをチェックできるようにしました。
  2. 次に、デフォルトの_Zend_Form_Decorator_ViewHelper_をオーバーライドする必要がありました。その中で、ビューにアクセスしてフォーム要素タイプのヘルパーをインスタンス化し、ビューヘルパーで作成したsetElement()メソッドの存在を確認し、存在する場合は設定しました。これを行うことで、スクリプト全体を無効にすることなく、一部のフォーム要素タイプを拡張でき、他のタイプは拡張できませんでした。
  3. 各フォームのinit()関数で、新しいフォームデコレータを指す新しい要素プレフィックスパス(addElementPrefixPath('My_Form_Decorator'), 'path/to/decorator'))を追加する必要がありました。
  4. 最後に、Zend Frameworkが最初の箇条書きで作成したヘルパーを見つけることができるように、アプリケーションにヘルパーパスを追加する必要がありました:addHelperPath('/path/to/helpers', 'My_View_Helper');

複雑なチュートリアルを書くのに実際の問題が本当に必要な理由がわかります。これらの種類のヘルパーまたは複雑なデコレータスキームを設定することの大きな部分は、すべてが前もって煩わしいものであっても、同じデザインスキームに準拠する多くのフォームを非常に簡単に作成し、変更があった場合に出力を非常に迅速に均一に変更できることです作成する必要があります。しかし一方で、1つのフォームの利益のために単純なタスクを実行する方法を理解するのに多くの時間を費やしていると感じた場合は、スキップしてください。

ただし、より具体的なサポートが必要な場合は、喜んでサポートさせていただきます。別の質問をする(またはこれを更新する)だけで、私は手助けするために最善を尽くします。

2
chuckg

あなたはおそらくこれまでにこれを解決したでしょうが、私はいくつかの仕事をしていて、同様の解決策を必要としていました。

 form-> getSubform( 'subform'); 
 foreach($ subform as $ key => $ value){
 //ここにいくつかのマークアップとカスタムコード
 print $ value; 
 //いくつかのマークアップとここにカスタムコード
 
} 
?> 

foreachループ内で、テーブルマークアップを追加できます。テーブル行のキーに適切な名前を付けた場合、それらはフォームキーと一致する必要があります。キーによって適切なサブフォームを取得するループ、またはキーによって要素を取得するループを使用することもできます。キーがわかっている場合は、foreachループをスキップして、単にprint $ subform ['somekey']と言うことができます。 $ form-> setIsArray(true);と言ってメインフォームを設定すると仮定します。 (その最後の部分が厳密に必要かどうかはわかりませんが、複雑なフォームの場合は、とにかくそのように設定する必要があります。

デフォルトのデコレータを削除して、各要素内の印刷を完全に制御できるようにしました。 Zend_Formには、個々の要素をもう少し簡単に取得するための組み込みメソッドが必要です。しかし、これはかなりうまく機能すると思います。

それが誰かに役立つことを願っています!

1
msumme

ここに答えてください。それがあなたを助けることを願っています。私はそれを見つけるまで、異常な量の情報を調べました。

<table>
    <tr>
        <td>Page name: *</td>
        <td><?php echo $this->pageForm->header_title;?></td>
    </tr>

    <tr>
        <td>H1 tag: *</td>
        <td><?php echo $this->pageForm->h1_tag;?></td>
    </tr>

    <tr>
        <td>Page URL: *</td>
        <td><?php echo $this->pageForm->url;?></td>
    </tr>

    <tr>
        <td>Meta Description: </td>
        <td><?php echo $this->pageForm->meta_description;?></td>
    </tr>

    <tr>
        <td>Meta Keywords: </td>
        <td><?php echo $this->pageForm->meta_keywords;?></td>
    </tr>

    <tr>
        <td>Short Description: *</td>
        <td><?php echo $this->pageForm->short_description;?></td>
    </tr>

    <tr>
        <td colspan="2"><a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true"
                           title="add a caption to title attribute / or leave blank" class="thickbox">Open iFrame Modal</a></td>
         <td>
            <a href="<?php echo $this->websiteUrl;?>backend_template/list?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" onclick="javascript:getDataFromAddPage()" title="Select Template For Page" class="thickbox" > TEST FORM  </a>
         </td>
    </tr>

    <tr>
        <td>Featured: </td>
        <td><?php echo $this->pageForm->featured;?></td>
    </tr>

    <tr>
        <td>Mark as 404: </td>
        <td><?php echo $this->pageForm->is_404page;?></td>
    </tr>

    <tr>
        <td>Show in Navigation Menu: </td>
        <td><?php echo $this->pageForm->in_navmain;?></td>
    </tr>

    <tr>
        <td>Show in Static Menu:</td>
        <td><?php echo $this->pageForm->in_navstatic;?></td>
    </tr>

    <tr>
        <td><?php echo $this->pageForm->submit;?></td>
        <td><?php echo $this->pageForm->button_close;?></td>
    </tr>

</table>
1
Kesselring

Zend_Formとデコレータにいくつかのサブクラスを記述して、フォームを<table>にレイアウトしました。複数の送信ボタンを同じ行に表示するなどの特別なトリックもありました。

それを機能させるために、丸一日ハッキングをしました。 Zend 1.5.1に対して書かれているので、現在のバージョンで動作するかどうかはわかりませんが、興味があれば、ソースをどこかにアップロードできます。

これは、ZendFormsで非常によくある苦情のようです。

(CSSの純粋主義者が、テーブルを使用してフォームをレイアウトすることにうんちをすることはわかっています。ほとんどの場合、CSSの方が優れていることに同意しますが、見た目が良くないCSSを使用した適切なフォームレイアウトはまだ見ていません。お尻の醜い恨みのようです。テーブルを使用すると、フォームは「必要なすべてのブラウザでほぼ機能します」。)

編集:さて、お尻の醜い応急修理について言えば、私はgithubで表形式のzendフォームを生成するためのコードを配置しました。 ここ に移動して表示します。 (gaoshan88がそれを求めたからです。)

1
Evan

Sean McSomethingの最初のアドバイスは、私のために行く方法です。フォームをレンダリングするために_<?php echo $this->form ?>_を実行するのは魔法すぎるといつも思っていました。さらに一歩進んで、$element->renderDecorator()マジックメソッドを使用して、個々の要素ではなく個々のデコレータをレンダリングします。このように、デコレータを定義した順序について心配する必要はありません。そこにある必要があるだけで、厄介で直感的でないHtmlTagデコレータを追加する必要はありません。 これについてブログに投稿しました

0
monzee