web-dev-qa-db-ja.com

サーバー側のフォーム検証は常にtrueを返します

サーバー側でフォームの入力を検証しようとしていますが、バリデーターから常に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を使用したいと思います。これが機能しない理由はありますか?

1
inf3rno

JFormのコード を確認しました。

それによると、_class="required validate-username"_は機能しません。代わりに、必要なフィールドで_required="true"_を使用する必要があります。

それ以外はすべてルールによって検証されます。 XMLファイルに_validate="ruleType"_を追加する必要があります。 minLengthmaxLengthなどは明らかにクライアント側でのみ機能し、サーバー側の検証は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で指定されたメッセージを使用する必要はありません。私にとってはそれで十分でした。

0
inf3rno