PowerCMS™
2025年1月1日購入分よりライセンスの価格を改定いたします。
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[新着情報] PowerCMS 4 系のサポート終了予定について を追加しました。
[新着情報] PowerCMS 4.58 の提供を開始 を追加しました。

PowerCMS ブログ

ホーム > PowerCMS ブログ > PowerCMS 5 > ContactFormのテキスト系項目に文字種チェックを追加する

2020年03月26日

ContactFormのテキスト系項目に文字種チェックを追加する

ContactForm の post_save_feedback コールバックを使用することでフォームから投稿されたタイミングで何らかの処理を行うことができ、フォームの投稿をCRMなどの外部サービスに送る処理などに利用することができます。これによりContactForm をデータ管理の入り口として使用することができるようになりますが、外部サービスによる制約でシフトJIS(CP932)で定義された文字しか使用できないといった場合があります。ここではそのような場合に使用できない文字が入力された際にフォームの入力エラーとする方法をご紹介します。

具体的には以下の処理を行うプラグインを実装します。

  1. ContactForm の init_app コールバックで validate ハンドラを変更する
  2. validate ハンドラで文字種チェックを行い、結果をテンプレートパラメータに設定する

validate ハンドラを変更する

ContactForm に組み込みのフォーム項目タイプもプラグインから追加するフォーム項目タイプと同様の仕組みで実装されており、レジストリに定義を登録し、各種ハンドラを実装するという形になっています。プラグインによるフォーム項目タイプの追加方法については下記の記事を参照してください。

テキスト系フォーム項目のバリデーションの挙動を変えるには、タイプ text とタイプ textarea のフォーム項目の validate ハンドラを変更します。この2つのフォーム項目には validate ハンドラは設定されていないので、単純に新しいハンドラをレジストリに設定することで実現できます。

アプリケーションの初期化時にレジストリを変更することで実行時にプラグインから validate ハンドラを変更することができます。従って、まずはプラグインの config.yaml で以下のように ContactForm の init_app コールバックハンドラの設定を行います。

callbacks:
    MT::App::ContactForm::init_app: $sample::Sample::Callbacks::cb_contactform_init_app

validate ハンドラの設定はレジストリの「contactform_objects→フォーム項目タイプ→validate」にあるため、init_app コールバックで以下のように新しいハンドラを設定します。

sub cb_contactform_init_app {
    my ($cb, $app) = @_;

    my $registry = MT->instance->registry( 'contactform_objects' );
    $registry->{text}->{validate} = \&contactform_validate_text;
    $registry->{textarea}->{validate} = \&contactform_validate_text;

    ContactForm::ContactForm->add_trigger(post_load => sub {
        my $obj = shift;
        return 1 unless $obj->type eq 'text' || $obj->type eq 'textarea';
        $obj->validate(1);
    });
}

また、フォーム項目の入力チェックの使用の有無はフォーム項目の編集画面から設定を行いますが、入力チェックが設定できるかどうかはフォーム項目のタイプによって決まっています。タイプ text とタイプ textarea は設定できないタイプであるため入力チェックを有効にすることができません。そこでオブジェクトのロード時に強制的に有効にするようにトリガーを設定しています。

文字集合のバリデーションを行う

validate ハンドラは下記の引数を受け取り、バリデーションに成功なら真を、失敗なら偽を返す関数として実装します。

$appMT::App::ContactForm オブジェクト
$contactformContactForm::ContactForm オブジェクト(フォーム項目)
$field_valueフォームに入力された値(スカラまたは配列のリファレンス)
$paramsテンプレートパラメータのハッシュのリファレンス

レジストリで指定した contactform_validate_text() を以下のように実装します。

sub contactform_validate_text {
    my ( $app, $contactform, $field_value, $params ) = @_;

    my $value = ref $field_value eq 'ARRAY' ? join('', @$field_value) : $field_value;
    my $value2 = $value;

    require Encode;
    $value2 = Encode::encode('cp932', $value2);
    $value2 = Encode::decode('cp932', $value2);

    if ($value ne $value2) {
        $params->{ invalid_char } = 1;
        return 0;
    }
    
    $params->{ invalid_char } = 0;
    return 1;
}

今回は文字集合のチェックをUTF-8からCP932に変換して元に戻した時に同じ文字列に戻るかどうかで判定しています。CP932で使用できない文字が含まれていた場合、CP932に変換した時点で元の文字とは異なる文字(?など)に変換されるということを利用しています。validate ハンドラが偽を返した場合、ContactForm が $params のキー「field_error」に「invalid」を設定しますが、詳細情報として「invalid_char」を設定するようにしています。テンプレートではこれらのパラメータを使用してエラーメッセージを表示します。

バリデーション結果を出力する

フォーム項目のテンプレートを修正して適切なエラーメッセージが表示されるようにします。そのままの状態でも「〜の書式を確認してください。」というメッセージが表示されますが、より適切な「〜にご利用いただけない文字が入力されています。」というメッセージが表示されるようにします。

バリデーションのエラーメッセージは以下の部分で表示されています。

      <MTIf name="field_error" eq="invalid">
        <$MT:Trans phrase="Invalid '[_1]'." component="ContactForm" params="$field_name"$>

この部分に invalid_char を使用した分岐を追加して以下のようにします。

      <MTIf name="field_error" eq="invalid">
        <MTIf name="invalid_char">
          <mt:var name="field_name" escape="html">にご利用いただけない文字が入力されています。
        <MTElse>
          <$MT:Trans phrase="Invalid '[_1]'." component="ContactForm" params="$field_name"$>
        </MTIf>

以上で文字種チェックを行うプラグインが実装できました。


カテゴリー
PowerCMS 5
プラグイン
技術情報
投稿者
Sakai Ryuji

Recent Entries