Changeset 21360
- Timestamp:
- 08/23/09 04:40:56 (4 years ago)
- Files:
-
- doc/branches/1.1/forms/ja/01-Form-Creation.txt (modified) (1 diff)
- doc/branches/1.1/forms/ja/02-Form-Validation.txt (modified) (11 diffs)
- doc/branches/1.1/forms/ja/03-Forms-for-web-Designers.txt (modified) (6 diffs, 1 prop)
- doc/branches/1.1/forms/ja/04-Propel-Integration.txt (modified) (5 diffs)
- doc/branches/1.1/forms/ja/08-Internationalisation-and-Localisation.txt (modified) (4 diffs)
- doc/branches/1.1/forms/ja/11-Doctrine-Integration.txt (modified) (6 diffs)
- doc/branches/1.2/forms/ja/01-Form-Creation.txt (modified) (10 diffs)
- doc/branches/1.2/forms/ja/02-Form-Validation.txt (modified) (13 diffs)
- doc/branches/1.2/forms/ja/03-Forms-for-web-Designers.txt (modified) (7 diffs)
- doc/branches/1.2/forms/ja/04-Propel-Integration.txt (modified) (12 diffs)
- doc/branches/1.2/forms/ja/08-Internationalisation-and-Localisation.txt (modified) (4 diffs)
- doc/branches/1.2/forms/ja/11-Doctrine-Integration.txt (modified) (13 diffs)
- doc/branches/1.2/forms/ja/A-Widgets.txt (modified) (8 diffs)
- doc/branches/1.2/forms/ja/B-Validators.txt (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
doc/branches/1.1/forms/ja/01-Form-Creation.txt
r20601 r21360 517 517 >XSS(クロスサイトスクリプティング)の対策 518 518 > 519 >ウィジェットに対してHTML属性を設定するか、デフォルト値を定義すると、`sfForm`クラスではHTMLコードを生成する際にXSS攻撃に対してこれらの値を自動的に保護します。この保護は`settings.yml`ファイルの`escaping_strategy`設定に依存しません。内容が別のメソッドによって 既に保護された場合、保護は再度適用されません。519 >ウィジェットに対してHTML属性を設定するか、デフォルト値を定義すると、`sfForm`クラスではHTMLコードを生成する際にXSS攻撃に対してこれらの値を自動的に保護します。この保護は`settings.yml`ファイルの`escaping_strategy`設定に依存しません。内容が別のメソッドによってすでに保護された場合、保護は再度適用されません。 520 520 > 521 521 >この処理で、生成されたHTMLを無効にする可能性がある`'`と`"`の文字も保護します。 doc/branches/1.1/forms/ja/02-Form-Validation.txt
r20601 r21360 49 49 ---------- 50 50 51 symfonyのフォームはフィールドで構成されます。1章で見てきたように、それぞれのフィールドはユニークな名前で識別されます。フィールドをユーザーに表示するために、それぞれのフィールドにウィジェット を結び付けました。ここでは、それぞれのフィールドにバリデーションルールを適用する方法を見てみましょう。51 symfonyのフォームはフィールドで構成されます。1章で見てきたように、それぞれのフィールドはユニークな名前で識別されます。フィールドをユーザーに表示するために、それぞれのフィールドにウィジェットがバインドされました。ここでは、それぞれのフィールドにバリデーションルールを適用する方法を見てみましょう。 52 52 53 53 ### sfValidatorBaseクラス … … 137 137 $this->form = new ContactForm(); 138 138 139 * ユーザーが`POST`リクエストでフォームを投稿すると、`bind()`メソッドによりフォームとユーザーの入力データが 結び付けられ、バリデーション処理が実行されます。フォームは**バインドされた状態**に変化します。139 * ユーザーが`POST`リクエストでフォームを投稿すると、`bind()`メソッドによりフォームとユーザーの入力データがバインドされ、バリデーション処理が実行されます。フォームは**バインドされた状態**に変化します。 140 140 141 141 [php] … … 144 144 $this->form->bind($request->getParameter('contact')); 145 145 146 * 一旦フォームがバインドされると、`isValid()`メソッドを利用してフォームの有効性をチェックできます:146 * いったんフォームがバインドされると、`isValid()`メソッドを利用してフォームの有効性をチェックできます: 147 147 148 148 * 戻り値が`true`の場合、フォームは有効なので、ユーザーはthank youページにリダイレクトされます: … … 173 173 クリーニングプロセスには、2つの主要なアクション: 入力データの**標準化**と**変換**があります。 174 174 175 既に`trim`オプションによるデータの標準化のケースについて説明しました。しかし、例えば日付フィールドでは、標準化のアクションはさらに重要です。`sfValidatorDate`は日付をバリデートします。このバリデータでは、タイムスタンプ、正規表現に基づくフォーマットなど、多くのフォーマットを利用できます。デフォルトでは、入力を単に返す代わりに`Y-m-d H:i:s`フォーマットに変換されます。したがって、開発者は入力フォーマットを気にすることなく、特定のフォーマットでデータを取得できることが保証されます。システムはユーザーに多くの柔軟性を提供し、開発者には一貫性を保証します。176 177 では、ファイルのアップロードのような変換アクションを考えてみましょう。ファイルは`sfValidatorFile`を利用してバリデートできます。 一旦ファイルがアップロードされると、バリデータはファイルの名前を返す代わりに`sfValidatedFile`オブジェクトを返します。`sfValidatedFile`オブジェクトを使用すると、ファイル情報の取り扱いがより簡単になります。この章の後半で、このバリデータを使う方法を説明します。175 すでに`trim`オプションによるデータの標準化のケースについて説明しました。しかし、例えば日付フィールドでは、標準化のアクションはさらに重要です。`sfValidatorDate`は日付をバリデートします。このバリデータでは、タイムスタンプ、正規表現に基づくフォーマットなど、多くのフォーマットを利用できます。デフォルトでは、入力を単に返す代わりに`Y-m-d H:i:s`フォーマットに変換されます。したがって、開発者は入力フォーマットを気にすることなく、特定のフォーマットでデータを取得できることが保証されます。システムはユーザーに多くの柔軟性を提供し、開発者には一貫性を保証します。 176 177 では、ファイルのアップロードのような変換アクションを考えてみましょう。ファイルは`sfValidatorFile`を利用してバリデートできます。いったんファイルがアップロードされると、バリデータはファイルの名前を返す代わりに`sfValidatedFile`オブジェクトを返します。`sfValidatedFile`オブジェクトを使用すると、ファイル情報の取り扱いがより簡単になります。この章の後半で、このバリデータを使う方法を説明します。 178 178 179 179 >**Tip** … … 217 217 | invalid | `Invalid.` | フィールドは無効 218 218 219 既に利用したバリデータに関するエラーコードは以下の通りです:219 すでに利用したバリデータに関するエラーコードは以下の通りです: 220 220 221 221 | **バリデータ** | **エラーコード** | … … 258 258  259 259 260 このエラーコード(`min_length`)に関連したデフォルトのエラーメッセージは、 既に説明したメッセージと異なります。2つの動的な値: ユーザーの入力データ(`foo`)と、このフィールドで許可する最小の文字数(`4`)を実装しています。リスト2-5では、これらの動的な値を利用してエラーメッセージをカスタマイズし、図2-7はカスタマイズした結果です。260 このエラーコード(`min_length`)に関連したデフォルトのエラーメッセージは、すでに説明したメッセージと異なります。2つの動的な値: ユーザーの入力データ(`foo`)と、このフィールドで許可する最小の文字数(`4`)を実装しています。リスト2-5では、これらの動的な値を利用してエラーメッセージをカスタマイズし、図2-7はカスタマイズした結果です。 261 261 262 262 リスト2-5 - 動的な値でエラーメッセージをカスタマイズする … … 364 364 } 365 365 366 保護が無い場合、ユーザーが`name`フィールドと同時に`is_admin`フィールドの値をフォームから投稿すると、このコードには脆弱性があります。このような投稿は、Firebugのようなツールを利用することで簡単に実現できます。実際、フォーム内に`is_admin`フィールドに関連 付けrられたバリデータがないため、`is_admin`の値は常に有効です。値が何であれ、`setFields()`メソッドは`name`プロパティだけでなく、`is_admin`プロパティも更新します。367 368 しかし、このコードで`name`と`is_admin`フィールドの両方に対して値を渡すテストすると、図2-8で示されるように、"Extra field name."グローバルエラーが表示されます。投稿されたフィールドに、バリデータが関連 付けられていないものがあるため、システムでエラーが生成されました。`is_admin`フィールドは`UserForm`フォームクラスで定義されていません。366 保護が無い場合、ユーザーが`name`フィールドと同時に`is_admin`フィールドの値をフォームから投稿すると、このコードには脆弱性があります。このような投稿は、Firebugのようなツールを利用することで簡単に実現できます。実際、フォーム内に`is_admin`フィールドに関連づけられたバリデータがないため、`is_admin`の値は常に有効です。値が何であれ、`setFields()`メソッドは`name`プロパティだけでなく、`is_admin`プロパティも更新します。 367 368 しかし、このコードで`name`と`is_admin`フィールドの両方に対して値を渡すテストすると、図2-8で示されるように、"Extra field name."グローバルエラーが表示されます。投稿されたフィールドに、バリデータが関連づけられていないものがあるため、システムでエラーが生成されました。`is_admin`フィールドは`UserForm`フォームクラスで定義されていません。 369 369 370 370 図2-8 - バリデータが見つからないエラー … … 422 422  423 423 424 よく見ると、フォームが有効であるにも関わらず、どんな値を投稿しても、thank youページ内で`name`フィールドの値が空になっています。実際、`$this->form->getValues()`で返される配列に値は設定されていません。`allow_extra_fields`オプションを無効にすることで、バリデータが存在しないエラーは発生しなくなりますが、`filter_extra_fields`オプションは、デフォルトで`true`に設定されており、バリデータが存在しない値をフィルタリングして、バリデート済みの値から削除します。リスト2-10で示すように、もちろんこの 振る舞いを変更することもできです。424 よく見ると、フォームが有効であるにも関わらず、どんな値を投稿しても、thank youページ内で`name`フィールドの値が空になっています。実際、`$this->form->getValues()`で返される配列に値は設定されていません。`allow_extra_fields`オプションを無効にすることで、バリデータが存在しないエラーは発生しなくなりますが、`filter_extra_fields`オプションは、デフォルトで`true`に設定されており、バリデータが存在しない値をフィルタリングして、バリデート済みの値から削除します。リスト2-10で示すように、もちろんこのふるまいを変更することもできです。 425 425 426 426 リスト2-10 - `filter_extra_fields`保護を無効にする … … 457 457 * `sfValidatorOr` : フィールドが少なくとも1つのバリデータのバリデーションをパスすると有効になります 458 458 459 論理バリデータのコンストラクタは、最初の引数としてバリデータのリストを取ります。リスト2-11では、同時に満たす必要がある2つのバリデータを`name`フィールドに関連 付けるために、`sfValidatorAnd`を使います。459 論理バリデータのコンストラクタは、最初の引数としてバリデータのリストを取ります。リスト2-11では、同時に満たす必要がある2つのバリデータを`name`フィールドに関連づけるために、`sfValidatorAnd`を使います。 460 460 461 461 リスト2-11 - `sfValidatorAnd`バリデータを使う … … 509 509 これまで説明したそれぞれのバリデータは、特定のフィールドと結びつけられ一度に1つの値のバリデーションのみを行います。デフォルトでは、フィールドのバリデーションはユーザーによって投稿された別のフィールドのデータに関係しませんが、コンテキストに依存したり、多くの別のフィールドの値に依存してバリデーションを行う場合もあります。例えば、2つのパスワードが同じでなければならないときや、開始日が終了日より前の日付でなければならないときに、グローバルバリデータが必要となります。 510 510 511 これら両方の場合において、それぞれのコンテキストでユーザー入力をバリデートするためにグローバルバリデータを使わなければなりません。プレバリデータもしくはポストバリデータをそれぞれ使うことで、個別のフィールドバリデーションの前または後にグローバルバリデータが処理されるように設定できます。通常はポストバリデータを使う方がベターです。データは 既にバリデートおよびクリーンアップされている、つまり標準化されたフォーマットになっているからです。リスト2-13では、`sfValidatorSchemaCompare`バリデータを利用して2つのパスワードの比較を実装する方法を示しています。511 これら両方の場合において、それぞれのコンテキストでユーザー入力をバリデートするためにグローバルバリデータを使わなければなりません。プレバリデータもしくはポストバリデータをそれぞれ使うことで、個別のフィールドバリデーションの前または後にグローバルバリデータが処理されるように設定できます。通常はポストバリデータを使う方がベターです。データはすでにバリデートおよびクリーンアップされている、つまり標準化されたフォーマットになっているからです。リスト2-13では、`sfValidatorSchemaCompare`バリデータを利用して2つのパスワードの比較を実装する方法を示しています。 512 512 513 513 リスト2-13 - `sfValidatorSchemaCompare`バリデータを使う … … 533 533 ポストバリデータを利用することで、2つの日付の比較が正確になることが保証されます。入力に使われる日付フォーマットに関わらず、`start_date`と`end_date`フィールドのバリデーションでは、比較できるフォーマット(デフォルトでは`Y-m-d H:i:s`)に常に変換されます。 534 534 535 デフォルトでは、プレバリデータとポストバリデータは、フォームに対してグローバルエラーを返します。とは言うものの、エラーを特定のフィールドに関連づけたい場合もあります。例えば、`sfValidatorSchemaCompare`バリデータの`throw_global_error`オプションを使うと、グローバルエラー(図2-10)にするか、またはエラーを最初のフィールドに関連 付ける(図2-11)かを選択できます。リスト2-15では、`throw_global_error`オプションの使い方を示しています。535 デフォルトでは、プレバリデータとポストバリデータは、フォームに対してグローバルエラーを返します。とは言うものの、エラーを特定のフィールドに関連づけたい場合もあります。例えば、`sfValidatorSchemaCompare`バリデータの`throw_global_error`オプションを使うと、グローバルエラー(図2-10)にするか、またはエラーを最初のフィールドに関連づける(図2-11)かを選択できます。リスト2-15では、`throw_global_error`オプションの使い方を示しています。 536 536 537 537 リスト2-15 - `throw_global_error`オプションを使う doc/branches/1.1/forms/ja/03-Forms-for-web-Designers.txt
- Property svn:mime-type deleted
r20601 r21360 4 4 1章と2章でウィジェットとバリデーションのルールを作る方法を見ました。これらを表示するために`<?php echo $form ?>`ステートメントを使いました。このステートメントのおかげで開発者は最終的にどのように表示されるのか考えなくてもアプリケーションのコードを書けます。フィールド(名前、ウィジェット...)を変更もしくは追加するたびにテンプレートを変更する必要はありません。開発者がモデルとビジネスロジックに重点的に取り組まなければならないとき、このステートメントは試作と初期の開発フェーズに適しています。 5 5 6 一旦オブジェクトモデルが安定してスタイルのガイドラインの準備ができれば、Webデザイナーは様々なアプリケーションのフォームに戻り整えることができます。6 いったんオブジェクトモデルが安定してスタイルのガイドラインの準備ができれば、Webデザイナーはさまざまなアプリケーションのフォームに戻り整えることができます。 7 7 8 8 この章を始める前に、symfonyのテンプレートシステムとビューレイヤーに精通しなければならなりません。そのためには、"The Definitive Guide to symfony"の[ビューレイヤーの内側](http://www.symfony-project.org/book/1_1/07-Inside-the-View-Layer)の章をご覧ください。 … … 146 146 147 147 >**TIP** 148 >すべてのフィールドは`id`生成属性を持ち、これによって開発者がCSSもしくはjavaScriptの 振る舞いを簡単に追加できます。148 >すべてのフィールドは`id`生成属性を持ち、これによって開発者がCSSもしくはjavaScriptのふるまいを簡単に追加できます。 149 149 150 150 プロトタイプのテンプレートのカスタマイズ … … 196 196 >オブジェクトを配列のように振る舞わせるには? 197 197 > 198 >PHP5以降では、オブジェクトはPHPの配列以外の 振る舞いを行うことができます。`sfForm`クラスはシンプルで短い構文を利用してそれぞれのフィールドに対してアクセスする権限を与えるArrayAccessの振る舞いを実装します。配列のキーはフィールド名で戻り値は関連ウィジェットのオブジェクトです:198 >PHP5以降では、オブジェクトはPHPの配列以外のふるまいを行うことができます。`sfForm`クラスはシンプルで短い構文を利用してそれぞれのフィールドに対してアクセスする権限を与えるArrayAccessのふるまいを実装します。配列のキーはフィールド名で戻り値は関連ウィジェットのオブジェクトです: 199 199 > 200 200 > [php] … … 253 253 >プロトタイプで使われた構造のフォーマットを変更するには? 254 254 > 255 >デフォルトでは、symfonyはフォームを表示するためにHTMLの配列を使います。この 振る舞いは特定の*フォーマッター(formatter)*によって変更できます。これらは組み込みもしくはプロジェクトに適合させるために特別に開発されます。フォーマッターを作るには、5章で説明されているクラスを作る必要があります。255 >デフォルトでは、symfonyはフォームを表示するためにHTMLの配列を使います。このふるまいは特定の*フォーマッター(formatter)*によって変更できます。これらは組み込みもしくはプロジェクトに適合させるために特別に開発されます。フォーマッターを作るには、5章で説明されているクラスを作る必要があります。 256 256 257 257 この構造から自由になるために、図3-6で示されるように、それぞれのフィールドは要素を生成するメソッドを持ちます: … … 275 275  276 276 277 これを行うにはフィールドのそれぞれの要素を個別に生成できるようにしなければなりません。フィールドにアクセスするために、`form`オブジェクトを連想配列として使用し、フィールド名をキーとして使用できることを 既に見ました。例えば、`email`フィールドは`$form['email']`でアクセスできます。リスト3-6は2つの列を持つフォームを実装する方法を示しています。277 これを行うにはフィールドのそれぞれの要素を個別に生成できるようにしなければなりません。フィールドにアクセスするために、`form`オブジェクトを連想配列として使用し、フィールド名をキーとして使用できることをすでに見ました。例えば、`email`フィールドは`$form['email']`でアクセスできます。リスト3-6は2つの列を持つフォームを実装する方法を示しています。 278 278 279 279 リスト3-6 - 2つのカラムで表示をカスタマイズする … … 505 505 * hiddenフィールからのエラーもしくは実際にはフォームに表示されないフィールド。これらはグローバルエラーにまとめられる。 506 506 507 フィールドに関連するエラーメッセージの実装方法を 既に調べたので、リスト3-15はグローバルエラーメッセージの実装方法を示します。507 フィールドに関連するエラーメッセージの実装方法をすでに調べたので、リスト3-15はグローバルエラーメッセージの実装方法を示します。 508 508 509 509 リスト3-15 - グローバルエラーメッセージを実装する doc/branches/1.1/forms/ja/04-Propel-Integration.txt
r20601 r21360 2 2 ====================== 3 3 4 Webプロジェクトにおいて、 大抵のフォームはモデルオブジェクトを作るもしくは修正するために使われます。ORMのおかげでこれらのオブジェクトは通常はデータベースでシリアライズされます。symfonyのフォームシステムはsymfonyに組み込まれているPropelと連動する追加レイヤーを提供し、これらのモデルオブジェクトに基づいたフォームの実装をより簡単にします。4 Webプロジェクトにおいて、たいていのフォームはモデルオブジェクトを作るもしくは修正するために使われます。ORMのおかげでこれらのオブジェクトは通常はデータベースでシリアライズされます。symfonyのフォームシステムはsymfonyに組み込まれているPropelと連動する追加レイヤーを提供し、これらのモデルオブジェクトに基づいたフォームの実装をより簡単にします。 5 5 6 6 この章ではフォームをPropelのオブジェクトモデルと統合する方法を詳しく検討します。Propelとsymfonyとの統合機能に習熟していることが大いに推奨されます。そうではない場合、"The Definitive Guide to symfony"の[モデルレイヤーの内側](http://www.symfony-project.org/book/1_1/08-Inside-the-Model-Layer)の章を参照してください。 … … 158 158 } 159 159 160 生成クラスは以前の章で 既に作成したフォームと非常に似ていますが、下記の内容が異なります:160 生成クラスは以前の章ですでに作成したフォームと非常に似ていますが、下記の内容が異なります: 161 161 162 162 * 基底クラスは`sfForm`の代わりに`BaseFormPropel`です … … 306 306 } 307 307 308 タスクは2つのテンプレート、`indexSuccess`と`editSuccess`も生成しました。`editSuccess`テンプレートは`<?php echo $form ?>`ステートメントを使わずに生成されました。`--non-verbose-templates`を利用して、この 振る舞いを修正できます:308 タスクは2つのテンプレート、`indexSuccess`と`editSuccess`も生成しました。`editSuccess`テンプレートは`<?php echo $form ?>`ステートメントを使わずに生成されました。`--non-verbose-templates`を利用して、このふるまいを修正できます: 309 309 310 310 $ ./symfony propel:generate-crud frontend author Author --non-verbose-templates … … 390 390 `propel:build-forms`と`propel:generate-crud`タスクによってモデルオブジェクトを表示する、作成する、編集し、削除する機能を持つsymfonyモジュールを作ることができます。これらのモジュールはモデルのバリデーションルールだけでなくテーブル間のリレーションも考慮します。一行も書かずにこれらすべてが行われます! 391 391 392 生成コードをカスタマイズする段階に来ました。フォームクラスが 既に多くの要素を考慮しているのであれば、いくつかの面をカスタマイズする必要があります。392 生成コードをカスタマイズする段階に来ました。フォームクラスがすでに多くの要素を考慮しているのであれば、いくつかの面をカスタマイズする必要があります。 393 393 394 394 ### バリデータとウィジェットを設定する … … 677 677 } 678 678 679 `propel:build-forms`を利用することでフォームにオブジェクトモデルをイントロスペクトさせる 大抵の要素を自動的に生成できます。この自動処理はいくつかの理由から役立ちます:679 `propel:build-forms`を利用することでフォームにオブジェクトモデルをイントロスペクトさせるたいていの要素を自動的に生成できます。この自動処理はいくつかの理由から役立ちます: 680 680 681 681 * 退屈で反復される作業をしなくて済むので、開発者の生活が楽になります。プロジェクト固有のビジネスルールに従ってバリデータとウィジェットのカスタマイズに焦点を当てることができます。 doc/branches/1.1/forms/ja/08-Internationalisation-and-Localisation.txt
r20601 r21360 2 2 ============================ 3 3 4 人気のあるWebアプリケーションの多くは 様々な言語で利用可能で、時にユーザーのcultureに基づいてカスタマイズされます。symfonyはこれらの機能の管理を楽にする組み込みのフレームワークを搭載しています(symfony bookの["国際化と ローカライズ"](http://www.symfony-project.org/book/1_1/13-I18n-and-L10n)の章を参照)。4 人気のあるWebアプリケーションの多くはさまざまな言語で利用可能で、時にユーザーのcultureに基づいてカスタマイズされます。symfonyはこれらの機能の管理を楽にする組み込みのフレームワークを搭載しています(symfony bookの["国際化と ローカライズ"](http://www.symfony-project.org/book/1_1/13-I18n-and-L10n)の章を参照)。 5 5 6 6 フォームフレームワークはユーザーのインターフェイス用の組み込みサポートを備えており国際化オブジェクトの管理を楽にする方法を提供します。 … … 59 59 ### 翻訳のために使うカタログを指定する 60 60 61 symfonyの国際化フレームワークの機能を利用する場合 (`http://www.symfony-project.org/book/1_1/13-I18n-and-L10n#Managing%20Dictionaries`)、フォームを特定のカタログにバインドできます。リスト8-3において、`ContactForm`フォームを`contact_form`カタログに関連 付けします。ですので、フォーム要素の翻訳は`contact_form.fr.xml`ファイルで捜索されます。61 symfonyの国際化フレームワークの機能を利用する場合 (`http://www.symfony-project.org/book/1_1/13-I18n-and-L10n#Managing%20Dictionaries`)、フォームを特定のカタログにバインドできます。リスト8-3において、`ContactForm`フォームを`contact_form`カタログに関連づけします。ですので、フォーム要素の翻訳は`contact_form.fr.xml`ファイルで捜索されます。 62 62 63 63 リスト8-3 - 翻訳カタログのカスタマイズ … … 79 79 ### エラーメッセージの国際化 80 80 81 時々、エラーメッセージにはユーザーによって投稿された値が埋め込まれます(例えば、"Eメールアドレスのuser@domainは有効ではありません。")。これをフォームクラスの中でカスタマイズされたエラーメッセージを定義してユーザーが投稿した値を簡単に利用できることを2章で 既に見ました。これらの参照は`%parameter_name%`のパターンに従います。81 時々、エラーメッセージにはユーザーによって投稿された値が埋め込まれます(例えば、"Eメールアドレスのuser@domainは有効ではありません。")。これをフォームクラスの中でカスタマイズされたエラーメッセージを定義してユーザーが投稿した値を簡単に利用できることを2章ですでに見ました。これらの参照は`%parameter_name%`のパターンに従います。 82 82 83 83 リスト8-4はこの原則をコンタクトフォームの`name`フィールドに適用する方法を示しています。 … … 131 131 >PHPのcallableは関数もしくはメソッドのインスタンスへの参照です。これは`is_callable()`関数に渡されるときに`true`を返すPHP変数でもあります。 132 132 133 リスト8-6で示されるクラスによって提供される独自の国際化メカニズムを 既に持つプロジェクトをマイグレートしなければならない場合を考えてみましょう。133 リスト8-6で示されるクラスによって提供される独自の国際化メカニズムをすでに持つプロジェクトをマイグレートしなければならない場合を考えてみましょう。 134 134 135 135 リスト8-6 - カスタムの国際化クラス doc/branches/1.1/forms/ja/11-Doctrine-Integration.txt
r20601 r21360 2 2 ========================= 3 3 4 Webプロジェクトにおいて、 大抵のフォームはモデルオブジェクトを作るもしくは修正するために使われます。通常これらのオブジェクトはORMのおかげでシリアライズ化されます。symfonyのフォームシステムはsymfonyに組み込まれたORMであるDoctrineと橋渡しをするための追加レイヤーを提供し、これらのモデルオブジェクトに基づくフォームの実装を簡単にします。5 6 この章ではフォームをDoctrineのオブジェクトモデルに統合する方法を詳しく説明します。Doctrineをsymfonyに統合して使うことに 既に慣れているのであれば大いにお勧めします。そうでなければ、"The Definitive Guide to symfony"の[モデルレイヤーの内側](http://www.symfony-project.org/book/1_1/08-Inside-the-Model-Layer)の章を参照してください。4 Webプロジェクトにおいて、たいていのフォームはモデルオブジェクトを作るもしくは修正するために使われます。通常これらのオブジェクトはORMのおかげでシリアライズ化されます。symfonyのフォームシステムはsymfonyに組み込まれたORMであるDoctrineと橋渡しをするための追加レイヤーを提供し、これらのモデルオブジェクトに基づくフォームの実装を簡単にします。 5 6 この章ではフォームをDoctrineのオブジェクトモデルに統合する方法を詳しく説明します。Doctrineをsymfonyに統合して使うことにすでに慣れているのであれば大いにお勧めします。そうでなければ、"The Definitive Guide to symfony"の[モデルレイヤーの内側](http://www.symfony-project.org/book/1_1/08-Inside-the-Model-Layer)の章を参照してください。 7 7 8 8 始める前に … … 158 158 } 159 159 160 生成クラスはわずかな違いを除いて、以前の章で 既に作成されたフォームによく似ています:160 生成クラスはわずかな違いを除いて、以前の章ですでに作成されたフォームによく似ています: 161 161 162 162 * 基底クラスは`sfForm`の代わりに`BaseFormDoctrine` … … 167 167 >Doctrineフォームのグローバルなカスタマイズ 168 168 > 169 >それぞれのテーブル用に生成されたクラスに加えて、`doctrine:build-forms`は`BaseFormDoctrine`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリの中の他のすべての生成クラスの基底クラスであり、Doctrineのすべてのフォームの 振る舞いをグローバルに設定することを可能にします。例えば、すべてのDoctrineフォーム用のデフォルトのフォーマッターを簡単に変更できます:169 >それぞれのテーブル用に生成されたクラスに加えて、`doctrine:build-forms`は`BaseFormDoctrine`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリの中の他のすべての生成クラスの基底クラスであり、Doctrineのすべてのフォームのふるまいをグローバルに設定することを可能にします。例えば、すべてのDoctrineフォーム用のデフォルトのフォーマッターを簡単に変更できます: 170 170 > 171 171 > [php] … … 330 330 } 331 331 332 タスクは`indexSuccess`と`editSuccess`の2つのテンプレートも生成しました。`<?php echo $form ?>`ステートメントを使わずに`editSuccess`テンプレートが生成されました。`--non-verbose-templates`を使用して、この 振る舞いを修正できます:332 タスクは`indexSuccess`と`editSuccess`の2つのテンプレートも生成しました。`<?php echo $form ?>`ステートメントを使わずに`editSuccess`テンプレートが生成されました。`--non-verbose-templates`を使用して、このふるまいを修正できます: 333 333 334 334 $ ./symfony doctrine:generate-crud frontend author Author --non-verbose-templates … … 419 419 `doctrine:build-forms`と`doctrine:generate-crud`タスクによってモデルオブジェクトの一覧を表示、作成、編集する機能を持つモジュールを作ることができます。これらのモジュールはモデルのバリデーションルールだけでなくテーブル間のリレーションも考慮されます。これらすべては一行のコードを書かずに行われます! 420 420 421 生成コードをカスタマイズしましょう。フォームクラスが 既に多くの要素を考慮しているのであれば、いくつかの面でカスタマイズする必要があります。421 生成コードをカスタマイズしましょう。フォームクラスがすでに多くの要素を考慮しているのであれば、いくつかの面でカスタマイズする必要があります。 422 422 423 423 ### バリデータとウィジェットを設定する … … 708 708 } 709 709 710 `doctrine:build-forms`を使うことでフォームはオブジェクトモデルをイントロスペクトして 大抵の要素を自動的に生成できます。この自動化はいくつかの理由から役に立ちます:710 `doctrine:build-forms`を使うことでフォームはオブジェクトモデルをイントロスペクトしてたいていの要素を自動的に生成できます。この自動化はいくつかの理由から役に立ちます: 711 711 712 712 * これによって繰り返される冗長な作業をしなくても済むので、開発者の人生が楽になります。開発者はプロジェクト固有のビジネスルールに従ってバリデータとウィジェットのカスタマイズに集中できます。 doc/branches/1.2/forms/ja/01-Form-Creation.txt
r20619 r21360 39 39 `configure()`メソッドに**ウィジェット**を追加するコードを記述することからフォームの設定を始めましょう。 40 40 41 **ウィジェット**はフォームフィールドを表します。この例のフォームでは、3つのフィールド: `name`, `email`、および`message`を表す3つのウィジェットを追加する必要があります。リスト1-1 に、`ContactForm`クラスの最初の実装を示します。41 **ウィジェット**はフォームフィールドを表します。この例のフォームでは、3つのフィールド: `name`, `email`、および`message`を表す3つのウィジェットを追加する必要があります。リスト1-1で`ContactForm`クラスの最初の実装を示します。 42 42 43 43 リスト1-1 - 3つのフィールドがあるフォームの`ContactForm`クラス … … 94 94 } 95 95 96 フォームがインスタンス化される際 、リスト1-1で定義した`configure()`メソッドは自動的に呼び出されます。97 98 アクションの修正 と合わせて、フォームを表示するためのテンプレートをリスト1-3のように作成する必要があります。96 フォームがインスタンス化される際に、リスト1-1で定義した`configure()`メソッドは自動的に呼び出されます。 97 98 アクションの修正に合わせてフォームを表示するために、リスト1-3のようなテンプレートを作成する必要があります。 99 99 100 100 リスト1-3 - フォームを表示するテンプレート … … 292 292 293 293 >**Tip** 294 >`executeSubmit()`が`executeIndex()`と異なることに気 づいたでしょうか。これらのメソッドを呼び出すとき、symfonyは現在の`sfRequest`オブジェクトを最初の引数として`executeXXX()`メソッドに渡します。PHPではすべてのパラメータを定義する必要はなく、また`executeIndex()`では`request`変数は必要なかったため、定義しませんでした。294 >`executeSubmit()`が`executeIndex()`と異なることに気がつかれたでしょうか。これらのメソッドを呼び出すとき、symfonyは`executeXXX()`メソッドに最初の引数として現在の`sfRequest`オブジェクトを渡します。PHPではすべてのパラメータを定義する必要はなく、また`executeIndex()`では`request`変数は必要なかったため、定義しませんでした。 295 295 296 296 図1-5に、ユーザーとインタラクトするときのメソッドのワークフローを示します。 … … 328 328 } 329 329 330 `setNameFormat()`を呼び出すことで、すべてのウィジェットが出力するHTMLの`name`属性を修正できます。フォームを生成するとき、`%s`は自動的にフィールドの名前に置き換えられます。 例えば`email`フィールドでは、`name`属性は`contact[email]`になります。PHPでは、`contact[email]`のようなフォーマットを含むリクエストの値に対して、配列が自動的に作成されます。このようすると、フィールドの値を`contact`配列として利用できます。330 `setNameFormat()`を呼び出すことで、すべてのウィジェットが出力するHTMLの`name`属性を修正できます。フォームを生成するとき、`%s`は自動的にフィールドの名前に置き換えられます。たとえば`email`フィールドでは、`name`属性は`contact[email]`になります。PHPでは、`contact[email]`のようなフォーマットを含むリクエストの値に対して、配列が自動的に作成されます。このようすると、フィールドの値を`contact`配列として利用できます。 331 331 332 332 リスト1-7で示すように、`request`オブジェクトから直接`contact`配列を取得できます。 … … 352 352 ### 別の解決方法 353 353 354 この例では、フォームを管理するために2つのアクション: 表示に対して`index` 、投稿に対して`submit`を使いました。フォームは`GET`メソッドで表示され`POST`メソッドで投稿されることを利用して、リスト1-8で示されるように2つのメソッドを`index`メソッドにマージすることもできます。354 この例では、フォームを管理するために2つのアクション: 表示に対して`index`、投稿に対して`submit`を使いました。フォームは`GET`メソッドで表示され`POST`メソッドで投稿されることを利用して、リスト1-8で示されるように2つのメソッドを`index`メソッドにマージすることもできます。 355 355 356 356 リスト1-8 - フォームで使われる2つのアクションをマージする … … 384 384 Webサイトが複数のWebマスターによって管理されている場合、質問内容に応じてメッセージをリダイレクトできるように、分類のドロップダウンリストを追加したいでしょう(図1-7)。リスト1-9では、`sfWidgetFormSelect`ウィジェットを利用して、ドロップダウンリストの`subject`を追加します。 385 385 386 図1-7 - `subject`フィールドをフォームに追加する387 388 389 390 リスト1-9 - `subject`フィールドをフォームに追加する386 図1-7 - フォームに`subject`フィールドを追加する 387 388  389 390 リスト1-9 - フォームに`subject`フィールドを追加する 391 391 392 392 [php] … … 439 439 > </select> 440 440 441 `sfWidgetFormSelect`ウィジェットは、すべてのウィジェットと同じように、 オプションのリストを最初の引数で受け取ります。オプションは必須もしくはオプションです。`sfWidgetFormSelect`ウィジェットでは、`choices`オプションは必須です。これまでに見てきたウィジェットで利用可能なオプションは下記の通りです:441 `sfWidgetFormSelect`ウィジェットは、すべてのウィジェットと同じように、最初の引数としてオプションのリストを受け取ります。オプションは必須もしくはオプションです。`sfWidgetFormSelect`ウィジェットでは、`choices`オプションは必須です。これまでに見てきたウィジェットで利用可能なオプションは下記の通りです: 442 442 443 443 | **ウィジェット** | **必須のオプション** | **追加のオプション** | … … 449 449 450 450 >**Tip** 451 >ウィジェットのすべてのオプションを知りた い場合、 ([http://www.symfony-project.org/api/1_2/](http://www.symfony-project.org/api/1_2/))で、オンラインで利用できる完全なAPIドキュメントを参照できます。追加のオプションやデフォルト値も合わせて、すべてのオプションが説明されています。例えば`sfWidgetFormSelect`のすべてのオプションは、次のURLで調べることができます: ([http://www.symfony-project.org/api/1_2/sfWidgetFormSelect](http://www.symfony-project.org/api/1_2/sfWidgetFormSelect)).451 >ウィジェットのすべてのオプションを知りたければ、([http://www.symfony-project.org/api/1_2/](http://www.symfony-project.org/api/1_2/))で、オンラインで利用できる完全なAPIドキュメントを参照できます。追加のオプションやデフォルト値も合わせて、すべてのオプションが説明されています。たとえば`sfWidgetFormSelect`のすべてのオプションは、次のURLで調べることができます: ([http://www.symfony-project.org/api/1_2/sfWidgetFormSelect](http://www.symfony-project.org/api/1_2/sfWidgetFormSelect)). 452 452 453 453 ### ウィジェットのHTML属性 … … 491 491 ### フィールドに対してデフォルトの値を定義する 492 492 493 それぞれのフィールドに対してデフォルト値を定義しておくと便利です。 例えば、ユーザーがフィールドにフォーカスを移すと消えるヘルプメッセージを、フィールド内に表示するときです。リスト1-13では、`setDefault()`と`setDefaults()`メソッドを利用してデフォルト値を定義する方法を示しています。493 それぞれのフィールドに対してデフォルト値を定義しておくと便利です。たとえば、ユーザーがフィールドにフォーカスを移すと消えるヘルプメッセージを、フィールド内に表示するときです。リスト1-13では、`setDefault()`と`setDefaults()`メソッドを利用してデフォルト値を定義する方法を示しています。 494 494 495 495 リスト1-13 - `setDefault()`と `setDefaults()`メソッド経由のウィジェットのデフォルト値 … … 528 528 >XSS(クロスサイトスクリプティング)の対策 529 529 > 530 >ウィジェットに対してHTML属性を設定するか、デフォルト値を定義すると、`sfForm`クラスではHTMLコードを生成する際にXSS攻撃に対してこれらの値を自動的に保護します。この保護は`settings.yml`ファイルの`escaping_strategy`設定に依存しません。内容が別のメソッドによって 既に保護された場合、保護は再度適用されません。530 >ウィジェットに対してHTML属性を設定するか、デフォルト値を定義すると、`sfForm`クラスではHTMLコードを生成する際にXSS攻撃に対してこれらの値を自動的に保護します。この保護は`settings.yml`ファイルの`escaping_strategy`設定に依存しません。内容が別のメソッドによってすでに保護された場合、保護は再度適用されません。 531 531 > 532 532 >この処理で、生成されたHTMLを無効にする可能性がある`'`と`"`の文字も保護します。 doc/branches/1.2/forms/ja/02-Form-Validation.txt
r20619 r21360 52 52 ---------- 53 53 54 symfonyのフォームはフィールドで構成されます。1章で見てきたように、それぞれのフィールドはユニークな名前で識別されます。フィールドをユーザーに表示するために、それぞれのフィールドにウィジェットを 結び付けました。ここでは、それぞれのフィールドにバリデーションルールを適用する方法を見てみましょう。54 symfonyのフォームはフィールドで構成されます。1章で見てきたように、それぞれのフィールドはユニークな名前で識別されます。フィールドをユーザーに表示するために、それぞれのフィールドにウィジェットをバインドしました。ここでは、それぞれのフィールドにバリデーションルールを適用する方法を見てみましょう。 55 55 56 56 ### sfValidatorBaseクラス … … 91 91 * `sfValidatorChoice`: 入力値と予め定義された選択のリストに対してバリデーションを行います 92 92 93 それぞれのバリデータは、最初の引数としてオプションのリストを 取ります。ウィジェットのように、これらのオプションの中には必須であるものと、必須ではないものがあります。例えば、`sfValidatorChoice`バリデータは1つの必須オプションである、`choices`を取ります。それぞれのバリデータは、`sfValidatorBase`クラスで定義された`required`と`trim`オプションを取ることもできます:93 それぞれのバリデータは、最初の引数としてオプションのリストを受け取ります。ウィジェットのように、これらのオプションの中には必須であるものと、必須ではないものがあります。たとえば、`sfValidatorChoice`バリデータは1つの必須オプションである、`choices`を受け取ります。それぞれのバリデータは、`sfValidatorBase`クラスで定義された`required`と`trim`オプションを受け取ることもできます: 94 94 95 95 | **オプション** | **デフォルト値** | **説明** … … 140 140 $this->form = new ContactForm(); 141 141 142 * ユーザーが`POST`リクエストでフォームを投稿すると、`bind()`メソッドによりフォームとユーザーの入力データが 結び付けられ、バリデーション処理が実行されます。フォームは**バインドされた状態**に変化します。142 * ユーザーが`POST`リクエストでフォームを投稿すると、`bind()`メソッドによりフォームとユーザーの入力データがバインドされ、バリデーション処理が実行されます。フォームは**バインドされた状態**に変化します。 143 143 144 144 [php] … … 147 147 $this->form->bind($request->getParameter('contact')); 148 148 149 * 一旦フォームがバインドされると、`isValid()`メソッドを利用してフォームの有効性をチェックできます:149 * いったんフォームがバインドされると、`isValid()`メソッドを利用してフォームの有効性をチェックできます: 150 150 151 151 * 戻り値が`true`の場合、フォームは有効なので、ユーザーはthank youページにリダイレクトされます: … … 176 176 クリーニングプロセスには、2つの主要なアクション: 入力データの**標準化**と**変換**があります。 177 177 178 既に`trim`オプションによるデータの標準化のケースについて説明しました。しかし、例えば日付フィールドでは、標準化のアクションはさらに重要です。`sfValidatorDate`は日付をバリデートします。このバリデータでは、タイムスタンプ、正規表現に基づくフォーマットなど、多くのフォーマットを利用できます。デフォルトでは、入力を単に返す代わりに`Y-m-d H:i:s`フォーマットに変換されます。したがって、開発者は入力フォーマットを気にすることなく、特定のフォーマットでデータを取得できることが保証されます。システムはユーザーに多くの柔軟性を提供し、開発者には一貫性を保証します。179 180 では、ファイルのアップロードのような変換アクションを考えてみましょう。ファイルは`sfValidatorFile`を利用してバリデートできます。 一旦ファイルがアップロードされると、バリデータはファイルの名前を返す代わりに`sfValidatedFile`オブジェクトを返します。`sfValidatedFile`オブジェクトを使用すると、ファイル情報の取り扱いがより簡単になります。この章の後半で、このバリデータを使う方法を説明します。178 すでに`trim`オプションによるデータの標準化のケースについて説明しました。しかし、たとえば日付フィールドでは、標準化のアクションはさらに重要です。`sfValidatorDate`は日付をバリデートします。このバリデータでは、タイムスタンプ、正規表現に基づくフォーマットなど、多くのフォーマットを利用できます。デフォルトでは、入力を単に返す代わりに`Y-m-d H:i:s`フォーマットに変換されます。したがって、開発者は入力フォーマットを気にすることなく、特定のフォーマットでデータを取得できることが保証されます。システムはユーザーに多くの柔軟性を提供し、開発者には一貫性を保証します。 179 180 では、ファイルのアップロードのような変換アクションを考えてみましょう。ファイルは`sfValidatorFile`を利用してバリデートできます。いったんファイルがアップロードされると、バリデータはファイルの名前を返す代わりに`sfValidatedFile`オブジェクトを返します。`sfValidatedFile`オブジェクトを使用すると、ファイル情報の取り扱いがより簡単になります。この章の後半で、このバリデータを使う方法を説明します。 181 181 182 182 >**Tip** … … 220 220 | invalid | `Invalid.` | フィールドは無効 221 221 222 既に利用したバリデータに関するエラーコードは以下の通りです:222 すでに利用したバリデータに関するエラーコードは以下の通りです: 223 223 224 224 | **バリデータ** | **エラーコード** | … … 261 261  262 262 263 このエラーコード(`min_length`)に関連したデフォルトのエラーメッセージは、 既に説明したメッセージと異なります。2つの動的な値: ユーザーの入力データ(`foo`)と、このフィールドで許可する最小の文字数(`4`)を実装しています。リスト2-5では、これらの動的な値を利用してエラーメッセージをカスタマイズし、図2-7はカスタマイズした結果です。263 このエラーコード(`min_length`)に関連したデフォルトのエラーメッセージは、すでに説明したメッセージと異なります。2つの動的な値: ユーザーの入力データ(`foo`)と、このフィールドで許可する最小の文字数(`4`)を実装しています。リスト2-5では、これらの動的な値を利用してエラーメッセージをカスタマイズし、図2-7はカスタマイズした結果です。 264 264 265 265 リスト2-5 - 動的な値でエラーメッセージをカスタマイズする … … 291 291 292 292 >**Tip** 293 >バリデータのすべてのエラーコード、オプション、デフォルトメッセージを確認したい場合は、APIのオンラインドキュメント ([http://www.symfony-project.org/api/1_2/](http://www.symfony-project.org/api/1_2/))を参照してください。デフォルト値に加えて、それぞれのコード、オプションとエラーメッセージが詳細に記述されています。 例えば、`sfValidatorString`バリデータのAPIは [http://www.symfony-project.org/api/1_2/sfValidatorString](http://www.symfony-project.org/api/1_2/sfValidatorString)で利用可能です。293 >バリデータのすべてのエラーコード、オプション、デフォルトメッセージを確認したい場合は、APIのオンラインドキュメント ([http://www.symfony-project.org/api/1_2/](http://www.symfony-project.org/api/1_2/))を参照してください。デフォルト値に加えて、それぞれのコード、オプションとエラーメッセージが詳細に記述されています。たとえば、`sfValidatorString`バリデータのAPIは [http://www.symfony-project.org/api/1_2/sfValidatorString](http://www.symfony-project.org/api/1_2/sfValidatorString)で利用可能です。 294 294 295 295 バリデータのセキュリティ … … 367 367 } 368 368 369 保護が無い場合、ユーザーが`name`フィールドと同時に`is_admin`フィールドの値をフォームから投稿すると、このコードには脆弱性があります。このような投稿は、Firebugのようなツールを利用することで簡単に実現できます。実際、フォーム内に`is_admin`フィールドに関連 付けrられたバリデータがないため、`is_admin`の値は常に有効です。値が何であれ、`setFields()`メソッドは`name`プロパティだけでなく、`is_admin`プロパティも更新します。370 371 しかし、このコードで`name`と`is_admin`フィールドの両方に対して値を渡すテストすると、図2-8で示されるように、"Extra field name."グローバルエラーが表示されます。投稿されたフィールドに、バリデータが 関連付けられていないものがあるため、システムでエラーが生成されました。`is_admin`フィールドは`UserForm`フォームクラスで定義されていません。369 保護が無い場合、ユーザーが`name`フィールドと同時に`is_admin`フィールドの値をフォームから投稿すると、このコードには脆弱性があります。このような投稿は、Firebugのようなツールを利用することで簡単に実現できます。実際、フォーム内に`is_admin`フィールドに関連づけられたバリデータがないため、`is_admin`の値は常に有効です。値が何であれ、`setFields()`メソッドは`name`プロパティだけでなく、`is_admin`プロパティも更新します。 370 371 しかし、このコードで`name`と`is_admin`フィールドの両方に対して値を渡すテストすると、図2-8で示されるように、"Extra field name."グローバルエラーが表示されます。投稿されたフィールドに、バリデータが連づけられていないものがあるため、システムでエラーが生成されました。`is_admin`フィールドは`UserForm`フォームクラスで定義されていません。 372 372 373 373 図2-8 - バリデータが見つからないエラー … … 425 425  426 426 427 よく見ると、フォームが有効であるにも関わらず、どんな値を投稿しても、thank youページ内で`name`フィールドの値が空になっています。実際、`$this->form->getValues()`で返される配列に値は設定されていません。`allow_extra_fields`オプションを無効にすることで、バリデータが存在しないエラーは発生しなくなりますが、`filter_extra_fields`オプションは、デフォルトで`true`に設定されており、バリデータが存在しない値をフィルタリングして、バリデート済みの値から削除します。リスト2-10で示すように、もちろんこの 振る舞いを変更することもできです。427 よく見ると、フォームが有効であるにも関わらず、どんな値を投稿しても、thank youページ内で`name`フィールドの値が空になっています。実際、`$this->form->getValues()`で返される配列に値は設定されていません。`allow_extra_fields`オプションを無効にすることで、バリデータが存在しないエラーは発生しなくなりますが、`filter_extra_fields`オプションは、デフォルトで`true`に設定されており、バリデータが存在しない値をフィルタリングして、バリデート済みの値から削除します。リスト2-10で示すように、もちろんこのふるまいを変更することもできです。 428 428 429 429 リスト2-10 - `filter_extra_fields`保護を無効にする … … 460 460 * `sfValidatorOr` : フィールドが少なくとも1つのバリデータのバリデーションをパスすると有効になります 461 461 462 論理バリデータのコンストラクタは、最初の引数としてバリデータのリストを受け取ります。リスト2-11では、同時に満たす必要がある2つのバリデータを`name`フィールドに関連 付けるために、`sfValidatorAnd`を使います。462 論理バリデータのコンストラクタは、最初の引数としてバリデータのリストを受け取ります。リスト2-11では、同時に満たす必要がある2つのバリデータを`name`フィールドに関連づけるために、`sfValidatorAnd`を使います。 463 463 464 464 リスト2-11 - `sfValidatorAnd`バリデータを使う … … 510 510 -------------------- 511 511 512 これまで説明したそれぞれのバリデータは、特定のフィールド と結びつけられ一度に1つの値のバリデーションのみを行います。デフォルトでは、フィールドのバリデーションはユーザーによって投稿された別のフィールドのデータに関係しませんが、コンテキストに依存したり、多くの別のフィールドの値に依存してバリデーションを行う場合もあります。例えば、2つのパスワードが同じでなければならないときや、開始日が終了日より前の日付でなければならないときに、グローバルバリデータが必要となります。513 514 これら両方の場合において、それぞれのコンテキストでユーザー入力をバリデートするためにグローバルバリデータを使わなければなりません。プレバリデータもしくはポストバリデータをそれぞれ使うことで、個別のフィールドバリデーションの前または後にグローバルバリデータが処理されるように設定できます。通常はポストバリデータを使う方がベターです。データは 既にバリデートおよびクリーンアップされている、つまり標準化されたフォーマットになっているからです。リスト2-13では、`sfValidatorSchemaCompare`バリデータを利用して2つのパスワードの比較を実装する方法を示しています。512 これまで説明したそれぞれのバリデータは、特定のフィールドに結びつけられ一度に1つの値のバリデーションのみを行います。デフォルトでは、フィールドのバリデーションはユーザーによって投稿された別のフィールドのデータに関係しませんが、コンテキストに依存したり、多くの別のフィールドの値に依存してバリデーションを行う場合もあります。たとえば、2つのパスワードが同じでなければならないときや、開始日が終了日より前の日付でなければならないときに、グローバルバリデータが必要となります。 513 514 これら両方の場合において、それぞれのコンテキストでユーザー入力をバリデートするためにグローバルバリデータを使わなければなりません。プレバリデータもしくはポストバリデータをそれぞれ使うことで、個別のフィールドバリデーションの前または後にグローバルバリデータが処理されるように設定できます。通常はポストバリデータを使う方がベターです。データはすでにバリデートおよびクリーンアップされている、つまり標準化されたフォーマットになっているからです。リスト2-13では、`sfValidatorSchemaCompare`バリデータを利用して2つのパスワードの比較を実装する方法を示しています。 515 515 516 516 リスト2-13 - `sfValidatorSchemaCompare`バリデータを使う … … 542 542 ポストバリデータを利用することで、2つの日付の比較が正確になることが保証されます。入力に使われる日付フォーマットに関わらず、`start_date`と`end_date`フィールドのバリデーションでは、比較できるフォーマット(デフォルトでは`Y-m-d H:i:s`)に常に変換されます。 543 543 544 デフォルトでは、プレバリデータとポストバリデータは、フォームに対してグローバルエラーを返します。とは言うものの、エラーを特定のフィールドに関連づけたい場合もあります。 例えば、`sfValidatorSchemaCompare`バリデータの`throw_global_error`オプションを使うと、グローバルエラー(図2-10)にするか、またはエラーを最初のフィールドに関連付ける(図2-11)かを選択できます。リスト2-15では、`throw_global_error`オプションの使い方を示しています。544 デフォルトでは、プレバリデータとポストバリデータは、フォームに対してグローバルエラーを返します。とは言うものの、エラーを特定のフィールドに関連づけたい場合もあります。たとえば、`sfValidatorSchemaCompare`バリデータの`throw_global_error`オプションを使うと、グローバルエラー(図2-10)にするか、またはエラーを最初のフィールドに関連づける(図2-11)かを選択できます。リスト2-15では、`throw_global_error`オプションの使い方を示しています。 545 545 546 546 リスト2-15 - `throw_global_error`オプションを使う doc/branches/1.2/forms/ja/03-Forms-for-web-Designers.txt
r20619 r21360 4 4 1章と2章でウィジェットとバリデーションのルールを作る方法を見ました。これらを表示するために`<?php echo $form ?>`ステートメントを使いました。このステートメントのおかげで開発者は最終的にどのように表示されるのか考えなくてもアプリケーションのコードを書けます。フィールド(名前、ウィジェット...)を変更もしくは追加するたびにテンプレートを変更する必要はありません。開発者がモデルとビジネスロジックに重点的に取り組まなければならないとき、このステートメントは試作と初期の開発フェーズに適しています。 5 5 6 一旦オブジェクトモデルが安定してスタイルのガイドラインの準備ができれば、Webデザイナーは様々なアプリケーションのフォームに戻り整えることができます。6 いったんオブジェクトモデルが安定してスタイルのガイドラインの準備ができれば、Webデザイナーはさまざまなアプリケーションのフォームに戻り整えることができます。 7 7 8 8 この章を始める前に、symfonyのテンプレートシステムとビューレイヤーに精通しなければならなりません。そのためには、"The Definitive Guide to symfony"の[ビューレイヤーの内側](http://www.symfony-project.org/book/1_2/07-Inside-the-View-Layer)の章をご覧ください。 … … 151 151 152 152 >**TIP** 153 >すべてのフィールドは`id`生成属性を持ち、これによって開発者がCSSもしくはjavaScriptの 振る舞いを簡単に追加できます。153 >すべてのフィールドは`id`生成属性を持ち、これによって開発者がCSSもしくはjavaScriptのふるまいを簡単に追加できます。 154 154 155 155 プロトタイプのテンプレートのカスタマイズ … … 201 201 >オブジェクトを配列のように振る舞わせるには? 202 202 > 203 >PHP5以降では、オブジェクトはPHPの配列以外の 振る舞いを行うことができます。`sfForm`クラスはシンプルで短い構文を利用してそれぞれのフィールドに対してアクセスする権限を与えるArrayAccessの振る舞いを実装します。配列のキーはフィールド名で戻り値は関連ウィジェットのオブジェクトです:203 >PHP5以降では、オブジェクトはPHPの配列以外のふるまいを行うことができます。`sfForm`クラスはシンプルで短い構文を利用してそれぞれのフィールドに対してアクセスする権限を与えるArrayAccessのふるまいを実装します。配列のキーはフィールド名で戻り値は関連ウィジェットのオブジェクトです: 204 204 > 205 205 > [php] … … 258 258 >プロトタイプで使われた構造のフォーマットを変更するには? 259 259 > 260 >デフォルトでは、symfonyはフォームを表示するためにHTMLの配列を使います。この 振る舞いは特定の*フォーマッター(formatter)*によって変更できます。これらは組み込みもしくはプロジェクトに適合させるために特別に開発されます。フォーマッターを作るには、5章で説明されているクラスを作る必要があります。260 >デフォルトでは、symfonyはフォームを表示するためにHTMLの配列を使います。このふるまいは特定の*フォーマッター(formatter)*によって変更できます。これらは組み込みもしくはプロジェクトに適合させるために特別に開発されます。フォーマッターを作るには、5章で説明されているクラスを作る必要があります。 261 261 262 262 この構造から自由になるために、図3-6で示されるように、それぞれのフィールドは要素を生成するメソッドを持ちます: 263 263 264 264 * `renderLabel()` : ラベル(フィールドに結びつけられた` <label>`タグ) 265 * `render()` : フィールドタグそのもの( 例えば`<input>`タグ)265 * `render()` : フィールドタグそのもの(たとえば`<input>`タグ) 266 266 * `renderError()` : エラーメッセージ(`<ul class="error_list">`リストとして) 267 267 … … 280 280  281 281 282 これを行うにはフィールドのそれぞれの要素を個別に生成できるようにしなければなりません。フィールドにアクセスするために、`form`オブジェクトを連想配列として使用し、フィールド名をキーとして使用できることを 既に見ました。例えば、`email`フィールドは`$form['email']`でアクセスできます。リスト3-6は2つの列を持つフォームを実装する方法を示しています。282 これを行うにはフィールドのそれぞれの要素を個別に生成できるようにしなければなりません。フィールドにアクセスするために、`form`オブジェクトを連想配列として使用し、フィールド名をキーとして使用できることをすでに見ました。たとえば、`email`フィールドは`$form['email']`でアクセスできます。リスト3-6は2つの列を持つフォームを実装する方法を示しています。 283 283 284 284 リスト3-6 - 2つのカラムで表示をカスタマイズする … … 391 391 ラベルの名前を引数として送信する場合`renderLabel()`メソッドには何の意味があるのでしょうか? 392 392 なぜシンプルなHTMLの`label`タグを使わないのでしょうか? 393 これは`renderLabel()`メソッドは`label`タグを生成しリンク 付きフィールド(`id`)の識別子に393 これは`renderLabel()`メソッドは`label`タグを生成しリンクつきフィールド(`id`)の識別子に 394 394 セットされる`for` 属性を自動的に追加するからです。このことは 395 395 フィールドがアクセス可能であることを保証します; ラベルをクリックするとき、フィールドは自動的に … … 518 518 * hiddenフィールからのエラーもしくは実際にはフォームに表示されないフィールド。これらはグローバルエラーにまとめられる。 519 519 520 フィールドに関連するエラーメッセージの実装方法を 既に調べたので、リスト3-15はグローバルエラーメッセージの実装方法を示します。520 フィールドに関連するエラーメッセージの実装方法をすでに調べたので、リスト3-15はグローバルエラーメッセージの実装方法を示します。 521 521 522 522 リスト3-15 - グローバルエラーメッセージを実装する doc/branches/1.2/forms/ja/04-Propel-Integration.txt
r20601 r21360 2 2 ====================== 3 3 4 Webプロジェクトにおいて、 大抵のフォームはモデルオブジェクトを作るもしくは修正するために使われます。ORMのおかげでこれらのオブジェクトは通常はデータベースでシリアライズされます。symfonyのフォームシステムはsymfonyに組み込まれているPropelと連動する追加レイヤーを提供し、これらのモデルオブジェクトに基づいたフォームの実装をより簡単にします。4 Webプロジェクトにおいて、たいていのフォームはモデルオブジェクトを作るもしくは修正するために使われます。ORMのおかげでこれらのオブジェクトは通常はデータベースでシリアライズされます。symfonyのフォームシステムはsymfonyに組み込まれているPropelと連動する追加レイヤーを提供し、これらのモデルオブジェクトに基づいたフォームの実装をより簡単にします。 5 5 6 6 この章ではフォームをPropelのオブジェクトモデルと統合する方法を詳しく検討します。Propelとsymfonyとの統合機能に習熟していることが大いに推奨されます。そうではない場合、"The Definitive Guide to symfony"の[モデルレイヤーの内側](http://www.symfony-project.org/book/1_2/08-Inside-the-Model-Layer)の章を参照してください。 … … 84 84 BaseTagForm.class.php 85 85 86 `propel:build-forms`タスクはスキーマのそれぞれのテーブルに対して2つのクラスを生成し、1つの基底クラスは`lib/form/base`ディレクトリに、もう一つのクラスは`lib/form/`ディレクトリに存在します。 例えば`author`テーブルは、`lib/form/base/BaseAuthorForm.class.php`と`lib/form/AuthorForm.class.php`ファイルに生成された`BaseAuthorForm`と`AuthorForm`クラスで構成されます。86 `propel:build-forms`タスクはスキーマのそれぞれのテーブルに対して2つのクラスを生成し、1つの基底クラスは`lib/form/base`ディレクトリに、もう一つのクラスは`lib/form/`ディレクトリに存在します。たとえば`author`テーブルは、`lib/form/base/BaseAuthorForm.class.php`と`lib/form/AuthorForm.class.php`ファイルに生成された`BaseAuthorForm`と`AuthorForm`クラスで構成されます。 87 87 88 88 >**SIDEBAR** … … 158 158 } 159 159 160 生成クラスは以前の章で 既に作成したフォームと非常に似ていますが、下記の内容が異なります:160 生成クラスは以前の章ですでに作成したフォームと非常に似ていますが、下記の内容が異なります: 161 161 162 162 * 基底クラスは`sfForm`の代わりに`BaseFormPropel`です … … 167 167 >Propelフォームのグローバルなカスタマイズ 168 168 > 169 >それぞれのテーブル用の生成クラスに加えて、`propel:build-forms`は`BaseFormPropel`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリに生成された他のすべてのクラスの基底クラスでこれによってすべてのPropelフォームのビヘイビアをグローバルに設定できます。 例えば、すべてのPropelフォームに対してデフォルトのフォーマッターを変更することは簡単にできます:169 >それぞれのテーブル用の生成クラスに加えて、`propel:build-forms`は`BaseFormPropel`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリに生成された他のすべてのクラスの基底クラスでこれによってすべてのPropelフォームのビヘイビアをグローバルに設定できます。たとえば、すべてのPropelフォームに対してデフォルトのフォーマッターを変更することは簡単にできます: 170 170 > 171 171 > [php] … … 306 306 } 307 307 308 タスクは2つのテンプレート、`indexSuccess`と`editSuccess`も生成しました。`editSuccess`テンプレートは`<?php echo $form ?>`ステートメントを使わずに生成されました。`--non-verbose-templates`を利用して、この 振る舞いを修正できます:308 タスクは2つのテンプレート、`indexSuccess`と`editSuccess`も生成しました。`editSuccess`テンプレートは`<?php echo $form ?>`ステートメントを使わずに生成されました。`--non-verbose-templates`を利用して、このふるまいを修正できます: 309 309 310 310 $ ./symfony propel:generate-crud frontend author Author --non-verbose-templates … … 390 390 `propel:build-forms`と`propel:generate-crud`タスクによってモデルオブジェクトを表示する、作成する、編集し、削除する機能を持つsymfonyモジュールを作ることができます。これらのモジュールはモデルのバリデーションルールだけでなくテーブル間のリレーションも考慮します。一行も書かずにこれらすべてが行われます! 391 391 392 生成コードをカスタマイズする段階に来ました。フォームクラスが 既に多くの要素を考慮しているのであれば、いくつかの面をカスタマイズする必要があります。392 生成コードをカスタマイズする段階に来ました。フォームクラスがすでに多くの要素を考慮しているのであれば、いくつかの面をカスタマイズする必要があります。 393 393 394 394 ### バリデータとウィジェットを設定する … … 396 396 デフォルトで生成されたバリデータとウィジェットを設定することから始めましょう。 397 397 398 `ArticleForm`フォームは`slug`フィールドを持ちます。スラッグは記事をURLで一意的に表現する文字の文字列です。 例えば、タイトルが"Optimize the developments with symfony"である記事のスラッグは`12-optimize-the-developments-with-symfony`で、`12`は記事の`id`です。このフィールドは`title`に依存しており、オブジェクトが保存されたときに自動的に算出されますが、ユーザーによって明示的に上書きされる可能性があります。このフィールドがスキーマに必要な場合でも、フォームに必須にはなることはありません。リスト4-8のように、バリデータを修正してオプションにしている理由はそういうわけです。`content`フィールドもサイズを増やして少なくともユーザーが五文字を入力するようにカスタマイズします。398 `ArticleForm`フォームは`slug`フィールドを持ちます。スラッグは記事をURLで一意的に表現する文字の文字列です。たとえば、タイトルが"Optimize the developments with symfony"である記事のスラッグは`12-optimize-the-developments-with-symfony`で、`12`は記事の`id`です。このフィールドは`title`に依存しており、オブジェクトが保存されたときに自動的に算出されますが、ユーザーによって明示的に上書きされる可能性があります。このフィールドがスキーマに必要な場合でも、フォームに必須にはなることはありません。リスト4-8のように、バリデータを修正してオプションにしている理由はそういうわけです。`content`フィールドもサイズを増やして少なくともユーザーが五文字を入力するようにカスタマイズします。 399 399 400 400 リスト4-8 - バリデータとウィジェットをカスタマイズする … … 419 419 >オブジェクトをPHP配列として利用できるようにするために、`sfValidatorSchema`と`sfWidgetFormSchema`クラスはPHP5以降で利用できる`ArrayAccess`インターフェイスを実装します。 420 420 421 2つの記事が同じ`slug`を持たないことを確認するために、ユニーク制約がスキーマの定義に追加されました。`sfValidatorPropelUnique`バリデータを利用することでデータベースレベルでのこの制約は`ArticleForm`フォームに反映されました。このバリデータは任意のフォームフィールドの独自性をチェックできます。 例えば、ログインのEメールアドレスの一意性のチェックなどに役立ちます。リスト4-9は`ArticleForm`フォームでこれを使う方法を示しています。421 2つの記事が同じ`slug`を持たないことを確認するために、ユニーク制約がスキーマの定義に追加されました。`sfValidatorPropelUnique`バリデータを利用することでデータベースレベルでのこの制約は`ArticleForm`フォームに反映されました。このバリデータは任意のフォームフィールドの独自性をチェックできます。たとえば、ログインのEメールアドレスの一意性のチェックなどに役立ちます。リスト4-9は`ArticleForm`フォームでこれを使う方法を示しています。 422 422 423 423 リスト4-9 - フィールドの唯一性をチェックするために `sfValidatorPropelUnique`バリデータを使う … … 677 677 } 678 678 679 `propel:build-forms`を利用することでフォームにオブジェクトモデルをイントロスペクトさせる 大抵の要素を自動的に生成できます。この自動処理はいくつかの理由から役立ちます:679 `propel:build-forms`を利用することでフォームにオブジェクトモデルをイントロスペクトさせるたいていの要素を自動的に生成できます。この自動処理はいくつかの理由から役立ちます: 680 680 681 681 * 退屈で反復される作業をしなくて済むので、開発者の生活が楽になります。プロジェクト固有のビジネスルールに従ってバリデータとウィジェットのカスタマイズに焦点を当てることができます。 … … 692 692 ### デフォルトの値 693 693 694 **Propelフォームのインスタンスは常Propelのオブジェクトに接続します**。リンクされたPropelオブジェクトは常に`getModelName()`メソッドによって返されたクラスに所属します。 例えば、`AuthorForm`フォームは`Author`クラスに所属するオブジェクトのみにリンクできます。このオブジェクトは空のオブジェクト(`Author`クラスの空インスタンス)、もしくは最初の引数としてコンストラクタに送り出されるオブジェクトです。"平均的な"フォームのコンストラクタが値の配列を最初の引数として受け取る一方で、PropelフォームのコンストラクタはPropelオブジェクトを受け取ります。このオブジェクトはそれぞれのフィールドのデフォルト値を定義するために使われます。`getObject()`メソッドは現在のインスタンスに関連するオブジェクトを返し`isNew()`メソッドによってコンストラクタ経由でオブジェクトが送り出されたかどうかを知ることができます:694 **Propelフォームのインスタンスは常Propelのオブジェクトに接続します**。リンクされたPropelオブジェクトは常に`getModelName()`メソッドによって返されたクラスに所属します。たとえば、`AuthorForm`フォームは`Author`クラスに所属するオブジェクトのみにリンクできます。このオブジェクトは空のオブジェクト(`Author`クラスの空インスタンス)、もしくは最初の引数としてコンストラクタに送り出されるオブジェクトです。"平均的な"フォームのコンストラクタが値の配列を最初の引数として受け取る一方で、PropelフォームのコンストラクタはPropelオブジェクトを受け取ります。このオブジェクトはそれぞれのフィールドのデフォルト値を定義するために使われます。`getObject()`メソッドは現在のインスタンスに関連するオブジェクトを返し`isNew()`メソッドによってコンストラクタ経由でオブジェクトが送り出されたかどうかを知ることができます: 695 695 696 696 [php] … … 746 746 $this->form = new AuthorForm($author); 747 747 748 * 関連テーブル(`author`)から名 付けられたPHP配列の入力データを読み取れるようにウィジェットの`name`属性フォーマットは自動的にカスタマイズされます:748 * 関連テーブル(`author`)から名づけられたPHP配列の入力データを読み取れるようにウィジェットの`name`属性フォーマットは自動的にカスタマイズされます: 749 749 750 750 [php] … … 782 782 ### save()メソッド 783 783 784 Propelフォームが有効なとき、`save()`メソッドは関連オブジェクトを更新してデータベースに保存します。実際にはこのメソッドはメインオブジェクトだけでなく潜在的に関連するオブジェクトも保存します。 例えば、`ArticleForm`フォームは記事に結びつけられたタグを更新します。`article`テーブルと`tag`テーブル間の多対多のリレーションでは、記事に関連するタグは(生成された`saveArticleTagList()`メソッドを利用して)`article_tag`テーブルに保存されます。一貫したシリアライズを保証するために、`save()`メソッドは1つのトランザクション内ですべての更新を含みます。784 Propelフォームが有効なとき、`save()`メソッドは関連オブジェクトを更新してデータベースに保存します。実際にはこのメソッドはメインオブジェクトだけでなく潜在的に関連するオブジェクトも保存します。たとえば、`ArticleForm`フォームは記事に結びつけられたタグを更新します。`article`テーブルと`tag`テーブル間の多対多のリレーションでは、記事に関連するタグは(生成された`saveArticleTagList()`メソッドを利用して)`article_tag`テーブルに保存されます。一貫したシリアライズを保証するために、`save()`メソッドは1つのトランザクション内ですべての更新を含みます。 785 785 786 786 >**Note** doc/branches/1.2/forms/ja/08-Internationalisation-and-Localisation.txt
r20601 r21360 2 2 ============================ 3 3 4 人気のあるWebアプリケーションの多くは 様々な言語で利用可能で、時にユーザーのcultureに基づいてカスタマイズされます。symfonyはこれらの機能の管理を楽にする組み込みのフレームワークを搭載しています(symfony bookの["国際化と ローカライズ"](http://www.symfony-project.org/book/1_2/13-I18n-and-L10n)の章を参照)。4 人気のあるWebアプリケーションの多くはさまざまな言語で利用可能で、時にユーザーのcultureに基づいてカスタマイズされます。symfonyはこれらの機能の管理を楽にする組み込みのフレームワークを搭載しています(symfony bookの["国際化と ローカライズ"](http://www.symfony-project.org/book/1_2/13-I18n-and-L10n)の章を参照)。 5 5 6 6 フォームフレームワークはユーザーのインターフェイス用の組み込みサポートを備えており国際化オブジェクトの管理を楽にする方法を提供します。 … … 59 59 ### 翻訳のために使うカタログを指定する 60 60 61 symfonyの国際化フレームワークの機能を利用する場合 (`http://www.symfony-project.org/book/1_2/13-I18n-and-L10n#chapter_13_sub_managing_dictionaries`)、フォームを特定のカタログにバインドできます。リスト8-3において、`ContactForm`フォームを`contact_form`カタログに 関連付けします。ですので、フォーム要素の翻訳は`contact_form.fr.xml`ファイルで捜索されます。61 symfonyの国際化フレームワークの機能を利用する場合 (`http://www.symfony-project.org/book/1_2/13-I18n-and-L10n#chapter_13_sub_managing_dictionaries`)、フォームを特定のカタログにバインドできます。リスト8-3において、`ContactForm`フォームを`contact_form`カタログに連づけします。ですので、フォーム要素の翻訳は`contact_form.fr.xml`ファイルで捜索されます。 62 62 63 63 リスト8-3 - 翻訳カタログのカスタマイズ … … 75 75 76 76 >**Note** 77 >カタログを利用することで 例えばフォームごとに1つのファイルを使用する翻訳の編成がよりベターになります。77 >カタログを利用することでたとえばフォームごとに1つのファイルを使用する翻訳の編成がよりベターになります。 78 78 79 79 ### エラーメッセージの国際化 80 80 81 時々、エラーメッセージにはユーザーによって投稿された値が埋め込まれます( 例えば、"Eメールアドレスのuser@domainは有効ではありません。")。これをフォームクラスの中でカスタマイズされたエラーメッセージを定義してユーザーが投稿した値を簡単に利用できることを2章で既に見ました。これらの参照は`%parameter_name%`のパターンに従います。81 時々、エラーメッセージにはユーザーによって投稿された値が埋め込まれます(たとえば、"Eメールアドレスのuser@domainは有効ではありません。")。これをフォームクラスの中でカスタマイズされたエラーメッセージを定義してユーザーが投稿した値を簡単に利用できることを2章ですでに見ました。これらの参照は`%parameter_name%`のパターンに従います。 82 82 83 83 リスト8-4はこの原則をコンタクトフォームの`name`フィールドに適用する方法を示しています。 … … 131 131 >PHPのcallableは関数もしくはメソッドのインスタンスへの参照です。これは`is_callable()`関数に渡されるときに`true`を返すPHP変数でもあります。 132 132 133 リスト8-6で示されるクラスによって提供される独自の国際化メカニズムを 既に持つプロジェクトをマイグレートしなければならない場合を考えてみましょう。133 リスト8-6で示されるクラスによって提供される独自の国際化メカニズムをすでに持つプロジェクトをマイグレートしなければならない場合を考えてみましょう。 134 134 135 135 リスト8-6 - カスタムの国際化クラス doc/branches/1.2/forms/ja/11-Doctrine-Integration.txt
r20619 r21360 2 2 ========================= 3 3 4 Webプロジェクトにおいて、 大抵のフォームはモデルオブジェクトを作成もしくは修正するために使われます。4 Webプロジェクトにおいて、たいていのフォームはモデルオブジェクトを作成もしくは修正するために使われます。 5 5 これらのオブジェクトはORMのおかげで通常はシリアライズされデータベースに保存されます。 6 6 symfonyのフォームシステムはsymfonynの組み込みのORMであるDoctrineとやりとりするための追加レイヤーを提供します。 … … 103 103 BaseTagForm.class.php 104 104 105 `doctrine:build-forms`タスクはスキーマのそれぞれのテーブル用の2つのクラスを生成し、1つの基底クラスは`lib/form/base`ディレクトリに、もう1つの基底クラスは`lib/form/`ディレクトリです。 例えば、`author`テーブルは`BaseAuthorForm`と`AuthorForm`クラスで構成され、これらのクラスは`lib/form/base/BaseAuthorForm.class.php`と`lib/form/AuthorForm.class.php`ファイルに生成されました。105 `doctrine:build-forms`タスクはスキーマのそれぞれのテーブル用の2つのクラスを生成し、1つの基底クラスは`lib/form/base`ディレクトリに、もう1つの基底クラスは`lib/form/`ディレクトリです。たとえば、`author`テーブルは`BaseAuthorForm`と`AuthorForm`クラスで構成され、これらのクラスは`lib/form/base/BaseAuthorForm.class.php`と`lib/form/AuthorForm.class.php`ファイルに生成されました。 106 106 107 107 下記のテーブルは`AuthorForm`フォームの定義に関連する異なったクラス間の階層をまとめています。 … … 163 163 } 164 164 165 生成クラスはわずかな違いを除いて、以前の章で 既に作成されたフォームによく似ています:165 生成クラスはわずかな違いを除いて、以前の章ですでに作成されたフォームによく似ています: 166 166 167 167 * 基底クラスは`sfForm`の代わりに`BaseFormDoctrine` … … 172 172 >Doctrineフォームのグローバルなカスタマイズ 173 173 > 174 >それぞれのテーブル用に生成されたクラスに加えて、`doctrine:build-forms`は`BaseFormDoctrine`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリの中の他のすべての生成クラスの基底クラスであり、Doctrineのすべてのフォームの 振る舞いをグローバルに設定することを可能にします。例えば、すべてのDoctrineフォーム用のデフォルトのフォーマッターを簡単に変更できます:174 >それぞれのテーブル用に生成されたクラスに加えて、`doctrine:build-forms`は`BaseFormDoctrine`クラスも生成します。この空のクラスは`lib/form/base/`ディレクトリの中の他のすべての生成クラスの基底クラスであり、Doctrineのすべてのフォームのふるまいをグローバルに設定することを可能にします。たとえば、すべてのDoctrineフォーム用のデフォルトのフォーマッターを簡単に変更できます: 175 175 > 176 176 > [php] … … 293 293 } 294 294 295 このモジュールにおいて、フォームのライフサイクルは3つのメソッド: `create`、`edit`と、`update`メソッドによって対処されます。`--non-atomic-actions`オプションを 付けることで、`doctrine:generate-crud`タスクに以前の3つのメソッドの機能のみをカバーする1つのメソッドだけを生成するように頼むこともできます:295 このモジュールにおいて、フォームのライフサイクルは3つのメソッド: `create`、`edit`と、`update`メソッドによって対処されます。`--non-atomic-actions`オプションをつけることで、`doctrine:generate-crud`タスクに以前の3つのメソッドの機能のみをカバーする1つのメソッドだけを生成するように頼むこともできます: 296 296 297 297 $ ./symfony doctrine:generate-crud frontend author Author --non-atomic-actions … … 335 335 } 336 336 337 タスクは`indexSuccess`と`editSuccess`の2つのテンプレートも生成しました。`<?php echo $form ?>`ステートメントを使わずに`editSuccess`テンプレートが生成されました。`--non-verbose-templates`を使用して、この 振る舞いを修正できます:337 タスクは`indexSuccess`と`editSuccess`の2つのテンプレートも生成しました。`<?php echo $form ?>`ステートメントを使わずに`editSuccess`テンプレートが生成されました。`--non-verbose-templates`を使用して、このふるまいを修正できます: 338 338 339 339 $ ./symfony doctrine:generate-crud frontend author Author --non-verbose-templates … … 424 424 `doctrine:build-forms`と`doctrine:generate-crud`タスクによってモデルオブジェクトの一覧を表示、作成、編集する機能を持つモジュールを作ることができます。これらのモジュールはモデルのバリデーションルールだけでなくテーブル間のリレーションも考慮されます。これらすべては一行のコードを書かずに行われます! 425 425 426 生成コードをカスタマイズしましょう。フォームクラスが 既に多くの要素を考慮しているのであれば、いくつかの面でカスタマイズする必要があります。426 生成コードをカスタマイズしましょう。フォームクラスがすでに多くの要素を考慮しているのであれば、いくつかの面でカスタマイズする必要があります。 427 427 428 428 ### バリデータとウィジェットを設定する … … 430 430 デフォルトで生成されたバリデータとウィジェットを設定することを始めましょう。 431 431 432 `ArticleForm`フォームは`slug`フィールドを持ちます。スラッグはURLの中で記事を一意的に表す文字列です。 例えば、タイトルが"Optimize the developments with symfony"である記事のslugは`12-optimize-the-developments-with-symfony`で、`12`は記事の`id`です。オブジェクトが保存されたときこのフィールドは`title`に従って自動的に算出されますが、これは明らかにユーザーによって上書きされる可能性があります。このフィールドがスキーマに必要であるとしても、フォームに必須なものになることはありません。リスト4-8で示されるように、これがバリデータを修正してオプションを追加する理由です。`content`フィールドのサイズを増やしてユーザーが少なくとも5文字を入力するようにもカスタマイズします。432 `ArticleForm`フォームは`slug`フィールドを持ちます。スラッグはURLの中で記事を一意的に表す文字列です。たとえば、タイトルが"Optimize the developments with symfony"である記事のslugは`12-optimize-the-developments-with-symfony`で、`12`は記事の`id`です。オブジェクトが保存されたときこのフィールドは`title`に従って自動的に算出されますが、これは明らかにユーザーによって上書きされる可能性があります。このフィールドがスキーマに必要であるとしても、フォームに必須なものになることはありません。リスト4-8で示されるように、これがバリデータを修正してオプションを追加する理由です。`content`フィールドのサイズを増やしてユーザーが少なくとも5文字を入力するようにもカスタマイズします。 433 433 434 434 リスト4-8 - バリデータとウィジェットをカスタマイズする … … 713 713 } 714 714 715 `doctrine:build-forms`を使うことでフォームはオブジェクトモデルをイントロスペクトして 大抵の要素を自動的に生成できます。この自動化はいくつかの理由から役に立ちます:715 `doctrine:build-forms`を使うことでフォームはオブジェクトモデルをイントロスペクトしてたいていの要素を自動的に生成できます。この自動化はいくつかの理由から役に立ちます: 716 716 717 717 * これによって繰り返される冗長な作業をしなくても済むので、開発者の人生が楽になります。開発者はプロジェクト固有のビジネスルールに従ってバリデータとウィジェットのカスタマイズに集中できます。 … … 728 728 ### デフォルトの値 729 729 730 **Doctrineフォームのインスタンスは常にDoctrineオブジェクトに接続されます**。リンクされたDoctrineオブジェクトは`getModelName()`メソッドによって返されたクラスに常に所属します。 例えば、`AuthorForm`フォームは`Author`クラスに所属するオブジェクトのみにリンクできます。このオブジェクトは空のオブジェクト(`Author`クラスの空のインスタンス)、もしくはコンストラクタに最初の引数として送り出されるオブジェクトのどちらかです。"平均的な"フォームのコンストラクタは値の配列を最初の引数として受け取るのに対して、DoctrineフォームのコンストラクタはDoctrineのオブジェクトを受け取ります。このオブジェクトはそれぞれのフィールドのデフォルトの値を定義するために使われます。`getObject()`メソッドは現在のインスタンスに関連するオブジェクトを返し`isNew()`メソッドによってオブジェクトがコンストラクタを通して送り出されたことを知ることができます:730 **Doctrineフォームのインスタンスは常にDoctrineオブジェクトに接続されます**。リンクされたDoctrineオブジェクトは`getModelName()`メソッドによって返されたクラスに常に所属します。たとえば、`AuthorForm`フォームは`Author`クラスに所属するオブジェクトのみにリンクできます。このオブジェクトは空のオブジェクト(`Author`クラスの空のインスタンス)、もしくはコンストラクタに最初の引数として送り出されるオブジェクトのどちらかです。"平均的な"フォームのコンストラクタは値の配列を最初の引数として受け取るのに対して、DoctrineフォームのコンストラクタはDoctrineのオブジェクトを受け取ります。このオブジェクトはそれぞれのフィールドのデフォルトの値を定義するために使われます。`getObject()`メソッドは現在のインスタンスに関連するオブジェクトを返し`isNew()`メソッドによってオブジェクトがコンストラクタを通して送り出されたことを知ることができます: 731 731 732 732 [php] … … 782 782 $this->form = new AuthorForm($author); 783 783 784 * 関連テーブル(`author`)から名 付けられたPHP配列形式で入力データを取得できるようにウィジェットの`name`属性のフォーマットは自動的にカスタマイズされます:784 * 関連テーブル(`author`)から名づけられたPHP配列形式で入力データを取得できるようにウィジェットの`name`属性のフォーマットは自動的にカスタマイズされます: 785 785 786 786 [php] … … 818 818 ### save()メソッド 819 819 820 Doctrineのフォームが有効なとき、`save()`メソッドは関連オブジェクトを更新してそれをデータベースに保存します。このメソッドはメインのオブジェクトだけでなく潜在的に関連するオブジェクトも実際に保存します。 例えば、`ArticleForm`フォームは記事に関連するタグを更新します。` article`テーブルと`tag`テーブルのリレーションは多対多なので、(生成された`saveArticleTagList()`メソッドを利用して)記事に関連するタグは`article_tag`テーブルに保存されます。820 Doctrineのフォームが有効なとき、`save()`メソッドは関連オブジェクトを更新してそれをデータベースに保存します。このメソッドはメインのオブジェクトだけでなく潜在的に関連するオブジェクトも実際に保存します。たとえば、`ArticleForm`フォームは記事に関連するタグを更新します。` article`テーブルと`tag`テーブルのリレーションは多対多なので、(生成された`saveArticleTagList()`メソッドを利用して)記事に関連するタグは`article_tag`テーブルに保存されます。 821 821 822 822 一貫したシリアライゼーションを保証するために、`save()`メソッドは1つのトランザクションの中のすべての更新を含みます。 … … 866 866 867 867 >**Caution** 868 >`doctrine:build-all`タスクはすべてのスキーマテーブルを再生成するためにこれらを削除することに気を 付けてください。テーブル内のデータはそれゆえ上書きされます。これがそれぞれのモデルを修正するたびに再びダウンロードできるテストデータ(`fixtures`)を作ることが重要である理由です。868 >`doctrine:build-all`タスクはすべてのスキーマテーブルを再生成するためにこれらを削除することに気をつけてください。テーブル内のデータはそれゆえ上書きされます。これがそれぞれのモデルを修正するたびに再びダウンロードできるテストデータ(`fixtures`)を作ることが重要である理由です。 869 869 870 870 リスト4-25はウィジェットとバリデータを`file`フィールドにリンクするために`ArticleForm`クラスを修正する方法を示しています。 doc/branches/1.2/forms/ja/A-Widgets.txt
r20638 r21360 6 6 7 7 symfonyフォームフレームワークはたくさんの便利なウィジェットを搭載してやってきます。 8 これらのウィジェットは 大抵のプロジェクトの共通のニーズをカバーします。8 これらのウィジェットはたいていのプロジェクトの共通のニーズをカバーします。 9 9 この章ではsymfonyに搭載されたデフォルトのフォームウィジェットを説明します。 10 10 `sfFormExtraPlugin`、`sfPropelPlugin`、と`sfDoctrinePlugin`プラグインからも … … 267 267 >**CAUTION** 268 268 >`edit`モードにおいて、このウィジェットは接尾辞が"_delete"である 269 >ファイルアップロードウィジェットから名 付けられた追加ウィジェットをレンダリングします。269 >ファイルアップロードウィジェットから名づけられた追加ウィジェットをレンダリングします。 270 270 >ですので、フォームを作る際には、この追加フィールド用のバリデータを追加することをお忘れなく。 271 271 … … 350 350 >~`sfWidgetFormSelectCheckbox`~、と~`sfWidgetFormSelectRadio`~ウィジェット 351 351 >は他のウィジェットと同じくプレーンなもので直接利用できます。 352 > 大抵の場合、このセクションではこれらのドキュメントは作成されていないので、352 >たいていの場合、このセクションではこれらのドキュメントは作成されていないので、 353 353 >より柔軟な`sfWidgetFormChoice`ウィジェットを使う方がベターです。 354 354 … … 667 667 # ); 668 668 669 ウィジェットの 振る舞いは多くのオプションでカスタマイズできます:669 ウィジェットのふるまいは多くのオプションでカスタマイズできます: 670 670 671 671 | オプション | 説明 … … 723 723 # ); 724 724 725 ウィジェットの 振る舞いは多くのオプションでカスタマイズできます:725 ウィジェットのふるまいは多くのオプションでカスタマイズできます: 726 726 727 727 | オプション | 説明 … … 982 982 HTTPリクエストからフォームをバインドするときこれらを手動で追加しなければなりません。 983 983 984 例えば、フォームが`contact[%s]`ネームフォーマットを持つ場合、984 たとえば、フォームが`contact[%s]`ネームフォーマットを持つ場合、 985 985 captcha情報が残りのフォームに投稿された値にマージされることを保証するために必要なコードは次の通りです: 986 986 … … 1031 1031 1032 1032 `sfWidgetFormSchema`ウィジェットはいくつかのフィールドで構成されるウィジェットを表します。 1033 フィールドは名前 付きのシンプルなウィジェットです:1033 フィールドは名前つきのシンプルなウィジェットです: 1034 1034 1035 1035 [php] … … 1064 1064 1065 1065 `sfWidgetFormSchema`クラスは`sfWidgetForm`クラスを継承するので、 1066 すべてのメソッドと 振る舞いを継承します。1066 すべてのメソッドとふるまいを継承します。 1067 1067 1068 1068 >**CAUTION** doc/branches/1.2/forms/ja/B-Validators.txt
r20619 r21360 6 6 7 7 symfonyフォームフレームワークはたくさんの便利なバリデータを搭載しています。 8 これらのバリデータは 大抵のプロジェクトの共通のニーズをカバーします。8 これらのバリデータはたいていのプロジェクトの共通のニーズをカバーします。 9 9 この章ではsymfonyに搭載されたデフォルトのフォームバリデータを説明します。 10 10 `sfPropelPlugin`、と`sfDoctrinePlugin`プラグインにもバリデータが含まれています。 … … 26 26 バリデータは2つの目標: 汚染された値をクリーンにすることとバリデートすることを持ちます。 27 27 28 バリデータを作るとき、オプション としてオプションとエラーメッセージを引数として渡すことができます:28 バリデータを作るとき、オプションの引数としてオプションとエラーメッセージを渡すことができます: 29 29 30 30 [php] … … 54 54 $cleaned = $v->clean('name', 'value', array('class' => 'foo')); 55 55 56 `clean()`メソッドは 汚染された値を引数として受け取りクリーンな値を返します。56 `clean()`メソッドは引数として汚染された値を受け取りクリーンな値を返します。 57 57 バリデーションエラーが起きるとき、`sfValidatorError`が投げられます。 58 58 … … 269 269 *スキーマバリデータ*: No 270 270 271 `sfValidatorCallback`バリデータは実際のバリデーション作業をPHP callbackに委譲します。271 `sfValidatorCallback`バリデータは実際のバリデーション作業をPHPコールバックに委譲します。 272 272 273 273 callbackは現在のバリデータインスタンスに、(`arguments`オプションから) … … 292 292 | オプション | エラー| 説明 293 293 | ----------- | ----- | ----------- 294 | `callback` | n/a | 有効なPHP callback(必須)295 | `arguments` | n/a | callbackに渡す引数の配列294 | `callback` | n/a | 有効なPHPコールバック(必須) 295 | `arguments` | n/a | コールバックに渡す引数の配列 296 296 297 297 日付バリデータ … … 302 302 *スキーマバリデータ*: No 303 303 304 `sfValidatorDate`は日付と 日付と時間の組をバリデートします304 `sfValidatorDate`は日付と時間の組をバリデートします 305 305 (日付と時間の組は`with_time`オプションを設定することでサポートされます)。 306 306 日付フォーマットをバリデートすることとは別に、 … … 416 416 | `validated_file_class` | n/a | クリーンにされたアップロードファイルを管理するクラスの名前(オプション) 417 417 418 `web_images` mime-typeカテゴリは次のmime-typeを含みます:418 `web_images`カテゴリは次のmime-typeを含みます: 419 419 420 420 * `image/jpeg` … … 429 429 * `guessFromFileinfo`: `finfo_open()`関数を使用する(PECLの`Fileinfo`エクステンションから) 430 430 * `guessFromMimeContentType`: `mime_content_type()`関すを使用する (非推奨) 431 * `guessFromFileBinary`: ファイルバイナリを使用する( *nixシステムでのみ動作する)431 * `guessFromFileBinary`: ファイルバイナリを使用する(Unix系システムでのみ動作する) 432 432 433 433 | エラー | プレースホルダー | デフォルト値 … … 487 487 少なくともリストからのバリデータから汚染された値が通過する場合、`sfValidatorOr`バリデータはその汚染された値をバリデートします。 488 488 489 `sfValidatorOr`コンストラクタは最初の引数としてバリデータのリストを 取ります:489 `sfValidatorOr`コンストラクタは最初の引数としてバリデータのリストを受け取ります: 490 490 491 491 [php]