サーバー側でフォームの入力を検証しようとしていますが、バリデーターから常にtrueを取得しています。何が悪いのですか?
.../templates/customer_registration.xml
_<?xml version="1.0" encoding="UTF-8"?>
<form name="customer_registration_form" title="COM_CANTEEN_CUSTOMER_REGISTRATION_TITLE" description="COM_CANTEEN_CUSTOMER_REGISTRATION_DESCRIPTION" buttonLabel="COM_CANTEEN_CUSTOMER_REGISTRATION_BUTTON_LABEL">
<fields name="customer_registration">
<fieldset name="customer_registration">
<field name="name" type="text" class="required validate-username" size="80" minLength="4" maxLength="255"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_MESSAGE" />
<field name="age" type="integer" class="required" default="6" first="1" last="150" step="1"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_MESSAGE" />
<field name="permanent_orderer" type="checkbox" default="1"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_MESSAGE" />
</fieldset>
</fields>
</form>
_
.../templates/basic_form_layout.php
_<?php
extract($displayData);
JHtml::_('behavior.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_canteen&controller=main&action=form_test'); ?>"
method="post" name="<?php echo $form->getAttribute('name'); ?>" class="<?php echo $form->getAttribute('class'); ?>">
<legend><?php echo JText::_($form->getAttribute('title')); ?></legend>
<?php
echo JText::_($form->getAttribute('description'));
foreach (array_keys($form->getFieldsets()) as $fieldset)
echo $form->renderFieldset($fieldset);
?>
<div>
<?php echo JHtml::_('form.token'); ?>
<button type="submit"><?php echo JText::_($form->getAttribute('buttonLabel')); ?></button>
</div>
</form>
_
.../MainController.php
_/**
* @action
* @allow("public")
*/
public function formTest(iRequest $request, iResponse $response){
$templateDir = JPATH_COMPONENT . '/Canteen/presentation/templates';
$form = JForm::getInstance('customer_registration', $templateDir . '/customer_registration.xml');
$formData = $request->getPostData()->getArray();
$filtered = $form->filter($formData);
foreach ($filtered as $fieldset => $fields)
foreach ($fields as $field => $value)
$form->setValue($field, $fieldset, $value);
$result = $form->validate($filtered);
$content = new HtmlFragment();
$content->addTemplate($response->getTemplate('basic_form_layout.php'), array('form' => $form));
$content->addText(var_export($result, true));
$response->setContent($content);
}
_
_$filtered
_変数を確認しました。これには、CSRFトークンなしでフィルタリングされたデータが含まれます。たとえば、_{'customer_registration': {name: "", age: "6", permanent_orderer: "1"}}
_のようになります。実際、$form->validate($data)
にどのようなデータを渡しても、常にtrueが返されます。エラーメッセージの検証と表示にJForm
を使用したいと思います。これが機能しない理由はありますか?
JFormのコード を確認しました。
それによると、_class="required validate-username"
_は機能しません。代わりに、必要なフィールドで_required="true"
_を使用する必要があります。
それ以外はすべてルールによって検証されます。 XMLファイルに_validate="ruleType"
_を追加する必要があります。 minLength
、maxLength
などは明らかにクライアント側でのみ機能し、サーバー側の検証はHTML5仕様に準拠していません。
クライアント側で検証したい場合は、クライアント側のlibでも同じルールタイプを定義する必要があると思います。 HTML5で確認したところ、動作しましたが、エラーメッセージは表示されませんでした。壊れていると思ったのですが、HTML5検証に適切に接続されていないようです。本当に問題ではありません。2回働きたくないので、クライアント側の検証は行いません。
エラーメッセージは$form->getErrors()
で確認できます。それらがフィールドに追加されると思ったので、自動レンダリングするとエラーメッセージが表示されますが、どうやらjoomlaアプリでこれらのメッセージをエンキューする必要があります。大丈夫ですが、もっと良かったかもしれません。
注意:
docs で関連部分を見つけましたが、おそらく表面的すぎるので読みすぎました。私は眠りませんでした。 :S
私は次のコードで終わりました:
.../templates/customer_registration.xml
_<?xml version="1.0" encoding="UTF-8"?>
<form name="customer_registration_form" title="COM_CANTEEN_CUSTOMER_REGISTRATION_TITLE" description="COM_CANTEEN_CUSTOMER_REGISTRATION_DESCRIPTION" buttonLabel="COM_CANTEEN_CUSTOMER_REGISTRATION_BUTTON_LABEL">
<fields name="customer_registration">
<fieldset name="customer_registration">
<field name="name" type="text" required="true" size="80"
validate="text" minLength="4" maxLength="80" pattern="\p{L}+(?:\p{Zs}\p{L}+)+"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_NAME_MESSAGE" />
<field name="age" type="integer" required="true" default="6" first="1" last="150" step="1"
validate="integer" min="1" max="150"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_AGE_MESSAGE" />
<field name="permanent_orderer" type="checkbox" default="1"
label="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_LABEL" description="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_DESCRIPTION" message="COM_CANTEEN_CUSTOMER_REGISTRATION_PERMANENT_ORDERER_MESSAGE" />
</fieldset>
</fields>
</form>
_
.../templates/rules/text.php
_<?php
use \SimpleXMLElement;
use \JForm;
use \JRegistry;
use \JFormRule;
class JFormRuleText extends JFormRule {
public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
{
if (!isset($value))
$value = '';
if (!is_string($value))
return false;
$length = mb_strlen($value, mb_detect_encoding($value));
if (isset($element['minLength'])) {
$minLength = (int) $element['minLength'];
if ($minLength > $length)
return false;
}
if (isset($element['maxLength'])) {
$maxLength = (int) $element['maxLength'];
if ($maxLength < $length)
return false;
}
if (isset($element['pattern'])) {
$pattern = '/'.$element['pattern'].'/usD';
if (!preg_match($pattern, $value))
return false;
}
return true;
}
}
_
.../templates/rules/integer.php
_<?php
use \SimpleXMLElement;
use \JForm;
use \JRegistry;
use \JFormRule;
class JFormRuleInteger extends JFormRule {
public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
{
$intValue = (int) $value;
if ((string) $intValue !== $value || (float) $intValue !== (float) $value)
return false;
if (isset($element['min'])) {
$min = (int) $element['min'];
if ($min > $intValue)
return false;
}
if (isset($element['max'])) {
$max = (int) $element['max'];
if ($max < $intValue)
return false;
}
return true;
}
}
_
.../MainController.php
_/**
* @action
* @allow("public")
*/
public function formTest(iRequest $request, iResponse $response){
$form = $response->getForm('customer_registration.xml', $request->getAddress(), $request->getQuery());
if ($request->isPost()){
$form->fill($request->getPostData());
$isValid = true;
if (!$request->hasValidToken()) {
$response->reportError(new Exception('Invalid token.'));
$isValid = false;
}
if (!$form->validate()) {
foreach ($form->getErrors() as $error)
$response->reportError($error);
$isValid = false;
}
if ($isValid) {
$response->reportSuccess('Customer created.');
$form->reset();
}
}
$content = new HtmlFragment();
$content->addForm($form, $response->getTemplate('basic_form_layout.php'));
$response->setContent($content);
}
_
よくこれはまだ、検証が機能することを示すためのダミーの概念実証コードです。
誰かがしたい場合は、デフォルトのエラーメッセージを上書きすることもできます:
_// required: JText::sprintf('JLIB_FORM_VALIDATE_FIELD_REQUIRED', $name|label);
// rule: $message | JText::sprintf('JLIB_FORM_VALIDATE_FIELD_INVALID', $label)
_
また、Exception
ではなくfalse
インスタンスを返すことで、同じルールから異なるエラーメッセージを送信することが可能です。したがって、XMLで指定されたメッセージを使用する必要はありません。私にとってはそれで十分でした。