コンテンツにスキップ
Nibiru docsv0.9.2

フォーム

Nibiruの静的ファクトリでフォームを流暢に構築します。

Stable Reading time ~ 2 min Edit on GitHub

Nibiruのフォームは、\Nibiru\Factory\Formクラスの静的メソッドを呼び出すことで流暢に構築されます。各呼び出しでは、HTMLフラグメントが内部の静的なバッファに追加されます。最後に、Form::addForm()メソッドはバッファを<form>要素で囲み、レンダリングされたHTML文字列を返します。

use Nibiru\Factory\Form;

これが唯一必要な use です。すべての入力タイプはこのクラスの静的メソッドです。

歴史的な命名により、3つのメソッドのバリエーションがあります。

addInputType* — 実際の <input> 要素用

Section titled “addInputType* — 実際の <input> 要素用”
addInputTypeText addInputTypePassword addInputTypeEmail
addInputTypeDate addInputTypeDatetime addInputTypeColor
addInputTypeRadio addInputTypeCheckbox addInputTypeSwitch
addInputTypeSubmit addInputTypeTextarea

addType* — 非 <input> フォーム要素用

Section titled “addType* — 非 <input> フォーム要素用”
addTypeFileUpload addTypeHidden addTypeImageSubmit
addTypeNumber addTypeRange addTypeReset
addTypeSearch addTypeTelefon addTypeUrl
addTypeButton addTypeLabel

addSelect / addSelectOption<select><option> のため

Section titled “addSelect / addSelectOption — <select> と <option> のため”
addSelect addSelectOption
addOpenDiv addCloseDiv addOpenAny addCloseAny
addOpenSpan addCloseSpan
create / reset the static buffer; call before building a new form
addForm / wrap the buffer in <form>...</form> and return as a string
use Nibiru\Factory\Form;
Form::create(); / reset the static buffer
Form::addOpenDiv(['class' => 'form-group']);
Form::addTypeLabel(['for' => 'login', 'value' => 'Username']);
Form::addInputTypeText([
'name' => 'login',
'id' => 'login',
'class' => 'form-control',
'required' => 'required',
'placeholder' => 'Type your name…',
]);
Form::addCloseDiv();
Form::addOpenDiv(['class' => 'form-group']);
Form::addTypeLabel(['for' => 'password', 'value' => 'Password']);
Form::addInputTypePassword([
'name' => 'password',
'id' => 'password',
'class' => 'form-control',
'required' => 'required',
]);
Form::addCloseDiv();
Form::addInputTypeSubmit(['value' => 'Sign in', 'class' => 'btn btn-primary']);
$html = Form::addForm([
'method' => 'POST',
'action' => '/login',
'name' => 'loginForm',
]);

$html をビューに渡します:

View::assign(['loginForm' => $html]);
``````smarty
<div class="card-body">
{$loginForm nofilter}
</div>

(nofilterForm::addForm() がすでにレンダリングされた HTML を返すためです — Smarty ではそれ以外をエスケープします。)

Form::addSelect(['name' => 'country', 'class' => 'form-control', 'id' => 'country']);
Form::addSelectOption(['value' => 'at', 'label' => 'Austria']);
Form::addSelectOption(['value' => 'lu', 'label' => 'Luxembourg']);
Form::addSelectOption(['value' => 'us', 'label' => 'United States']);

addSelect<select> を開き、オプション収集状態をキューに登録します。各 addSelectOption はそれに追加されます。ラップする </select> は次の非オプション呼び出しが発生したときに自動的に生成されます。

foreach (['standard', 'admin', 'editor'] as $r) {
Form::addInputTypeRadio([
'name' => 'role', 'value' => $r, 'id' => "role-$r",
]);
Form::addTypeLabel(['for' => "role-$r", 'value' => ucfirst($r)]);
}
Form::addTypeFileUpload([
'name' => 'avatar',
'accept' => 'image/png,image/jpeg',
]);

フォームで enctype を忘れないでください。

Form::addForm([
'method' => 'POST',
'action' => '/profile/upload',
'enctype' => 'multipart/form-data',
]);
Form::addTypeHidden([
'name' => 'csrf',
'value' => bin2hex(random_bytes(16)),
]);

(値を $_SESSION['csrf'] に保存し、POST 時に検証してください。)

addOpenDiv / addCloseDivaddOpenAny / addCloseAny を使用すると、同じフレuent ストリーム内で Bootstrap スタイルのレイアウトを作成できます。

Form::addOpenDiv(['class' => 'row']);
Form::addOpenDiv(['class' => 'col-md-6']);
Form::addInputTypeText(['name' => 'first']);
Form::addCloseDiv();
Form::addOpenDiv(['class' => 'col-md-6']);
Form::addInputTypeText(['name' => 'last']);
Form::addCloseDiv();
Form::addCloseDiv();

addOpenAny([…, 'tag' => 'fieldset']) は任意の他のタグを開きます;addCloseAny([…, 'tag' => 'fieldset']) はそれを閉じます。

フォームのレンダリングは文字列ベースです。DOMベースではありません。各タイプクラスはcore/c/type<X>.phpにあり、プレースホルダーを含むHTMLテンプレートが含まれています:

core/c/typetext.php
private function _setElement() {
$this->_element = '<input type="text" name="NAME" value="VALUE" '
. 'placeholder="PLACEHOLDER" maxlength="MAXLENGTH" ID CLASS '
. 'REQUIRED DATA>' . "\n";
}

ファクトリーは、あなたの $attributes 配列を FormAttributes::loadAttributeValues() に渡します。このメソッドは、各プレースホルダーを対応する値で置き換えます。空の値がある場合は、プレースホルダーが削除されるため、属性が空文字列でレンダリングされることはありません。

これがなぜ のみ知られたキーが機能するか'name', 'value', 'placeholder', 'class', 'id', 'required', 'data' が認識され、任意のキーは静かにドロップされるのか。

thorax.nibiru-framework.com 上の formsController は、コンストラクタで連絡先フォームを構築し、プロパティに割り当てます。

namespace Nibiru;
use Nibiru\Adapter\Controller;
use Nibiru\Factory\Form;
class formsController extends Controller {
private string $form;
public function __construct() {
parent::__construct();
Form::create();
Form::addTypeLabel(['value' => 'Full Name', 'for' => 'full-name']);
Form::addInputTypeText([
'name' => 'full-name',
'id' => 'full-name',
'required' => 'required',
'class' => 'contacts-input form-control',
]);
/ ...more fields...
$this->form = Form::addForm([
'name' => 'newregister',
'method' => 'post',
'action' => '/forms/submit',
]);
}
public function pageAction() {
View::assign(['form' => $this->form]);
}
}

これにより、コントローラーのアクションが小さくなります — フォームはテンプレートにレンダリングするための一行です。

  • Form::create() を忘れている。 バッファは静的です。create() がないと、最後にあったもの(長時間動作する PHP プロセス間を含む)に連結されます。
  • Smarty が HTML をエスケープしている。 レンダリングされた文字列を出力するときには nofilter (または |nofilter)を追加します。
  • カスタム属性が静かに無視される。 各タイプは固定のプレースホルダーキーを受け付けます。data-* 属性(展開されます)のために data キーを使用しますが、真に任意の属性はドロップされます。
  • 自動的な XSS エスケープがない。 フォーム層は文字列ベースです。ユーザー入力をデフォルトの value としてレンダリングする場合、ファクトリに渡す前に自分でエスケープしてください。
  • addInputType… vs addType… の混同。 不確実な場合は、core/c/type<X>.php ファイル名を見てください — タイプの HTML 要素が <input type="X"> であれば addInputType<X> を使用し、それ以外は addType<X> を使用します。addSelect は唯一の例外です(プレフィックスなしで addSelect)。

Nibiru はサーバーサイドバリデーションを搭載していません。一般的なパターン:

  • Respect/Validation による宣言的なチェック(既に多くのプロダクションNibiruアプリで使用されています)。
  • フォームタイプごとの validate() プラグインを含むモジュール。
  • HTML5の requiredpatternmin/max が第一線の防御です。