CakePHPは、規約に沿ってコードを書くことで効率を最大化できるフレームワーク。フォームヘルパーを使ってフォームを自動生成する機能は、その一例と言えるかと。この記事では、CakePHPのフォームヘルパーがどのように入力タイプを自動設定するのか、具体的なカラム名やコンテキストの役割を解説します。
フィールドタイプごとのチートシート
以下は、使用頻度が高いフィールドタイプごとに、どのようにコードを書けばそのタイプが生成されるかを示したチートシートです。それぞれのタイプについて、条件、生成方法、生成されるHTMLを示します。
自動設定されるケース
select
-
条件:カラム名が
_id
で終わる -
生成方法:
FormHelper::control('category_id')
-
生成されるHTML:
<select name="category_id">...</select>
_idサフィックスは他テーブルとの紐づけを示すためにも使われるので、混同を避けるために、selectカラムの自動設定には使わないという判断もあります。
textarea
-
条件:オプションに
'rows'
または'cols'
が含まれている -
生成方法:
FormHelper::control('description', ['rows' => '3'])
-
生成されるHTML:
<textarea name="description">...</textarea>
checkbox
-
条件:オプションに
'checked'
が含まれている -
生成方法:
FormHelper::control('is_active', ['checked' => true])
-
生成されるHTML:
<input type="checkbox" name="is_active" checked="checked" />
password
-
条件:カラム名が
passwd
、password
などを含む -
生成方法:
FormHelper::control('password')
-
生成されるHTML:
<input type="password" name="password" />
tel
-
条件:カラム名が
tel
、telephone
、phone
を含む -
生成方法:
FormHelper::control('phone')
-
生成されるHTML:
<input type="tel" name="phone" />
email
-
条件:カラム名が
email
を含む -
生成方法:
FormHelper::control('email')
-
生成されるHTML:
<input type="email" name="email" />
number
-
条件:カラムのタイプが
integer
、float
、decimal
-
生成方法:
FormHelper::control('price')
-
生成されるHTML:
<input type="number" name="price" />
text
- 条件:その他のカラム、または特に指定がない場合
-
生成方法:
FormHelper::control('username')
-
生成されるHTML:
<input type="text" name="username" />
明示的に設定するタイプ
datetime
-
条件:オプションに
'type' => 'datetime'
を指定 -
生成方法:
FormHelper::control('appointment', ['type' => 'datetime'])
-
生成されるHTML:
<input type="datetime-local" name="appointment" />
date
-
条件:オプションに
'type' => 'date'
を指定 -
生成方法:
FormHelper::control('birthdate', ['type' => 'date'])
-
生成されるHTML:
<input type="date" name="birthdate" />
time
-
条件:オプションに
'type' => 'time'
を指定 -
生成方法:
FormHelper::control('meeting_time', ['type' => 'time'])
-
生成されるHTML:
<input type="time" name="meeting_time' />
CakePHP 3.4と3.10(3系最終版)の違い
筆者が関わっているプロジェクトは3.4のため、違いについてまとめておきます。CakePHP 3.10には、CakePHP 3.4にない追加機能がいくつかあって、その中でも、特に重要な2つの違いについて説明します。ほとんどのユーザには不要な情報ですが・・
customValidityMessageの設定
CakePHP 3.10での変更点:
-
カスタム有効性メッセージ:CakePHP 3.10では、フォームフィールドが必須の場合、エラーメッセージを設定することができます。このエラーメッセージは、HTML5の
setCustomValidity
メソッドを使用してクライアントサイドで表示されます。 -
イベントハンドラの自動設定:
oninvalid
とoninput
イベントが自動的に設定され、入力が無効な場合にカスタムメッセージが表示され、入力が有効になった場合にメッセージがクリアされます。
CakePHP 3.4:
-
対応していません:CakePHP 3.4では、カスタム有効性メッセージや
oninvalid
、oninput
イベントの自動設定はサポートされていません。そのため、手動でこれらの機能を実装する必要があります。
具体例として、CakePHP 3.7でのコード例を以下に示します。
if (method_exists($context, 'getRequiredMessage')) {
$message = $context->getRequiredMessage($fieldName);
$message = h($message);
if ($options['required'] && $message) {
$options['templateVars']['customValidityMessage'] = $message;
if ($this->getConfig('autoSetCustomValidity')) {
$options['oninvalid'] = "this.setCustomValidity(''); if (!this.validity.valid) this.setCustomValidity('$message')";
$options['oninput'] = "this.setCustomValidity('')";
}
}
}
maxlengthの設定の拡張
CakePHP 3.10での変更点:
-
maxlengthの設定:CakePHP 3.10では、
maxlength
が自動的に設定されるようになりました。これは、コンテキストのgetMaxLength
メソッドを使用して、フィールドの最大長を取得し、その値がHTMLのmaxlength
属性として設定されます。
CakePHP 3.4:
-
対応していません:CakePHP 3.4では、
maxlength
は自動的に設定されません。手動で設定する必要があります。
具体例として、CakePHP 3.10でのコード例を以下に示します。
$typesWithMaxLength = ['text', 'textarea', 'email', 'tel', 'url', 'search'];
if (
!array_key_exists('maxlength', $options)
&& in_array($options['type'], $typesWithMaxLength)
) {
$maxLength = null;
if (method_exists($context, 'getMaxLength')) {
$maxLength = $context->getMaxLength($fieldName);
}
if ($maxLength === null && !empty($fieldDef['length'])) {
$maxLength = $fieldDef['length'];
}
if ($maxLength !== null) {
$options['maxlength'] = min($maxLength, 100000);
}
}
フォームヘルパーの自動入力タイプ設定の仕組み
フォームヘルパーの_inputType
メソッドは、以下の手順で入力タイプを自動設定します。
-
カラム名のチェック:
- カラム名が
*_id
で終わる場合、select
タイプを返します。 - カラム名が
password
やtel
、email
など特定の名前の場合、それに対応するタイプを返します。
- カラム名が
-
内部型の取得:
- コンテキストを通じてフィールドの内部型を取得します。これにより、データベースの型情報に基づいて適切な入力タイプを決定します。
-
オプションのチェック:
-
checked
やoptions
オプションが設定されている場合、それに応じたタイプを返します。
-
-
デフォルトの型マッピング:
- 型マッピングに基づいて、デフォルトの入力タイプを決定します。例えば、
string
型はtext
、boolean
型はcheckbox
となります。
- 型マッピングに基づいて、デフォルトの入力タイプを決定します。例えば、
コンテキストの役割
フォームヘルパーは、コンテキストを使用してフォームフィールドの情報を取得します。コンテキストは、フォームに関連するデータやメタデータを提供し、フォーム生成をサポートします。以下のようなコンテキストが存在します。
-
EntityContext
:データベースのエンティティやそのコレクションに基づくコンテキスト。 -
ArrayContext
:配列データに基づくコンテキスト。 -
FormContext
:カスタムフォームオブジェクトに基づくコンテキスト。 -
NullContext
:特に情報がない場合に使用されるデフォルトのコンテキスト。
コード例
以下に、実際のコード例を示します。これにより、フォームヘルパーがどのようにコンテキストを使用して入力タイプを決定するのかがわかります。
protected function _inputType($fieldName, $options)
{
$context = $this->_getContext();
if ($context->isPrimaryKey($fieldName)) {
return 'hidden';
}
if (substr($fieldName, -3) === '_id') {
return 'select';
}
$internalType = $context->type($fieldName);
$map = $this->_config['typeMap'];
$type = isset($map[$internalType]) ? $map[$internalType] : 'text';
$fieldName = array_slice(explode('.', $fieldName), -1)[0];
switch (true) {
case isset($options['checked']):
return 'checkbox';
case isset($options['options']):
return 'select';
case in_array($fieldName, ['passwd', 'password']):
return 'password';
case in_array($fieldName, ['tel', 'telephone', 'phone']):
return 'tel';
case $fieldName === 'email':
return 'email';
case isset($options['rows']) || isset($options['cols']):
return 'textarea';
}
return $type;
}
どこで確認できる?
-
ソースコードの場所:フォームヘルパーの自動入力タイプ設定は、CakePHP本体
FormHelper
クラスの_inputType
メソッドで行われます。このメソッドは、/cakephp/src/View/Helper/FormHelper.php
にあります。 -
データベーススキーマ:内部型の取得は、
$context->type($fieldName)
で行われます。これにより、データベースのスキーマ情報が利用されます。 -
コンテキストの確認:フォームのコンテキストは、
_getContext
メソッドで取得されます。このメソッドは、FormHelper
クラスの中にあります。
まとめ
CakePHPのフォームヘルパーを利用することで、フォームフィールドの生成がすっきり簡単になります。規約に従ったカラム名や適切なコンテキストの使用により、入力タイプが自動的に設定されるため、開発者はコードを書く手間を大幅に削減でき、効率的なアプリケーション開発を加速させることができます。また、コードが読みやすくなり、メンテナンス性が向上するため、チーム開発においても大きなメリットがあります。個人的にはこのメリットが一番大きく感じられます。
この記事を通じて、CakePHPのフォームヘルパーの自動入力タイプ設定について理解が深まったでしょうか? ぜひ、実際のプロジェクトで試してみてください!