フォーム

目次

フォームの基本

a-blog cms では標準でフォーム機能も搭載しております。お問い合わせにフォームなどで利用されています。機能としては、以下のようなものが上げられます。

  • サイトのどこにでも設置が可能
  • フォームの入力内容は管理者と一般にメールが送られてきます
  • 入力項目のチェック機能(必須入力やメールアドレスが一致しているか、数字判定など)
  • 入力項目のコンバート機能(大文字を小文字に変換など)
  • 複数ステップのフォームを作る事ができる
  • フォームの送信内容を蓄積してCSVのダウンロードする

フォームモジュール

フォームについてもモジュールとして提供しております。フォームは基本的に「新規」「修正」「確認」「完了」の4つのステップ(Twig版の場合は3ステップ)で構成されています。必要に応じてステップを追加できるため、複数ステップに対応したフォームを柔軟に構築することが可能です。


<!-- BEGIN_MODULE Form -->

<!-- BEGIN step-->
  <!-- 初期画面 -->
  @include("/contact/form/input.html")
<!-- END step -->

<!-- BEGIN step#reapply -->
  <!-- 修正画面 -->
  @include("/contact/form/input.html")
<!-- END step#reapply -->

<!-- BEGIN step#confirm -->
  <!-- 確認画面 -->
  @include("/contact/form/confirm.html")
<!-- END step#confirm -->

<!-- BEGIN step#result -->
  <!-- 完了画面 -->
  @include("/contact/form/confirm.html")
<!-- END step#result -->

<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.step == 'step' %}
  <!-- 初期・修正画面 -->
  {{ include('/contact/form/input.twig', form.fields) }}
{% endif %}

{% if form.step == 'confirm' %}
  <!-- 確認画面 -->
  {{ include('/contact/form/confirm.twig', form.fields) }}
{% endif %}

{% if form.step == 'result' %}
  <!-- 完了画面 -->
  {{ include('/contact/form/confirm.twig', form.fields) }}
{% endif %}

フォームの基本

入力フォームは、基本的にカスタムフィールドと同じ書き方で増やしていく事ができます。(HTMLのみで追加可能)


<input type="text" name="address" value="{address}" />
<input type="hidden" name="field[]" value="address" />

<input type="hidden" name="address:validator#required" /> <!-- 必須項目 -->
<input type="text" name="address" value="{{ address.value }}" aria-invalid="{{ address.invalid ? 'true' : 'false' }}" />
<input type="hidden" name="field[]" value="address" />

<input type="hidden" name="address:validator#required" /> <!-- 必須項目 -->

フォームの管理ページ

フォーム > フォーム管理 の[変更]ボタンを押すとフォームを管理するページに移動します。こちらに、フォームIDを設定し、そのフォームIDをテンプレート上に設定する事で、データベース上にフォームの入力情報を保存し、CSVダウンロードを可能にしています。また、メールのテンプレートの設定や、From, To等の設定も管理ページ上で設定します。


フォーム管理画面

フォーム管理画面

stepブロックを知ろう

基本のブロック構成

テンプレートを上から順に見ていくと、以下のようなブロック構成になっていることが分かります。フォームの現在のステップに応じて、該当するブロックの内容のみが表示され、その他のステップの内容は表示されません。

入力画面(step)でエラーが発生した場合は再入力画面(step#reapply)へ遷移し、エラーがなければ確認画面(step#confirm)へ遷移します。その後、確認画面から送信すると完了画面(step#result)へ遷移します。

Twigテンプレート例では入力画面と再入力画面を分けず、エラーがある場合も入力画面(step)内にメッセージを表示します。

なお、標準テンプレートでもTwigテンプレート例と同様に、再入力画面(step#reapply)を設けない構成にすることが可能です。

Formモジュールにおけるstepブロックの構成


<!-- BEGIN_MODULE Form -->

<!-- BEGIN step -->
(中略:はじめの入力画面)
<!-- END step -->

<!-- BEGIN step#reapply -->
(中略:エラーがあったときの再入力画面)
<!-- END step#reapply -->

<!-- BEGIN step#confirm -->
(中略:送信前の内容確認)
<!-- END step#confirm -->

<!-- BEGIN step#result -->
(中略:送信後の完了通知)
<!-- END step#result -->

<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.step == 'step' %}
(中略:はじめの入力画面 or エラーがあったときの再入力画面)
{% endif %}

{% if form.step == 'confirm' %}
(中略:送信前の内容確認)
{% endif %}

{% if form.step == 'result' %}
(中略:送信後の完了通知)
{% endif %}

次に表示するステップ操作の仕組み

基本的に、サンプルテンプレートを元に編集を加えるだけで利用することができます。そのため、以下の内容について編集する事はあまり多くはありませんが、どこでその記述をしているかについて説明します。


再入力画面( step#reapply )のHTMLソース

再入力画面( step#reapply )のHTMLソース


エラー時に表示されるstepの指定

GET, POSTの2通りの方法で指定が可能です。

  • form要素のaction属性に?step=reapplyを指定(GET)
  • input要素のname属性にerror、value属性にreapplyを指定(POST)

どちらか一方の指定だけで大丈夫です。エラーなどがあった場合は、ここで指定されたstepが表示されます。

次に表示したいstepの指定

HTMLのinput要素のname属性にstepvalue属性にconfirmと記述しています。ここに次に表示したいstepの名前を入力します。エラーなどがなければ、ここで指定されたstepが表示されます。

例の場合では再入力の内容にエラーがあれば再入力画面( step#reapply )に戻ってきて、エラーがなければ確認画面( step#confirm )に遷移するという記述になります。

フォームIDの設定

フォームを設置するときフォームIDをテンプレートとフォーム管理画面に設定しています。フォームIDがあることでフォームの管理画面に送信データをデータベースに蓄積したり、メールのテンプレートやメールアドレスを指定することができます。

FormモジュールにフォームIDを指定する

フォームの各ステップにフォームIDを記述します。IDの英数字で指定してください。記述方法は以下のような記述になります。

<input type="hidden" name="id" value="(フォームID)" />

例えば、フォームIDが contactForm のときは以下のように記述します。


<!-- BEGIN_MODULE Form -->
 
<!-- BEGIN step-->
<!-- 新規 -->
@include("/include/form/input.html")
<input type="hidden" name="id" value="contactForm" />
<!-- END step -->
 
<!-- BEGIN step#reapply -->
<!-- 修正 -->
@include("/include/form/input.html")
<input type="hidden" name="id" value="contactForm" />
<!-- END step#reapply -->
 
<!-- BEGIN step#confirm -->
<!-- 確認 -->
@include("/include/form/confirm.html")
<input type="hidden" name="id" value="contactForm" />
<!-- END step#confirm -->
 
<!-- BEGIN step#result -->
<!-- 完了 -->
@include("/include/form/result.html")
<!-- END step#result -->
 
<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.step == 'step' %}
  <!-- 初期・修正画面 -->
  {{ include('/contact/form/input.twig', form.fields) }}
  <input type="hidden" name="id" value="contactForm" />
{% endif %}

{% if form.step == 'confirm' %}
  <!-- 確認画面 -->
  {{ include('/contact/form/confirm.twig', form.fields) }}
  <input type="hidden" name="id" value="contactForm" />
{% endif %}

{% if form.step == 'result' %}
  <!-- 完了画面 -->
  {{ include('/contact/form/confirm.twig', form.fields) }}
{% endif %}

フォーム管理にフォームIDを指定する

管理画面 > フォームの [フォームIDを作成]ボタンを押してフォームIDを作成します。フォーム管理ではフォームの送信データのログを閲覧したり、メールアドレスやテンプレートを指定ができます。

メールのテンプレートを指定する

フォームID画面ではメールのテンプレートや管理者のメールアドレスを指定することができます。

  • SubjectTpl :一般に届くメールの件名
  • BodyTpl :一般に届くメールの本文
  • BodyHTMLTpl : 一般に届くHTMLメールの本文(※Ver.2.5以降より追加)
  • AdminSubjectTpl:管理者に届くメールの件名
  • AdminBodyTpl:管理者に届くメールの本文
  • AdminBodyHTMLTpl:管理者に届くHTMLメールの本文(※Ver.2.5以降より追加)

メールのテンプレートはフォームのテンプレートが置いてあるテーマフォルダに置いてください。 例えば メールテンプレートが /themes/site2015/contact/form/subject.txt に置いてあった場合のパスは /contact/form/subject.txt になります。

テキストメール or HTMLメール

HTMLメールの本文のテンプレートがない場合は、テキストメールとして送信されます。HTMLメールとして送りたい場合は、テキストとHTML両方のテンプレートを指定ください。

メールアドレスを指定する

以下のようなメールアドレスを指定する箇所があります。

  • To
  • From
  • Cc
  • Bcc
  • Reply-To
  • AdminTo
  • AdminFrom
  • AdminCc
  • AdminBcc
  • AdminReply-To

最初にAdminがつく設定が管理者宛の設定で、つかないものが、自動返信の一般宛の設定になります。 これらの値は、ここでの設定以外にフォームのテンプレートで指定ができます。

通常は、Toにはお問い合わせした人に送信するので、毎回変わりますので、テンプレートで動的に設定します。 Fromは管理者のメールアドレスを設定すればよいでしょう。

逆に管理者宛のAdminToは、管理者のメールアドレスを固定で設定し、Fromを動的にテンプレートで指定します。


フォーム管理でのメール設定

フォーム管理でのメール設定


<!-- BEGIN step#confirm -->
  @include("/contact/form/confirm.html")
  
  <form action="thanks.html" method="post" class="js-unload_alert" enctype="multipart/form-data">
    <!-- テンプレートで、自動返信の宛先を動的に設定 -->
    <input type="hidden" name="To[]" value="{email}" />
    <!-- テンプレートで、管理者宛メールの返信先を動的に設定 -->
    <input type="hidden" name="AdminReply-To[]" value="{email}" />

    <input type="hidden" name="step" value="result" />
    <input type="hidden" name="takeover" value="{takeover}" />
    <input type="hidden" name="id" value="contactForm" />

    <button type="submit" name="ACMS_POST_Form_Submit">
      送信する
    </button>
  </form>
<!-- END step#confirm -->
{% if form.step == 'confirm' %}
  {{ include('/contact/form/confirm.twig', form.fields) }}

  <form action="thanks.html" method="post" enctype="multipart/form-data">
    <!-- テンプレートで、自動返信の宛先を動的に設定 -->
    <input type="hidden" name="To[]" value="{{ form.fields.email.value }}" />
    <!-- テンプレートで、管理者宛メールの返信先を動的に設定 -->
    <input type="hidden" name="AdminReply-To[]" value="{{ form.fields.email.value }}" />

    <input type="hidden" name="step" value="result" />
    <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
    <input type="hidden" name="id" value="contactForm" />

    <button type="submit" name="ACMS_POST_Form_Submit">
      送信する
    </button>
  </form>
{% endif %}

メールテンプレート

メールテンプレートにはフォームの項目で使用したカスタムフィールドの変数やグローバル変数などが記述されてします。
例えば /themes/site2015/contact/form/adminbody.txt では以下のような記述をしています。

{name} 様 よりお問い合わせがありました。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

受付日時:%{Y}年%{n}月%{j}日 %{H}:%{i}:%{s}

■お問い合わせ情報

ご用件    : {description}[raw]
お問い合わせ内容:
{inquiry}[raw]


■お客様情報

会社名    : {company}[raw]
お名前    : {name}[raw]
メールアドレス: {email}
お電話番号  : {phone}
ご住所    : 〒{zip} {pref_code} {address}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

site2015テーマのフォームのメールテンプレートはテキストファイルのためHTMLは記述していません。Ver.2.5よりHTMLメールにも対応となりましたので、HTMLメールをご利用になる際はVer.2.5以降のバージョンをお使いください。

また、校正オプションを記述することができます。校正オプションについてはリファレンスをご覧ください。 例えばお問い合わせ内容のテキストを改行するには以下のような校正オプションを記述します。

{inquiry}[escape|nl2br]

送信データの確認

投稿データを確認する

フォームから送信された内容はフォーム管理に蓄積されます。フォーム管理の[投稿データ]ボタンを押してください。フォームに投稿された内容の一覧が表示されます。メールの内容を見たい場合は[本文を表示]ボタンを押すと本文を見ることができます。


本文を表示

本文を表示

投稿内容を絞り込む

投稿データを投稿された期間、連番などから絞り込めます。また、チェックした投稿データだけ削除することもできます。

管理者宛のメール内容を閲覧する

フォームログで表示されているのは一般宛に送信されたメールの内容が表示されています。管理者宛のメール内容を見るには絞り込むの「管理者宛(件名/本文) 」にチェックをして[表示]ボタンを押すと管理者宛のメール一覧が表示されます。


投稿内容を絞り込む

投稿内容を絞り込む

CSVデータでダウンロードする

投稿データはダウンロードする文字コードを選択してCSV形式でダンロードすることができます。


入力項目の追加

入力側に追加するときの記述について

フォームの入力フォームはフォームステップ:初期(step)とフォームステップ:修正・エラー(step#reapply)の2カ所に記述されています。フォームの項目を追加するにはこの2つのステップに追加してください。フォームの項目はカスタムフィールドで作られています。カスタムフィールドについてはカスタムフィールドのページをご覧ください。

例えばsiteテーマでは /themes/site/contact/form/input.html にフォームの項目が記述されています。siteテーマのフォームステップ:初期(step)とフォームステップ:修正・エラー(step#reapply)は input.html とインクルードしているため項目を追加するときはこのファイルを編集すれば2ステップに反映されます。 以下は siteテーマが /themes/site2014/contact/form/input.html を読み込んでいるソースの一部です。

Twigテンプレート例では入力画面と再入力画面を分けず、エラーがある場合も入力画面(step)内にメッセージを表示します。

なお、標準テンプレートでもTwigテンプレート例と同様に、再入力画面(step#reapply)を設けない構成にすることが可能です。


<!-- BEGIN step -->
<form action="?step=reapply" method="post" class="js-unload_alert js-validator h-adr" enctype="multipart/form-data">
  @include("/contact/form/input.html")

  <input type="hidden" name="step" value="confirm" />
  <input type="hidden" name="error" value="reapply" />
  <input type="hidden" name="id" value="contactForm" />
  <button type="submit" name="ACMS_POST_Form_Confirm">内容の確認へ</button>
</form>
<!-- END step -->

<!-- BEGIN step#reapply -->
<form action="?step=reapply" method="post" class="js-unload_alert js-validator h-adr" enctype="multipart/form-data">
  @include("/contact/form/input.html")

  <input type="hidden" name="step" value="confirm" />
  <input type="hidden" name="error" value="reapply" />
  <input type="hidden" name="id" value="contactForm" />
  <button type="submit" name="ACMS_POST_Form_Confirm">
    内容の確認へ
  </button>
</form>
<!-- END step#reapply -->
{% if form.step == 'step' %}
  <form
    id="contactForm"
    action=""
    method="post"
    enctype="multipart/form-data"
    class="js-validator js-unload_alert"
  >
    {{ include('/contact/form/input.twig', form.fields) }}

    <input type="hidden" name="step" value="confirm" />
    <input type="hidden" name="error" value="step" />
    <input type="hidden" name="id" value="contactForm" />
    <button type="submit" name="ACMS_POST_Form_Confirm">
      内容の確認へ
    </button>
  </form>
{% endif %}

siteテーマを使ってフォームの項目を追加してみましょう。 /themes/site/contact/form/input.html に資料請求するかどうかの項目を追加します。以下のソースを追加してください。


<tr>
  <th>資料請求</th>
  <td>
    <label class="acms-form-radio">
    <input type="radio" name="request" value="資料請求する"{request:checked#資料請求する} /><i class="acms-ico-radio"></i>資料請求する</label>

    <label class="acms-form-radio">
    <input type="radio" name="request" value="資料請求しない"{request:checked#資料請求しない} /><i class="acms-ico-radio"></i>資料請求しない</label>

    <input type="hidden" name="field[]" value="request" />
  </td>
</tr>
<tr>
  <th>資料請求</th>
  <td>
    <label class="acms-form-radio">
    <input type="radio" name="request" value="資料請求する" {{ request.array|checked('資料請求する') }} /><i class="acms-ico-radio"></i>資料請求する</label>

    <label class="acms-form-radio">
    <input type="radio" name="request" value="資料請求しない" {{ request.array|checked('資料請求しない') }} /><i class="acms-ico-radio"></i>資料請求しない</label>

    <input type="hidden" name="field[]" value="request" />
  </td>
</tr>

siteテーマのお問い合わせフォームに資料請求を追加するかどうかのフォームを追加できました。


selected / checked の出力

セレクトボックスやラジオボタン、チェックボックスでは、確認画面やバリデーションエラー発生後に入力済みの値を保持するため、selectedchecked 属性を出力する必要があります。

a-blog cms では、現在の入力値と比較して一致した場合のみ selected または checked 属性を出力する仕組みが用意されています。

標準テンプレート

標準テンプレートでは、以下の変数を利用できます。

用途

記述例

チェックボックス・ラジオボタン

{[フィールド名]:checked#[値]}

セレクトボックス

{[フィールド名]:selected#[値]}

入力値と指定した値が一致した場合のみ、それぞれ checked または selected が出力されます。

<input type="radio" name="gender" value="male" {gender:checked#male}>
<input type="radio" name="gender" value="female" {gender:checked#female}>

<select name="pref">
  <option value="tokyo" {pref:selected#tokyo}>東京都</option>
  <option value="osaka" {pref:selected#osaka}>大阪府</option>
</select>

また、複数選択のチェックボックスにも利用できます。

<input type="checkbox" name="hobby[]" value="sports" {hobby:checked#sports}>
<input type="checkbox" name="hobby[]" value="music" {hobby:checked#music}>

Twigテンプレート

Twigテンプレートでは、checked フィルターおよび selected フィルターを利用できます。

単一値の場合は .value、複数選択のチェックボックスの場合は .array を利用します。

単一値の場合でも .array による含有判定でチェックできるため、特に区別せず .array を利用しても問題ありません。

記述例

単一値の selected

{{ field.value | selected('value') }}

複数値の selected

{{ field.array | selected('value') }}

単一値の checked

{{ field.value | checked('value') }}

複数値の checked

{{ field.array | checked('value') }}

入力値と指定した値が一致した場合のみ、それぞれ selected または checked が出力されます。

<input type="radio" name="gender" value="male" {{ gender.value | checked('male') }}>
<input type="radio" name="gender" value="female" {{ gender.value | checked('female') }}>

<select name="pref">
  <option value="tokyo" {{ pref.value | selected('tokyo') }}>東京都</option>
  <option value="osaka" {{ pref.value | selected('osaka') }}>大阪府</option>
</select>

複数選択のチェックボックスでは .array を利用します。

<input type="checkbox" name="hobby[]" value="sports" {{ hobby.array | checked('sports') }}>
<input type="checkbox" name="hobby[]" value="music" {{ hobby.array | checked('music') }}>

Twigでは、checked および selected 校正オプション(フィルター)を利用して属性を出力します。指定した値が対象の変数と一致する場合、または配列に含まれる場合に checked または selected が出力され、それ以外の場合は何も出力されません。


a-blog cmsのフォームでは修正画面に戻っても入力したデータが保持されています。inputタグにカスタムフィールドの変数が書いてないとデータは保持されません。


<!-- ○ データが保持される -->
<input type="radio" name="request" value="on"{request:checked#on} /><i class="acms-ico-radio"></i>資料請求する</label>

<!-- × データが保持されない -->
<input type="radio" name="request" value="on" /><i class="acms-ico-radio"></i>資料請求する</label>
<!-- ○ データが保持される -->
<input type="radio" name="request" value="on" {{ request.array|checked('on') }} /><i class="acms-ico-radio"></i>資料請求する</label>

<!-- × データが保持されない -->
<input type="radio" name="request" value="on" /><i class="acms-ico-radio"></i>資料請求する</label>

出力側に追加するときの記述について

確認画面(step#confirm)と完了画面(step#result)で追加した項目を出力する用のソースを追加します。 今度はsiteテーマのお問い合わせフォームの /themes/site/contact/form/confirm.html に以下のHTMLを追加してください。


<tr>
  <th>資料請求</th>
  <td>
    {request}
  </td>
</tr>
<tr>
  <th>資料請求</th>
  <td>
    {{ request.value }}
  </td>
</tr>

確認画面にいくと資料請求の項目が追加されています。


メールのテンプレートに追加

項目を追加したらメールのテンプレートにも追加が必要です。フォームには管理者宛と一般宛の本文のメールテンプレートが2つあります。この2つに項目を追加してください。

siteテーマでは以下が管理者宛と一般宛の本文のメールテンプレートになります。
/themes/site/contact/form/body.txt
/themes/site/contact/form/adminbody.txt

adminbody.txtのテンプレートに資料請求の項目を追加した例になります。

{name} 様 よりお問い合わせがありました。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

受付日時:%{Y}年%{n}月%{j}日 %{H}:%{i}:%{s}

■お問い合わせ

会社名    : {company}
お名前    : {name}
メールアドレス: {email}
お電話番号  : {phone}
ご住所    : 〒{zip} {pref_code} {address}

資料請求: {request}

お問い合わせ種類: {description}
お問い合わせ内容:
{inquiry}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

バリデーター&コンバーター

入力された値のチェックと変換

a-blog cms のフォームには、入力された値のチェックや変換を行う「フォームオプション」という機能があります。

種類説明
バリデーター入力された値を指定した条件でチェックします(必須チェックなど)
コンバーター入力された値を指定した形式に変換します(全角→半角など)

バリデーター

ここでは、メールアドレスの入力欄を「必須入力」であることをチェックするように設定してみましょう。

バリデーターの指定

<input type="text" name="email" value="">
<input type="hidden" name="field[]" value="email">
<input type="hidden" name="email:v#required">

3行目が追加された記述です。この記述を入力画面(step)と再入力画面(step#reapply)の両方に追加してください。

<input type="hidden" name="[対象の項目名]:validator#[オプション名]" />

対象となるフォーム項目の name 属性を指定し、最後にバリデーターオプション名を指定します。

オプション説明
required必須項目が入力されているかチェックするオプションです
maxLength文字数の上限を設定するオプションです
emailメールアドレスの書式として正しいかをチェックするオプションです

他のオプションについては、リファレンス:フォームオプションを参照してください。

画像・ファイルの場合の必須チェック

ファイルアップロードや画像アップロードの入力項目で必須チェックを行う場合は、通常の入力項目とは記述方法が異なります。

次のように記述すると、ファイルを選択していてもエラーとなってしまいます。

<input type="hidden" name="photo:v#required" />

ファイルや画像の必須チェックを行う場合は、以下のように @path を付与してください。

<input type="hidden" name="photo@path:v#required" />

この記述で正しく必須チェックが機能します。

エラー表示の実装

バリデーターを設定したら、次にエラー発生時の表示を実装します。


<input type="text" name="email" value="{email}">
<input type="hidden" name="field[]" value="email">
<input type="hidden" name="email:v#required">

<!-- BEGIN email:validator -->メールアドレスを必須入力です。<!-- END email:validator -->

<input type="text" name="email" value="{{ email.value }}">
<input type="hidden" name="field[]" value="email">
<input type="hidden" name="email:v#required">

{% if email.invalid %}<p>メールアドレスを必須入力です。</p>{% endif %}

エラー表示のブロックが加わりました。このブロック内は、指定されたフィールドについて何かしらエラーがあったときだけ表示されます。


<!-- BEGIN [対象の項目名]:validator --><p>[エラーメッセージ]</p><!-- END [対象の項目名]:validator -->
{% if [対象の項目名].invalid %}<p>[エラーメッセージ]</p>{% endif %}

コンバーター

次に、メールアドレス欄に入力された全角英数字を自動的に半角英数字へ変換する機能を実装します。

コンバーターを設定する前に、メールアドレス欄へ全角英数字を含むメールアドレスを入力してみてください。メールアドレス形式のチェックに失敗し、バリデーションエラーが表示されるはずです。

全角英数字を半角英数字に変換するサンプルコード

<dt>メールアドレス</dt>
<dd>
<input type="text" name="email" value="{email}" />
<input type="hidden" name="field[]" value="email" />
<input type="hidden" name="email:validator#email" />
<input type="hidden" name="email:converter" value="a" />
</dd>

6行目がコンバーターの設定です。この記述を、入力画面( step )と、再入力画面( step#reapply )の両方に追記してください。

<input type="hidden" name="[対象の項目名]:converter" value="[変換オプション]" />

変換オプションはPHPのmb_convert_kana関数のオプションに準拠します。

設定後、再度全角英数字を含むメールアドレスを入力して動作を確認してみましょう。正しく設定できていれば、全角英数字が自動的に半角英数字へ変換され、エラーは表示されません。

この機能を利用することで、郵便番号や電話番号、住所中の数字などを半角または全角へ統一できます。利用者に半角・全角の入力を求めることなく、統一された形式のデータを取得できます。

エラーメッセージの分岐

一つのフィールドで複数のエラーを検知したい場合があります。例えば以下のように、必須だけではなく、数値のみ許可したり、最大数値を設定したりです。

  • 必須
  • 数値のみ許可
  • 100以下の数値を許可

今ままでのエラー表記

ここまでで紹介したエラー表記の仕方は、以下のようなコードでした。


<input type="text" name="age" value="{age}">
<input type="hidden" name="field[]" value="age">
<input type="hidden" name="age:validator#required"> <!-- 必須チェック -->
<input type="hidden" name="age:validator#digits"> <!-- 数値チェック -->
<input type="hidden" name="age:validator#max" value="100"> <!-- 最大数チェック -->

<!-- BEGIN age:validator -->
<p class="notice">年齢が入力されていないか、数値(100以下)が入力されていません。</p>
<!-- END age:validator -->
<input type="text" name="age" value="{{ age.value }}">
<input type="hidden" name="field[]" value="age">
<input type="hidden" name="age:validator#required"> <!-- 必須チェック -->
<input type="hidden" name="age:validator#digits"> <!-- 数値チェック -->
<input type="hidden" name="age:validator#max" value="100"> <!-- 最大数チェック -->

{% if age.invalid %}
<p class="notice">年齢が入力されていないか、数値(100以下)が入力されていません。</p>
{% endif %}

間違ってはいませんが、どのエラーにひっかかっているのか判りにくいです。

エラーにあわせてメッセージを変える


<input type="text" name="age" value="{age}">
<input type="hidden" name="field[]" value="age">
<input type="hidden" name="age:validator#required"> <!-- 必須チェック -->
<input type="hidden" name="age:validator#digits"> <!-- 数値チェック -->
<input type="hidden" name="age:validator#max" value="100"> <!-- 最大数チェック -->

<!-- BEGIN age:validator#required -->
<p class="notice">年齢を入力してください。</p>
<!-- END age:validator#required -->
<!-- BEGIN age:validator#digits -->
<p class="notice">年齢には数値を入力してください。</p>
<!-- END age:validator#digits -->
<!-- BEGIN age:validator#max -->
<p class="notice">年齢には100以下の数値を入力してください。</p>
<!-- END age:validator#max -->
<input type="text" name="age" value="{{ age.value }}">
<input type="hidden" name="field[]" value="age">
<input type="hidden" name="age:validator#required"> <!-- 必須チェック -->
<input type="hidden" name="age:validator#digits"> <!-- 数値チェック -->
<input type="hidden" name="age:validator#max" value="100"> <!-- 最大数チェック -->

{% if age.v.required %}
<p class="notice">年齢を入力してください。</p>
{% endif %}
{% if age.v.digits %}
<p class="notice">年齢には数値を入力してください。</p>
{% endif %}
{% if age.v.max %}
<p class="notice">年齢には100以下の数値を入力してください。</p>
{% endif %}

エラーメッセージが分岐され必要なメッセージだけが出力されるようになりました。

このようにエラーメッセージ用のブロックを書き換える事で、複数のバリデーターを設定した場合のエラーで、別々のメッセージを表示させることができます。


<!-- BEGIN [対象の項目名]:validator#[オプション名] --><p>[エラーメッセージ]</p><!-- BEGIN [対象の項目名]:validator#[オプション名] -->
{% if [対象の項目名].v.[オプション名] %}<p>[エラーメッセージ]</p>{% endif %}

特殊なエラーメッセージ

フォームでファイルをアップロードする際、PHP の upload_max_filesize を超えるサイズのファイルが送信されると、POST データ自体が空になるため、各フィールドごとのエラーメッセージは表示できません。

そのため、以下の記述を使用してフォーム全体のエラーメッセージを表示します。

<!-- BEGIN post:v#filesize -->リクエストサイズが大きすぎます<!-- END post:v#filesize -->

この特殊なエラーブロックは、標準テンプレートのみ対応しており、twig記法では出力できません。

フォームの入力エラー取得

フォームの各ステップに対応した以下のようなブロックがあります。

標準テンプレートの場合

  • step 初期画面
  • step#reapply エラー画面
  • step#confirm 確認画面
  • step#result 送信完了画面
  • step#forbidden 不正アクセス画面
  • step#repeated 連続投稿エラー画面

twigの場合

  • step 初期・修正画面
  • confirm 確認画面
  • result 送信完了画面
  • forbidden 不正アクセス画面
  • repeated 連続投稿エラー画面

<!-- BEGIN_MODULE Form -->

<!-- BEGIN step-->
  <!-- 初期画面 -->
<!-- END step -->

<!-- BEGIN step#reapply -->
  <!-- 修正画面 -->
<!-- END step#reapply -->

<!-- BEGIN step#confirm -->
  <!-- 確認画面 -->
<!-- END step#confirm -->

<!-- BEGIN step#result -->
  <!-- 完了画面 -->
<!-- END step#result -->

<!-- BEGIN step#forbidden -->
  <!-- 不正アクセス画面 -->
<!-- END step#forbidden -->

<!-- BEGIN step#repeated -->
  <!-- 連続投稿エラー画面 -->
<!-- END step#repeated -->

<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.step == 'step' %}
  <!-- 初期・修正画面 -->
{% endif %}

{% if form.step == 'confirm' %}
  <!-- 確認画面 -->
{% endif %}

{% if form.step == 'result' %}
  <!-- 完了画面 -->
{% endif %}

{% if form.step == 'forbidden' %}
  <!-- 不正アクセス画面 -->
{% endif %}

{% if form.step == 'repeated' %}
  <!-- 連続投稿エラー画面 -->
{% endif %}

エラーブロック

以下のようなブロックを記述すると、フォームのバリデーターでエラーが発生した際に、そのエラー内容とフォームIDを変数として持つブロックが表示されます。

エラーブロックの記述


<!-- BEGIN_MODULE Form -->
...
<!-- BEGIN error -->
  <!-- フォームID : {formID} / エラー項目 : {errorKey} -->
<!-- END error -->
...
<!-- END_MODULE Form -->

<!-- 実行例 -->
<!-- フォームID : contactForm / エラー項目 : description,inquiry,name,email,zip,pref_code,address -->
{% set form = module('V2_Form') %}

{% if form.error %}
  <!-- フォームID : {{ form.error.formID }} / エラー項目 : {{ form.error.fields|join(', ') }} -->
{% endif %}

<!-- 実行例 -->
<!-- フォームID : contactForm / エラー項目 : description,inquiry,name,email,zip,pref_code,address -->

  • formID フォームIDの変数
  • errorKey | error.fields 入力エラーが起こったフィールド名

Google Analyticsとの連携

Google Analyticsにイベントトラッキングという仕組みがあり、これを使ってフォームの入力エラーをイベント通知する事ができます。(Google Analyticsの詳細は省略します)


<!-- BEGIN_MODULE Form -->
...
<!-- BEGIN error -->
<script type="text/javascript">
ga('send', 'event', 'Form', 'error', '{formID}', '{errorKey}');
</script>
<!-- END error -->
...
<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.error %}
<script type="text/javascript">
ga('send', 'event', 'Form', 'error', '{{ form.error.formID }}', '{{ form.error.fields|join(',') }}');
</script>
{% endif %}

フォームのエラー箇所を収集する事により、顧客がどこで悩んだりつまづいているのかが分かってきます。この情報をフォーム改善に役立てましょう。

入力ステップの分割表示


フォームでは、入力画面を複数のステップに分割できます。例えば、次のようなフォームを作成できます。

step 商品選択
 ↓
step#2 お客様情報
 ↓
step#confirm 確認画面
 ↓
step#result 送信結果画面

入力内容を段階的に取得したい場合や、長いフォームを分割したい場合に利用します。

複数ステップフォームの仕組み

フォームは現在のステップに応じて対応するブロックを表示します。

標準では以下のステップが用意されています。

ステップ(twig)

説明

step(step)

入力画面

step#reapply(step)

エラー時の再入力画面

step#confirm(confirm)

確認画面

step#result(result)

完了画面

複数ステップフォームでは、step#2step#hoge などの独自ステップを追加できます。

ステップの追加

任意のステップを追加するには、テンプレートに対応するブロックを追加します。

<!-- BEGIN step#2 -->
<h2>お客様情報</h2>

<form action="" method="post">
  ...
</form>
<!-- END step#2 -->
{% if form.step == '2' %}
  <h2>お客様情報</h2>

  <form action="" method="post">
    ...
  </form>
{% endif %}

ステップの移動

次のステップへ移動するには、step フィールドで遷移先を指定します。例では数値になっていますが任意の文字列を指定できます。


<input type="hidden" name="step" value="2">
<input type="hidden" name="step" value="2">

上記の場合、送信後に step#2 が表示されます。

入力内容の引き継ぎ

複数ステップフォームでは、前のステップで入力した内容を次のステップへ引き継ぐ必要があります。

そのために takeover を利用します。


<input type="hidden" name="takeover" value="{takeover}">
<input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />

takeover がない場合、前のステップで入力した内容は保持されません。


複数ステップフォームでは、各ステップのフォームに takeover を含めてください。


前のステップへ戻る

前のステップへ戻る場合は ACMS_POST_Form_Chain を利用します。


<form action="" method="post">
  <input type="hidden" name="takeover" value="{takeover}">
  <input type="hidden" name="step" value="reapply">
  <button type="submit" name="ACMS_POST_Form_Chain">戻る</button>
</form>
<form action="" method="post">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}">
  <!-- Twigの場合、修正画面専用のステップ(reapply)がないため入力画面に戻るには「step」を指定します -->
  <input type="hidden" name="step" value="step">
  <button type="submit" name="ACMS_POST_Form_Chain">戻る</button>
</form>

実装例

以下は 2 ステップのフォーム構成例です。

step 入力画面1
 ↓
step#2 入力画面2
 ↓
step#confirm 確認画面
 ↓
step#result 送信結果画面

<!-- BEGIN_MODULE Form -->
 
<!-- BEGIN step -->
<form action="" method="post"> 
  @include("/contact/form/input.html")
  <input type="hidden" name="step" value="2">
  <input type="hidden" name="error" value="" />
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{takeover}">
  <button type="submit"name="ACMS_POST_Form_Confirm">次へ</button>
</form>
<!-- END step -->

<!-- BEGIN step#2 -->
<form action="" method="post"> 
  @include("/contact/form/input2.html")
  <input type="hidden" name="step" value="confirm">
  <input type="hidden" name="error" value="2" />
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{takeover}">
  <button type="submit"name="ACMS_POST_Form_Confirm">確認画面へ</button>
</form>
<form action="" method="post">
  <input type="hidden" name="step" value="">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{takeover}">
  <button type="submit"name="ACMS_POST_Form_Chain">戻って修正</button>
</form>
<!-- END step#2 -->

<!-- BEGIN step#confirm -->
<form action="" method="post"> 
  @include("/contact/form/confirm.html")
  <input type="hidden" name="step" value="result">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{takeover}">
  <input type="hidden" name="To[]" value="{email}" />
  <input type="hidden" name="AdminReply-To[]" value="{email}" />
  <button type="submit"name="ACMS_POST_Form_Submit">送信</button>
</form>
<form action="" method="post">
  <input type="hidden" name="step" value="2">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{takeover}">
  <button type="submit"name="ACMS_POST_Form_Chain">戻って修正</button>
</form>
<!-- END step#confirm -->

<!-- BEGIN step#result -->
  <h2>送信完了</h2>
  ...
  @include("/contact/form/confirm.html")
<!-- END step#result -->

<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}
 
{% if form.step == 'step' %}
<form action="" method="post"> 
  {{ include('/contact/form/input.twig', form.fields) }}
  <input type="hidden" name="step" value="2">
  <input type="hidden" name="error" value="step" />
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <button type="submit"name="ACMS_POST_Form_Confirm">次へ</button>
</form>
{% endif %}

{% if form.step == '2' %}
<form action="" method="post"> 
  {{ include('/contact/form/input2.twig', form.fields) }}
  <input type="hidden" name="step" value="confirm">
  <input type="hidden" name="error" value="2" />
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <button type="submit"name="ACMS_POST_Form_Confirm">確認画面へ</button>
</form>
<form action="" method="post">
  <input type="hidden" name="step" value="step">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <button type="submit"name="ACMS_POST_Form_Chain">戻って修正</button>
</form>
{% endif %}

{% if form.step == 'confirm' %}
<form action="" method="post"> 
  {{ include('/contact/form/confirm.twig', form.fields) }}
  <input type="hidden" name="step" value="result">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <input type="hidden" name="To[]" value="{{ form.fields.email.value }}" />
  <input type="hidden" name="AdminReply-To[]" value="{{ form.fields.email.value }}" />
  <button type="submit"name="ACMS_POST_Form_Submit">送信</button>
</form>
<form action="" method="post">
  <input type="hidden" name="step" value="2">
  <input type="hidden" name="id" value="sample">
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <button type="submit"name="ACMS_POST_Form_Chain">戻って修正</button>
</form>
{% endif %}

{% if form.step == 'result' %}
  <h2>送信完了</h2>
  ...
  {{ include('/contact/form/confirm.twig', form.fields) }}
{% endif %}

サンクスページの表示

サンクスページを作ってコンバージョン率を分析できるようにする

フォームは1枚のテンプレート( HTML )でフォームの入力から送信結果までが全て完結できます。この状態だと、最初から最後まで単一のURLで画面遷移が行われてしまうため、Google Analytics等でコンバージョンを調べる際に、ゴールページを設定することができませんでした。 サンキューページ( 送信のお礼ページ )を別で用意して、フォームの送信が完了したら、そのページが表示されるようにします。

サンキューページを用意する

thanks.html ファイルを作成し、この中にサンキューページの内容を入れていきます。まず、結果表示( step#result )のブロックをこのthanks.htmlに持ってきます。これで、送信完了画面でこのthanks.htmlのテンプレートが使われても、送信結果が表示できるようになります。


Twigを利用する場合は、thanks.html ではなく thanks.html.twig のように .twig 拡張子を付けることをおすすめします。Twigテンプレートとして認識されるため、エディターによるシンタックスハイライトや補完機能を利用でき、テンプレートの編集がしやすくなります。


<!-- BEGIN_MODULE Form -->

<!-- BEGIN step#result -->
<section>
  <h2 class="contactH2">メールでのお問い合わせ</h2>
  <p class="message">お問い合わせありがとうございました。以下の内容で送信しました。</p>
  @include("/contact/form/confirm.html")
</section>
<!-- END step#result -->

<!-- END_MODULE Form -->
{% set form = module('V2_Form') %}

{% if form.step == 'result' %}
<section>
  <h2 class="contactH2">メールでのお問い合わせ</h2>
  <p class="message">お問い合わせありがとうございました。以下の内容で送信しました。</p>
  {{ include('/contact/form/confirm.twig', form.fields) }}
</section>
{% endif %}

確認ページからthanks.htmlに飛ぶようにする

確認ページにあるフォーム送信ボタンのformタグのactionにthanks.htmlに飛ぶように記述します。
フォームテンプレートの確認ボタンのactionを action="thanks.html" にしてください。


<!-- BEGIN step#confirm -->
<!-- フォームステップ:確認画面 -->
@include("/contact/form/confirm.html")
<form action="?step=reapply" method="post">
  <input type="hidden" name="step" value="reapply" />
  <input type="hidden" name="takeover" value="{takeover}" />
  <input type="submit" name="ACMS_POST_Form_Chain" value="入力画面へ戻る" />
</form>

<form action="thanks.html" method="post">
  <input type="hidden" name="To[]" value="{email}" />
  <input type="hidden" name="AdminReply-To[]" value="<{email}>" />
  <input type="hidden" name="step" value="result" />
  <input type="hidden" name="takeover" value="{takeover}" />
  <input type="hidden" name="id" value="contactForm" />
  <input type="submit" name="ACMS_POST_Form_Submit" value="送信" />
</form>
<!-- END step#confirm -->
{% if form.step == 'confirm' %}
<!-- フォームステップ:確認画面 -->
@include("/contact/form/confirm.html")
<form action="?step=reapply" method="post">
  <input type="hidden" name="step" value="reapply" />
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <input type="submit" name="ACMS_POST_Form_Chain" value="入力画面へ戻る" />
</form>

<form action="thanks.html" method="post">
  <input type="hidden" name="To[]" value="{{ form.fields.email.value }}" />
  <input type="hidden" name="AdminReply-To[]" value="{{ form.fields.email.value }}" />
  <input type="hidden" name="step" value="result" />
  <input type="hidden" name="takeover" value="{{ form.fields.takeover }}" />
  <input type="hidden" name="id" value="contactForm" />
  <input type="submit" name="ACMS_POST_Form_Submit" value="送信" />
</form>
{% endif %}

これで、完了ページを別URLで表示できるようになりました。

フォームからのファイルの添付


フォームからアップロードされたファイルを、管理者宛てのメールへ添付して送信できます。

必要な設定

ファイルをメールへ添付するには、以下の設定が必要です。

  • フォーム設定で「メールに添付する」を有効にする

  • form 要素に enctype="multipart/form-data" を指定する

  • ファイル選択項目に type="file" を指定する

画像ファイルをアップロードする場合は、あわせて以下の設定も必要です。

  • 「アップロード許可ファイル拡張子」に画像拡張子を追加する

メールへの添付を有効にする

フォーム管理 > ファイル添付から「メールに添付する」を有効にします。

有効にすると、フォームからアップロードされたファイルが管理者宛てメールに添付されます。

メールテンプレートに特別な設定は必要ありません。

ファイル添付オプションの有効化

ファイル添付オプションの有効化


form要素の設定

ファイルをアップロードする場合は、form 要素に enctype="multipart/form-data" を指定してください。

<form action="" method="post" enctype="multipart/form-data">

この設定がない場合、ファイルは送信されません。

ファイル選択項目を作成する

ファイル選択項目は type="file" を指定して作成します。

<input type="file" name="pdf">

画像ファイルをアップロードする場合も同様です。

<input type="file" name="image">

アップロードを許可する拡張子を設定する

画像ファイルをアップロードする場合は、コンフィグ > 編集設定の「アップロード許可ファイル拡張子」に対象の拡張子を追加してください。

png
jpg
jpeg
gif
webp

設定されていない拡張子はアップロードできません。

添付できる拡張子を制限する

フォームごとに、添付可能な拡張子を制限できます。

例えば PDF と ZIP のみ許可する場合は、以下のように指定します。

<input type="hidden" name="pdf@extension[]" value="pdf">
<input type="hidden" name="pdf@extension[]" value="zip">

複数の拡張子を許可する場合は、許可したい数だけ設定してください。

拡張子エラーの表示

許可されていない拡張子がアップロードされた場合は、以下のようにエラーメッセージを表示できます。


<!-- BEGIN pdf:v#extension -->
許可されていない拡張子です
<!-- END pdf:v#extension -->
{% if pdf.v.extension %}
許可されていない拡張子です
{% endif %}

添付ファイルのサイズを制限する

添付可能なファイルサイズを制限できます。(Ver. 2.6.1.4 以降で利用可能)

テンプレートで指定する

以下の例では 200KB を上限として設定しています。

<input type="hidden" name="pdf:v#filesize" value="200">

サイズは KB 単位で指定します。

管理画面で指定する

フォーム設定画面の「ファイルサイズ上限値」を設定することもできます。

フォームオプションの設定
フォームオプションの設定

サイズは KB 単位で指定します。

テンプレート上の設定だけでは、ブラウザの開発者ツールなどから値を書き換えられる可能性があります。そのため、運用時は管理画面側でも上限値を設定することをおすすめします。


サーバーの upload_max_filesizepost_max_size を超えるサイズのファイルはアップロードできません。フォーム側で設定した上限値よりも、PHP の設定値が優先されます。


エラーメッセージの記述方法

指定した容量を超えた場合や、upload_max_filesizeを超えた場合のブロック


<!-- BEGIN pdf:v#filesize -->
ファイルサイズが大きすぎます
<!-- END pdf:v#filesize -->
{%if pdf.v.filesize %}
ファイルサイズが大きすぎます
{% endif %}

post_max_sizeを超えた場合のメッセージブロック(全体)

upload_max_filesize超えた場合、POSTが空になるのでフィールド毎にエラーは表示できません。 なので、以下の記述で全体のエラーメッセージを出力します。

<!-- BEGIN post:v#filesize -->リクエストサイズが大きすぎます<!-- END post:v#filesize -->

この特殊なエラーブロックは、標準テンプレートのみ対応しており、twig記法では出力できません。


ソースコードの例

以下は、変数名がpdfだった場合のソースコードの例です。


<tr>
  <th>PDF</th>
  <td>
    <!-- アップロード済みのファイルのプレビューエリア -->
    <!-- BEGIN_IF [{pdf@path}/nem/] -->
    <img src="%{ARCHIVES_DIR}{pdf@path}" width="450" alt="" /><br />
    <a href="%{ARCHIVES_DIR}{pdf@path}">{pdf@originalName}</a>
    <input type="hidden" name="pdf@old" value="{pdf@path}" />
    <input type="hidden" name="pdf@secret" value="{pdf@secret}" />
    <input type="hidden" name="pdf@originalName" value="{pdf@originalName}" />
    <label for="input-checkbox-pdf@edit">
      <input type="checkbox" name="pdf@edit" value="delete" id="input-checkbox-pdf@edit" />
      削除
    </label><br />
    <!-- END_IF -->

    <!-- ファイルをアップロードするフィールド -->
    <input type="hidden" name="pdf:v#filesize" value="500" id="pdf-v-filesize"> <!-- 500KBで制限 -->
    <input type="file" name="pdf" size="20" />
    <input type="hidden" name="field[]" value="pdf" />
    <input type="hidden" name="pdf:extension" value="file" />
    <input type="hidden" name="pdf@extension[]" value="pdf" />

    <!-- エラーメッセージ -->
    <div data-validator-label="pdf-v-filesize" class="validator-result-{pdf:v#filesize}">
      <p class="error-text"><span class="acms-icon acms-icon-attention"></span>ファイルサイズが大きすぎます。</p>
    </div>
    <div data-validator-label="pdf-v-extension" class="validator-result-{pdf:v#extension}">
      <p class="error-text"><span class="acms-icon acms-icon-attention"></span>許可されていない拡張子です。</p>
    </div>
  </td>
</tr>

<!-- BEGIN post:v#filesize -->リクエストサイズが大きすぎます<!-- END post:v#filesize -->
<tr>
  <th>PDF</th>
  <td>
    <!-- アップロード済みのファイルのプレビューエリア -->
    {% if pdf.value.path %}
    <img src="{{ pdf.value.path }}" width="450" alt="" /><br />
    <a href="{{ pdf.value.path }}">{{ pdf.value.originalName }}</a>
    <input type="hidden" name="pdf@old" value="{{ pdf.value.path }}" />
    <input type="hidden" name="pdf@secret" value="{{ pdf.value.secret }}" />
    <input type="hidden" name="pdf@originalName" value="{{ pdf.value.originalName }}" />
    <label for="input-checkbox-pdf@edit">
      <input type="checkbox" name="pdf@edit" value="delete" id="input-checkbox-pdf@edit" />
      削除
    </label><br />
    {% endif %}

    <!-- ファイルをアップロードするフィールド -->
    <input type="hidden" name="pdf:v#filesize" value="500" id="pdf-v-filesize"> <!-- 500KBで制限 -->
    <input type="file" name="pdf" size="20" />
    <input type="hidden" name="field[]" value="pdf" />
    <input type="hidden" name="pdf:extension" value="file" />
    <input type="hidden" name="pdf@extension[]" value="pdf" />

    <!-- エラーメッセージ -->
    <div data-validator-label="pdf-v-filesize" class="validator-result-{{ pdf.v.filesize ? '0' : '1' }}">
      <p class="error-text"><span class="acms-icon acms-icon-attention"></span>ファイルサイズが大きすぎます。</p>
    </div>
    <div data-validator-label="pdf-v-extension" class="validator-result-{{ pdf.v.extension ? '0' : '1' }}">
      <p class="error-text"><span class="acms-icon acms-icon-attention"></span>許可されていない拡張子です。</p>
    </div>
  </td>
</tr>

変数名

ここではファイル添付をした時に使用できる変数名を解説します。以下変数名が「pdf」だった場合で解説します。


標準テンプレート Twig 出力される内容
{pdf@path} {{ pdf.value.path }} ファイルが実態があるURLです。ファイル名なランダムなものになっています。
{pdf@originalName} {{ pdf.vlaue.orginalName }} 元のファイル名です。ダウンロード時のファイル名も元のファイル名が使用されます。
{pdf@secret} {{ pdf.value.secret }} セキュリティのためのランダム文字列です。

動的フォームの基本

動的フォームはエントリーページに設置することができます。動的フォームはHTMLの知識のない人でもフォームを設置できる仕組みになっています。例えば採用ページのエントリーを書いて、更新者がそのページに採用フォームをつけることができます。

フォームでは以下のような種類のフォームパーツが用意されています。

  • テキスト
  • テキストエリア
  • ラジオ
  • セレクト
  • チェックボックス

動的フォームの導入方法

動的フォームはコンフィグ管理の機能設定から機能を有効にすることができます。動的フォーム項目の動的フォームを利用可能にするにチェックをしてください。


動的フォームの有効化

動的フォームの有効化


エントリーの詳細ページを見てみるとエントリー管理ボタンのところに[フォーム]というボタンが追加されています。このボタンを押してエントリーに動的フォームを作っていきます。


動的フォームの編集ボタン

動的フォームの編集ボタン


動的フォーム作成画面ではエントリーのユニットと同じようにフォームのパーツが追加できます。ここにはフォームIDを紐づけるフォームセットという項目があります。こちらにフォームIDを設定していきます。次は動的フォーム用のフォームIDの作り作り方について解説します。


動的フォーム編集画面

動的フォーム編集画面


フォームIDを作成

フォームIDは通常のフォームと同じようにフォーム管理の[フォームIDを作成]ボタンから作っていきます。 フォームID、フォーム名、一般のメールテンプレート、管理者のメールテンプレート、管理者のメールアドレスを設定していきます。

メールテンプレートのパスについて

動的フォームのメールテンプレートはsystemのテーマフォルダに用意されています。通常のフォームのメールテンプレートは自分で自由にレイアウトができますが、動的フォームでは自由にレイアウトなどカスタマイズができません。動的フォームのメールテンプレートのパスは以下のようになります。

SubjectTpl/include/form/subject.txt
BodyTpl/include/form/body.txt
AdminSubjectTpl/include/form/adminsubject.txt
AdminBodyTpl/include/form/adminbody.txt

上記は /themes/system/include/ 以下に存在する各ファイルとなりますが、実際に使用する場合には本文など適宜カスタマイズが必要になるため、使用するテーマディレクトリへのコピーをしてカスタマイズ・利用をすることをお勧めします。
一例として、 /themes/使用テーマディレクトリ/recruit/form/ 以下に各ファイルをコピーしカスタマイズしたものを使用する場合の設定画面は以下のようになります。他の内容に動的フォームを使いたい場合には、 /themes/使用テーマディレクトリ/aaaaa/form/ のようにもう1セットコピーして利用すれば、各フォームに合わせたメールテンプレートが使用できます。


フォームID作成画面

フォームID作成画面


動的フォーム画面からフォームIDをセット

動的フォームを設置したいエントリーに戻り、[フォーム]ボタンを押して動的フォーム作成画面で先ほど作成したフォームIDを設定してください。動的フォームで送信されたデータはこのフォームIDに蓄積されていきます。

動的フォームの項目を追加

フォームのパーツはテキスト、テキストエリア、ラジオ、セレクト、チェックボックスを追加することができます。フォームのパーツはエントリーのユニットと同じように項目を追加していってください。


動的フォーム編集ボタン

動的フォーム編集ボタン


[フォーム]ボタンを押すとフォームの編集画面に移動します。ここからテキスト、テキストエリア、ラジオ、セレクト、チェックボックスなどフォームの項目を追加することができます。


動的フォーム編集画面

動的フォーム編集画面


ラベルフォームの項目名{label}
説明このフォームユニットの説明{caption}

バリデータとコンバーターを使う

[入力チェック]のリンクをクリックすることでフォームの項目を必須にしたり、文字数制限をしたり、文字を変換したり設定することができます。フォームのバリデータとコンバーターの設定について一部ご紹介していきます。

必須にする

項目はrequiredを選択します。メッセージにエラーメッセージを入力してください。


必須入力

必須入力


数値になっているかチェック

項目はdigitsを選択します。メッセージにエラーメッセージを入力してください。


数値かチェック

数値かチェック


入力文字数を制限する

項目はminLengthか、maxLengthを選択します。値には制限したい文字数を入力し、メッセージにエラーメッセージを入力してください。


文字数のチェック

文字数のチェック


入力した文字を変換する

入力の変換 ( converter )を選択し、値に変換したい種類を入力してください。コンバーターの変換種類についてはリファレンスのconverter ( c )の項目を御参考ください。


「全角カタカナ」を「半角カタカナ」に変換

「全角カタカナ」を「半角カタカナ」に変換


1つのフォーム項目に複数のオプションを設定することができます。フォームの項目を保存するとエントリーに動的フォームが設置されました。


動的フォーム完成例

動的フォーム完成例


標準提供のテンプレートの中には、説明 {caption} が使われておりません。入力した内容を表示させる際には、テンプレートのカスタマイズが必要です。

動的フォームのためのテンプレート

動的フォームのテンプレートはメールのテンプレート、入力フォームと入力確認画面のテンプレートがあります。フォームの項目は動的に出力されるため自由なカスタマイズはできないのですが、文面や署名などはテンプレートから変更することができます。

テンプレートについて

テンプレートはsystemテーマに置いてあります。変更するときはご利用しているテーマ内にコピーしてきてください。 /themes/利用中のテーマ/include/form/adminsubject.txt

メールのテンプレート

管理者宛メールの件名

/themes/system/include/form/adminsubject.txt

管理者宛メールの本文

/themes/system/include/form/adminbody.txt

一般宛メールの件名

/themes/system/include/form/subject.txt

一般宛メールの本文

/themes/system/include/form/body.txt

入力フォームと入力確認画面のテンプレート

formタグや入力フォームと入力確認画面のテンプレートを読み込んでいます

/themes/system/include/form/unit.html

完了画面のテンプレートは、デフォルトだと「thanks.html」が指定されています

/bid/%{BID}/eid/%{EID}/tpl/thanks.html

この時、URLコンテキスト「tpl」によって、thanks.html を指定していることによって、Ver. 2.11.25 以上をお使いの場合は、そのままでは動きません。 「private/config.system.yaml」の allow_tpl_path に 「thanks.html」を指定ください。これはセキュリティ上の仕様変更によるものになります。詳細

allow_tpl_path: [thanks.html]

入力フォームのテンプレート

/themes/system/include/form/input.html

入力確認画面のテンプレート

/themes/system/include/form/confirm.html

メールの署名を変更

メールの署名は /themes/system/include/form/adminbody.txt と /themes/system/include/form/body.txt に記述されています。ご利用のテーマにコピーしてきて署名を変更します。  
/themes/ご利用テーマ/include/form/body.txt

%{BLOG_NAME}

〒000-0000
○○県○○○市○○区 ××の××の××
電話番号: 123-456-7890
E-mail: ■■■@■■■■.■■

動的フォームの動的項目と静的項目の共存

動的フォームの入力フォームと確認画面のテンプレートをカスタマイズすることでHTMLのカスタムフィールドを埋め込むこともできます。例えば、お名前のフォーム項目は必ずフォームに必要だから予め固定のカスタムフィールドにするだとか、都道府県の項目はいれたいけど都道府県を入力フォームから入れていくのは大変だったりします。動的フォームの項目を一部HTMLで記述されたカスタムフィールドにすることができます。

HTMLで記述されたカスタムフィールドを埋め込む

動的フォームにHTMLで記述されたカスタムフィールドを埋め込むときは動的フォームパーツの上か下に埋め込むことになります。動的フォームのパーツの間にHTMLのカスタムフィールドを埋め込むことができず、順番を自由に設定することはできません。
例えば都道府県のHTMLのカスタムフィールドを埋め込んでみましょう。

入力フォームに埋め込む

動的フォームの入力フォームのテンプレート /themes/system/include/form/input.html をご利用のテーマにコピーしてきます。
/themes/ご利用のテーマ/include/form/input.html

Form2_Unitモジュールのcolumn:loopの外にHTMLで記述されたカスタムフィールドを記述してください。

<tr>
  <th>都道府県</th>
  <td>
  <select class="formSelect" name="pref_code">
    <option value="" selected="selected">選択してください ▼</option>
    <option value="北海道"\{pref_code:selected#北海道\}>北海道</option>
      
    <option value="青森県"\{pref_code:selected#青森県\}>青森県</option>
    <option value="岩手県"\{pref_code:selected#岩手県\}>岩手県</option>
    <option value="宮城県"\{pref_code:selected#宮城県\}>宮城県</option>
    <option value="秋田県"\{pref_code:selected#秋田県\}>秋田県</option>
    <option value="山形県"\{pref_code:selected#山形県\}>山形県</option>
    <option value="福島県"\{pref_code:selected#福島県\}>福島県</option>
    <option value="茨城県"\{pref_code:selected#茨城県\}>茨城県</option>
    <option value="栃木県"\{pref_code:selected#栃木県\}>栃木県</option>
    <option value="群馬県"\{pref_code:selected#群馬県\}>群馬県</option>
      
    <option value="埼玉県"\{pref_code:selected#埼玉県\}>埼玉県</option>
    <option value="千葉県"\{pref_code:selected#千葉県\}>千葉県</option>
    <option value="東京都"\{pref_code:selected#東京都\}>東京都</option>
    <option value="神奈川県"\{pref_code:selected#神奈川県\}>神奈川県</option>
    <option value="新潟県"\{pref_code:selected#新潟県\}>新潟県</option>
    <option value="富山県"\{pref_code:selected#富山県\}>富山県</option>
    <option value="石川県"\{pref_code:selected#石川県\}>石川県</option>
    <option value="福井県"\{pref_code:selected#福井県\}>福井県</option>
    <option value="山梨県"\{pref_code:selected#山梨県\}>山梨県</option>
      
    <option value="長野県"\{pref_code:selected#長野県\}>長野県</option>
    <option value="岐阜県"\{pref_code:selected#岐阜県\}>岐阜県</option>
    <option value="静岡県"\{pref_code:selected#静岡県\}>静岡県</option>
    <option value="愛知県"\{pref_code:selected#愛知県\}>愛知県</option>
    <option value="三重県"\{pref_code:selected#三重県\}>三重県</option>
    <option value="滋賀県"\{pref_code:selected#滋賀県\}>滋賀県</option>
    <option value="京都府"\{pref_code:selected#京都府\}>京都府</option>
    <option value="大阪府"\{pref_code:selected#大阪府\}>大阪府</option>
    <option value="兵庫県"\{pref_code:selected#兵庫県\}>兵庫県</option>
      
    <option value="奈良県"\{pref_code:selected#奈良県\}>奈良県</option>
    <option value="和歌山県"\{pref_code:selected#和歌山県\}>和歌山県</option>
    <option value="鳥取県"\{pref_code:selected#鳥取県\}>鳥取県</option>
    <option value="島根県"\{pref_code:selected#島根県\}>島根県</option>
    <option value="岡山県"\{pref_code:selected#岡山県\}>岡山県</option>
    <option value="広島県"\{pref_code:selected#広島県\}>広島県</option>
    <option value="山口県"\{pref_code:selected#山口県\}>山口県</option>
    <option value="徳島県"\{pref_code:selected#徳島県\}>徳島県</option>
    <option value="香川県"\{pref_code:selected#香川県\}>香川県</option>
      
    <option value="愛媛県"\{pref_code:selected#愛媛県\}>愛媛県</option>
    <option value="高知県"\{pref_code:selected#高知県\}>高知県</option>
    <option value="福岡県"\{pref_code:selected#福岡県\}>福岡県</option>
    <option value="佐賀県"\{pref_code:selected#佐賀県\}>佐賀県</option>
    <option value="長崎県"\{pref_code:selected#長崎県\}>長崎県</option>
    <option value="熊本県"\{pref_code:selected#熊本県\}>熊本県</option>
    <option value="大分県"\{pref_code:selected#大分県\}>大分県</option>
    <option value="宮崎県"\{pref_code:selected#宮崎県\}>宮崎県</option>
    <option value="鹿児島県"\{pref_code:selected#鹿児島県\}>鹿児島県</option>
      
    <option value="沖縄県"\{pref_code:selected#沖縄県\}>沖縄県</option>
  </select>
  <input type="hidden" name="field[]" value="pref_code" />
  </td>
</tr>

HTMLで記述されたカスタムフィールドの都道府県が追加されました。カスタムフィールドの変数が認識されるように変数の前にバックスラッシュ(\)でエスケープをします。



確認画面に項目を追加する

フォームの確認画面にも追加したHTMLのカスタムフィールドを追加してください。
Form2_Unitモジュールのcolumn:loopの外にHTMLで記述されたカスタムフィールドを追加します。
/themes/ご利用のテーマ/include/form/confirm.html

先ほど追加した都道府県の場合は以下のようになります。こちらもカスタムフィールドの変数にエスケープして記述します。

<tr>
  <th>都道府県</th>
  <td>\{pref_code\}</td>
</tr>

メールのテンプレートに項目を追加する

入力フォームと確認画面にHTMLで記述されたカスタムフィールドを追加してきました。追加したHTMLで記述されたカスタムフィールドの変数をメールのテンプレートにも記述する必要があります。メールのテンプレートもご利用のテーマにコピーしてきてからカスタマイズをしてください。

/themes/ご利用のテーマ/include/form/body.txt
/themes/ご利用のテーマ/include/form/adminbody.txt

追加する場所はForm2_Unitモジュールの外に追加してください。
メールのテンプレートはカスタムフィールドの変数にエスケープは必要ありません。

メールアドレス  : {email}<!-- BEGIN_MODULE Form2_Unit -->
<!-- BEGIN column:loop --><!-- BEGIN text -->
{label}  : \{form-unit-{utid}\}<!-- END text --><!-- BEGIN textarea -->
{label}  : \{form-unit-{utid}\}<!-- END textarea --><!-- BEGIN radio -->
{label}  : \{form-unit-{utid}\}<!-- END radio --><!-- BEGIN select -->
{label}  : \{form-unit-{utid}\}<!-- END select --><!-- BEGIN checkbox -->
{label}  : <!-- BEGIN\ form-unit-{utid}:loop -->\{form-unit-{utid}\} <!-- END\ form-unit-{utid}:loop --><!-- END checkbox -->
<!-- END column:loop --><!-- END_MODULE Form2_Unit -->
都道府県  : {pref_code}

このような方法で動的フォームにHTMLで記述されたカスタムフィールドを埋め込むことができます。

補足

ver 2.6.1.0よりradio,select,checkboxのループ内にて項目の連番変数 {i} を出力するように追加されました。
下記サンプルコードを参考にしてください。内容は一部抜粋しています。

 <!-- BEGIN radio -->
 <tr>
  <th><label>{label}</label></th>
  <td class="acms-radio">
   <!-- BEGIN radio#val:loop -->
   <label class="acms-form-radio"><input type="radio" name="form-unit-{utid}" value="{value}"\{form-unit-{utid}:checked#{value}\}>
   <i class="acms-ico-radio"></i>
   {value}:{i}
   </label><!-- END radio#val:loop -->
  </td>
 </tr><!-- END radio -->

メールでの文字コード指定

CMS Ver. 3.0.24で ISO-2022-JP 文字コードを廃止したため、UTF-8 のみとなりました。詳しくは Ver. 3.0.24 フィックスバージョンリリースのお知らせ をご覧ください。

ここでは、フォームでのメールで使用される文字コードの指定方法をみていきます。

本文の文字コード

本文の文字コードは、管理ページ > フォーム > フォーム詳細 の 文字コード(テキストメール)で設定します。

よく使われる文字コード

  • ISO-2022-JP 古くから電子メールなどで使われている文字コード。JISコードとも呼ばれる。
  • UTF-8 多言語対応するならこの文字コードを指定ください。

文字コード変換

CMS Ver. 3.0.24で ISO-2022-JP 文字コードを廃止したため、UTF-8 のみとなりました。詳しくは Ver. 3.0.24 フィックスバージョンリリースのお知らせ をご覧ください。

フォームのメール送信で、文字コードにISO-2022-JPなどを指定すると、表現できる文字数がUTF-8などに比べると少ないため、表示できない文字ができてます。

そこで、送信時にUTF-8からISO-2022-JPなどに変換するときに、存在しない文字を別の文字に置き換える仕組みを利用して、文字化けする文字を少なくしましょう。

設定ファイル

以下の命名規則をもつファイルを作成します。

/private/const/mail/[小文字の文字コード名].php

ISO-2022-JPの場合は、デフォルトで用意されています。

<?php
// UTF-8 → ISO-2022-JP
$const  = array(
/* --- 0x2100 - 0x2138 (文字種記号) --- */
// 0x2100 - 0x210F
"\xE2\x80\xA2" => "・",
"\xE2\x84\x80" => "a/c",
"\xE2\x84\x81" => "a/s",
...

変換例

例えば、UTF-8の㈱はISO-2022-JPで文字化けします。以下のような変換テーブルを書くと㈱を(株)のように3文字を使ったものに変換するので、文字化けを防ぐ事ができます。

...
"\xE3\x88\xB1" => "(株)",
...

JavaScriptによるバリデート

これまでバリデーターは、フォームに入力された内容を、サーバーに送信するとサーバーからのレスポンスとしてエラー結果が返ってくるものでした。

そこで今回は、a-blog cmsに標準で搭載されているJavaScriptを利用したバリデーター機能を利用してみたいと思います。

JavaScriptバリデーターの利点として、エンドユーザーのブラウザ側でエラーを判定するため、エラーがあったときのレスポンスが高速になるというメリットがあります。また、サーバーに余分な負荷をかけずに済むというメリットも挙げられます。

必要な作業

  1. a-blog cmsが標準で搭載しているJavaScript(acms.js)の読み込み
  2. 場合によってCSSにスタイルの追記作業
  3. この機能を使うためのクラスを付与
  4. エラーメッセージの記述を書き換え

通常のバリデーターも動かした上でJavaScriptバリデーターを動かすので、JavaScriptがOFFの環境でもエラー処理が動きます。

実装

まずは、組み込みJSを使うためにacms.jsを読み込みます。読み込みについては、こちらを参考ください。 読み込みが必要なJavascriptファイル

CSSを追記する

デフォルトの設定では、a-blog cmsのシステムのスタイルに組み込み済みですので、特に設定していただかなくても動きます。クラスを変更する場合や、スタイルを調整する場合は以下を参考に書き換えてください。

/* エラーメッセージ非表示時のスタイル */
.validator-result-,
.validator-result-1,
.v-result-,
.v-result-1 {
  display: none;
}

/* エラーメッセージ表示時のスタイル */
.validator-result-error,
.validator-result-0,
.v-result-error,
.v-result-0 {
  display: block;
  color: #F00;
}

クラスの付与

フォームでJavaScriptバリデーターを使用できるようにするために、以下のクラスをフォームに振ります。

<form action="" method="post" class="js-validator" enctype="multipart/form-data">
...
</form>

エラーメッセージの記述を書き換える

今までのエラーメッセージの記述


<th>ハンドルネーム (必須)</th>
<td>
  <input type="text" name="name" value="{name}">
  <input type="hidden" name="field[]" value="name">
  <input type="hidden" name="name:validator#required">
  <!-- BEGIN name:validator#required -->
  <p class="notice">ハンドルネームは必須項目です</p>
  <!-- END name:validator#required -->
</td>
<th>ハンドルネーム (必須)</th>
<td>
  <input type="text" name="name" value="{{ name.value }}">
  <input type="hidden" name="field[]" value="name">
  <input type="hidden" name="name:validator#required">
  {% if name.v.required %}
  <p class="notice">ハンドルネームは必須項目です</p>
  {% endif %}
</td>

JavaScriptバリデーターのエラーメッセージの記述


<th>ハンドルネーム (必須)</th>
<td>
  <input type="text" name="name" value="{name}">
  <input type="hidden" name="field[]" value="name">
  <input type="hidden" name="name:validator#required" id="name-v-required">
  <label for="name-v-required" class="validator-result-{name:validator#required}">
    ハンドルネームは必須項目です
  </label>
</td>
<th>ハンドルネーム (必須)</th>
<td>
  <input type="text" name="name" value="{{ name.value }}">
  <input type="hidden" name="field[]" value="name">
  <input type="hidden" name="name:validator#required" id="name-v-required">
  <label for="name-v-required" class="validator-result-{{ name.v.required ? '0' : '1' }}">
    ハンドルネームは必須項目です
  </label>
</td>

5行目id="name-v-required" を追加
6行目テンプレートタグのブロックから、label要素( classとfor属性も必須 )に変更

validator指定している要素のidと、その要素に対するエラーメッセージのラベルのfor属性を一致させてください。

JavaScriptが利用するための記述を加える事で、エラー時にlabel要素のclass名が書き換えられます。それにより、表示/非表示のCSSが操作されることでエラーメッセージとして動作します。

初期の入力画面( step )にも、再入力画面( step#reapply )と同様に サーバーに送信される前の動作なので、初期の入力画面でもエラーメッセージが表示される必要があります。再入力画面( step#reaply )と同じように書き換えましょう。インクルード機能を使い同じテンプレートを使う事をお勧めします。

組み込みJSの設定

以下のような設定が/js/config.jsで設定できます。

設定項目説明デフォルト値
validatorFormMarkバリデーターを使うform要素のセレクター'form.js-validator'
validatorResultClassエラーメッセージ要素につけるクラス'validator-result-'
validatorOkClassバリデートにパスした時につけるクラス'valid'
validatorNgClassバリデートに引っかかった場合につけるクラス'invalid'

validatorOkClassvalidatorNgClassは 該当する data-validator="フィールド名" が付与されている要素に、バリデートした結果に対して対応するクラスを付与します。

さあ、確認してみましょう

一通り編集し終わったら、動作を確認してみましょう。

JavaScriptバリデーターを利用すると画面遷移なしで即座にエラーを表示できるため、エンドユーザーに対するレスポンス向上につながります。記述は若干多くなりますが、積極的に利用してみてください。

JavaScriptバリデーターを実装したサンプルコード


<h3>お問い合わせ情報</h3>
<div class="entry-container">
<table class="contact-form">
  <tr>
    <th>
      <label for="description">ご用件</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="description">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
  
      <select id="description" class="form-select" name="description[]">
        <option value="" selected="selected">選択してください</option>
        <option value="ご質問"{description:selected#ご質問}>ご質問</option>
        <option value="ご要望"{description:selected#ご要望}>ご要望</option>
        <option value="資料請求"{description:selected#資料請求}>資料請求</option>
        <option value="その他"{description:selected#その他}>その他</option>
      </select>
      <input type="hidden" name="field[]" value="description">
      <input type="hidden" name="description:v#required" id="description-v">

      <label for="description-v" class="validator-result-{description:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お問い合わせ種類を選択してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th>
      <label for="inquiry">お問い合わせ内容</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="inquiry">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <textarea id="inquiry" name="inquiry" rows="5" class="acms-form-width-full" placeholder="お問い合わせ内容を入力してください。" data-validator="inquiry">{inquiry}</textarea>
      <input type="hidden" name="field[]" value="inquiry">
      <input type="hidden" name="inquiry:v#required" id="inquiry-v-required">
      <input type="hidden" name="inquiry:c" value="KV">

      <label for="inquiry-v-required" class="validator-result-{inquiry:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お問い合わせ内容を入力してください。</p>
      </label>
    </td>
  </tr>
</table>
</div>

<h3>お客様情報</h3>
<div class="entry-container">
<table class="contact-form h-adr">
  <tr>
    <th><label for="organization">会社名</label></th>
    <td>
      <input id="organization" type="text" name="organization" autocomplete="organization" value="{organization}" class="acms-form-width-full" placeholder="株式会社サンプルサイト">
      <input type="hidden" name="field[]" value="organization">
      <input type="hidden" name="organization:c" value="KV">
    </td>
  </tr>
  <tr>
    <th>
      <label for="name">お名前</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="name">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <input id="name" type="text" name="name" autocomplete="name" class="acms-form-width-full" value="{name}" placeholder="山田 太郎" data-validator="name">
      <input type="hidden" name="field[]" value="name">
      <input type="hidden" name="name:v#required" id="name-v-required">
      <input type="hidden" name="name:c" value="KV">

      <label for="name-v-required" class="validator-result-{name:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お名前を入力してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th>
      <label for="email">メールアドレス</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="email">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <input id="email" type="email" name="email" autocomplete="email" value="{email}" class="acms-form-width-full" placeholder="info@example.com" data-validator="email">
      <input type="hidden" name="field[]" value="email">
      <input type="hidden" name="email:v#required" id="email-v-required">
      <input type="hidden" name="email:v#email" id="email-v-email">
      <input type="hidden" name="email:c" value="a">

      <label for="email-v-required" class="validator-result-{name:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>メールアドレスを入力してください。</p>
      </label>
      <label for="email-v-email" class="validator-result-{name:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>正しいメールアドレスを入力してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th><label for="tel">お電話番号</label></th>
    <td>
      <input id="tel" type="tel" name="tel" autocomplete="tel" value="{tel}" size="12" class="acms-form-width-full" placeholder="000-000-0000">
      <input type="hidden" name="field[]" value="tel">
      <input type="hidden" name="tel:c" value="n">
    </td>
  </tr>
  <tr>
    <th><label for="address">ご住所</label><span class="label-required">必須</span></th>
    <td>
      <script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
      <span class="p-country-name" style="display:none;">Japan</span>
      <div class="acms-form-group">
        〒<input type="text" name="postal-code" autocomplete="postal-code" value="{postal-code}" id="postal-code" class="acms-form-width-mini p-postal-code" size="8" maxlength="7" placeholder="0000000" data-validator="postal-code">
        <input type="hidden" name="field[]" value="postal-code">
        <input type="hidden" name="postal-code:c" value="a">

        <select class="form-select p-region" name="address-level1" autocomplete="address-level1">
          <option value="" selected="selected">都道府県</option>
          <option value="北海道"{address-level1:selected#北海道}>北海道</option>

          <option value="青森県"{address-level1:selected#青森県}>青森県</option>
          <option value="岩手県"{address-level1:selected#岩手県}>岩手県</option>
          <option value="宮城県"{address-level1:selected#宮城県}>宮城県</option>
          <option value="秋田県"{address-level1:selected#秋田県}>秋田県</option>
          <option value="山形県"{address-level1:selected#山形県}>山形県</option>
          <option value="福島県"{address-level1:selected#福島県}>福島県</option>
          <option value="茨城県"{address-level1:selected#茨城県}>茨城県</option>
          <option value="栃木県"{address-level1:selected#栃木県}>栃木県</option>
          <option value="群馬県"{address-level1:selected#群馬県}>群馬県</option>

          <option value="埼玉県"{address-level1:selected#埼玉県}>埼玉県</option>
          <option value="千葉県"{address-level1:selected#千葉県}>千葉県</option>
          <option value="東京都"{address-level1:selected#東京都}>東京都</option>
          <option value="神奈川県"{address-level1:selected#神奈川県}>神奈川県</option>
          <option value="新潟県"{address-level1:selected#新潟県}>新潟県</option>
          <option value="富山県"{address-level1:selected#富山県}>富山県</option>
          <option value="石川県"{address-level1:selected#石川県}>石川県</option>
          <option value="福井県"{address-level1:selected#福井県}>福井県</option>
          <option value="山梨県"{address-level1:selected#山梨県}>山梨県</option>

          <option value="長野県"{address-level1:selected#長野県}>長野県</option>
          <option value="岐阜県"{address-level1:selected#岐阜県}>岐阜県</option>
          <option value="静岡県"{address-level1:selected#静岡県}>静岡県</option>
          <option value="愛知県"{address-level1:selected#愛知県}>愛知県</option>
          <option value="三重県"{address-level1:selected#三重県}>三重県</option>
          <option value="滋賀県"{address-level1:selected#滋賀県}>滋賀県</option>
          <option value="京都府"{address-level1:selected#京都府}>京都府</option>
          <option value="大阪府"{address-level1:selected#大阪府}>大阪府</option>
          <option value="兵庫県"{address-level1:selected#兵庫県}>兵庫県</option>

          <option value="奈良県"{address-level1:selected#奈良県}>奈良県</option>
          <option value="和歌山県"{address-level1:selected#和歌山県}>和歌山県</option>
          <option value="鳥取県"{address-level1:selected#鳥取県}>鳥取県</option>
          <option value="島根県"{address-level1:selected#島根県}>島根県</option>
          <option value="岡山県"{address-level1:selected#岡山県}>岡山県</option>
          <option value="広島県"{address-level1:selected#広島県}>広島県</option>
          <option value="山口県"{address-level1:selected#山口県}>山口県</option>
          <option value="徳島県"{address-level1:selected#徳島県}>徳島県</option>
          <option value="香川県"{address-level1:selected#香川県}>香川県</option>

          <option value="愛媛県"{address-level1:selected#愛媛県}>愛媛県</option>
          <option value="高知県"{address-level1:selected#高知県}>高知県</option>
          <option value="福岡県"{address-level1:selected#福岡県}>福岡県</option>
          <option value="佐賀県"{address-level1:selected#佐賀県}>佐賀県</option>
          <option value="長崎県"{address-level1:selected#長崎県}>長崎県</option>
          <option value="熊本県"{address-level1:selected#熊本県}>熊本県</option>
          <option value="大分県"{address-level1:selected#大分県}>大分県</option>
          <option value="宮崎県"{address-level1:selected#宮崎県}>宮崎県</option>
          <option value="鹿児島県"{address-level1:selected#鹿児島県}>鹿児島県</option>

          <option value="沖縄県"{address-level1:selected#沖縄県}>沖縄県</option>
        </select>
        <input type="hidden" name="field[]" value="address-level1">
      </div>
      <textarea id="address" name="address" rows="2" class="acms-form-width-full p-locality p-street-address p-extended-address" data-validator="address">{address}</textarea>
      <input type="hidden" name="field[]" value="address">
      <input type="hidden" name="postal-code:v#required" id="postal-code-v-required">
      <input type="hidden" name="postal-code:v#regex" value="^[\d]\{7\}$" id="postal-code-v-regex">
      <input type="hidden" name="address-level1:v#required" id="address-level1-v-required">
      <input type="hidden" name="address:v#required" id="address-v-required">
      <input type="hidden" name="address:c" value="KV">

      <label for="postal-code-v-required" class="validator-result-{postal-code:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>郵便番号が入力されていません。</p>
      </label>
      <label for="postal-code-v-regex" class="validator-result-{postal-code:v#regex}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>郵便番号はハイフンなしの数値7桁で入力してください。</p>
      </label>
      <label for="address-level1-v-required" class="validator-result-{address-level1:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>都道府県が選択されていません。</p>
      </label>
      <label for="address-v-required" class="validator-result-{address:v#required}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>住所が入力されていません。</p>
      </label>
    </td>
  </tr>
</table>
</div>
<h3>お問い合わせ情報</h3>
<div class="entry-container">
<table class="contact-form">
  <tr>
    <th>
      <label for="description">ご用件</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="description">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <select
        id="description"
        class="form-select"
        name="description[]"
        data-validator="description"
      >
        <option value="">選択してください</option>
        <option value="ご質問" {{ description.value|selected('ご質問') }}>ご質問</option>
        <option value="ご要望" {{ description.value|selected('ご要望') }}>ご要望</option>
        <option value="資料請求" {{ description.value|selected('資料請求') }}>資料請求</option>
        <option value="その他" {{ description.value|selected('その他') }}>その他</option>
      </select>
      <input type="hidden" name="field[]" value="description" />
      <input type="hidden" name="description:v#required" id="description-v" />

      <label for="description-v" class="validator-result-{% if description.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お問い合わせ種類を選択してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th>
      <label for="inquiry">お問い合わせ内容</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="inquiry">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <textarea
        id="inquiry"
        name="inquiry"
        rows="5"
        class="acms-form-width-full"
        placeholder="お問い合わせ内容を入力してください。"
        data-validator="inquiry"
      >{{ inquiry.value }}</textarea>
      <input type="hidden" name="field[]" value="inquiry" />
      <input type="hidden" name="inquiry:v#required" id="inquiry-v-required" />
      <input type="hidden" name="inquiry:c" value="KV" />

      <label for="inquiry-v-required" class="validator-result-{% if inquiry.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お問い合わせ内容を入力してください。</p>
      </label>
    </td>
  </tr>
</table>
</div>

<h3>お客様情報</h3>
<div class="entry-container">
<table class="contact-form h-adr">
  <tr>
    <th><label for="organization">会社名</label></th>
    <td>
      <input
        id="organization"
        type="text"
        name="organization"
        autocomplete="organization"
        value="{{ organization.value }}"
        class="acms-form-width-full"
        placeholder="株式会社サンプルサイト"
      />
      <input type="hidden" name="field[]" value="organization" />
      <input type="hidden" name="organization:c" value="KV" />
    </td>
  </tr>
  <tr>
    <th>
      <label for="name">お名前</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="name">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <input
        id="name"
        type="text"
        name="name"
        autocomplete="name"
        class="acms-form-width-full"
        value="{{ name.value }}"
        placeholder="山田 太郎"
        data-validator="name"
      />
      <input type="hidden" name="field[]" value="name" />
      <input type="hidden" name="name:v#required" id="name-v-required" />
      <input type="hidden" name="name:c" value="KV" />

      <label for="name-v-required" class="validator-result-{% if name.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>お名前を入力してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th>
      <label for="email">メールアドレス</label><span class="label-required">必須</span>
      <label class="valid-mark" data-validator="email">
        <span class="acms-icon acms-icon-checklist"></span>
      </label>
    </th>
    <td>
      <input
        id="email"
        type="email"
        name="email"
        autocomplete="email"
        value="{{ email.value }}"
        class="acms-form-width-full"
        placeholder="info@example.com"
        data-validator="email"
      />
      <input type="hidden" name="field[]" value="email" />
      <input type="hidden" name="email:v#required" id="email-v-required" />
      <input type="hidden" name="email:v#email" id="email-v-email" />
      <input type="hidden" name="email:c" value="a" />

      <label for="email-v-required" class="validator-result-{% if email.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>メールアドレスを入力してください。</p>
      </label>
      <label for="email-v-email" class="validator-result-{% if email.v.email %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>正しいメールアドレスを入力してください。</p>
      </label>
    </td>
  </tr>
  <tr>
    <th><label for="tel">お電話番号</label></th>
    <td>
      <input
        id="tel"
        type="tel"
        name="tel"
        autocomplete="tel"
        value="{{ tel.value }}"
        size="12"
        class="acms-form-width-full"
        placeholder="000-000-0000"
      />
      <input type="hidden" name="field[]" value="tel" />
      <input type="hidden" name="tel:c" value="n" />
    </td>
  </tr>
  <tr>
    <th><label for="address">ご住所</label><span class="label-required">必須</span></th>
    <td>
      {% set postalCode = _context['postal-code'] %}
      {% set addressLevel1 = _context['address-level1'] %}
      <script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
      <span class="p-country-name" style="display:none;">Japan</span>
      <div class="acms-form-group">
        〒<input
          type="text"
          name="postal-code"
          autocomplete="postal-code"
          value="{{ postalCode.value }}"
          id="postal-code"
          class="acms-form-width-mini p-postal-code"
          size="8"
          maxlength="7"
          placeholder="0000000"
          data-validator="postal-code"
        />
        <input type="hidden" name="field[]" value="postal-code" />
        <input type="hidden" name="postal-code:c" value="a" />

        <select class="form-select p-region" name="address-level1" autocomplete="address-level1" data-validator="address-level1">
          <option value="">都道府県</option>
          <option value="北海道" {{ addressLevel1.value|selected('北海道') }}>北海道</option>

          <option value="青森県" {{ addressLevel1.value|selected('青森県') }}>青森県</option>
          <option value="岩手県" {{ addressLevel1.value|selected('岩手県') }}>岩手県</option>
          <option value="宮城県" {{ addressLevel1.value|selected('宮城県') }}>宮城県</option>
          <option value="秋田県" {{ addressLevel1.value|selected('秋田県') }}>秋田県</option>
          <option value="山形県" {{ addressLevel1.value|selected('山形県') }}>山形県</option>
          <option value="福島県" {{ addressLevel1.value|selected('福島県') }}>福島県</option>
          <option value="茨城県" {{ addressLevel1.value|selected('茨城県') }}>茨城県</option>
          <option value="栃木県" {{ addressLevel1.value|selected('栃木県') }}>栃木県</option>
          <option value="群馬県" {{ addressLevel1.value|selected('群馬県') }}>群馬県</option>

          <option value="埼玉県" {{ addressLevel1.value|selected('埼玉県') }}>埼玉県</option>
          <option value="千葉県" {{ addressLevel1.value|selected('千葉県') }}>千葉県</option>
          <option value="東京都" {{ addressLevel1.value|selected('東京都') }}>東京都</option>
          <option value="神奈川県" {{ addressLevel1.value|selected('神奈川県') }}>神奈川県</option>
          <option value="新潟県" {{ addressLevel1.value|selected('新潟県') }}>新潟県</option>
          <option value="富山県" {{ addressLevel1.value|selected('富山県') }}>富山県</option>
          <option value="石川県" {{ addressLevel1.value|selected('石川県') }}>石川県</option>
          <option value="福井県" {{ addressLevel1.value|selected('福井県') }}>福井県</option>
          <option value="山梨県" {{ addressLevel1.value|selected('山梨県') }}>山梨県</option>

          <option value="長野県" {{ addressLevel1.value|selected('長野県') }}>長野県</option>
          <option value="岐阜県" {{ addressLevel1.value|selected('岐阜県') }}>岐阜県</option>
          <option value="静岡県" {{ addressLevel1.value|selected('静岡県') }}>静岡県</option>
          <option value="愛知県" {{ addressLevel1.value|selected('愛知県') }}>愛知県</option>
          <option value="三重県" {{ addressLevel1.value|selected('三重県') }}>三重県</option>
          <option value="滋賀県" {{ addressLevel1.value|selected('滋賀県') }}>滋賀県</option>
          <option value="京都府" {{ addressLevel1.value|selected('京都府') }}>京都府</option>
          <option value="大阪府" {{ addressLevel1.value|selected('大阪府') }}>大阪府</option>
          <option value="兵庫県" {{ addressLevel1.value|selected('兵庫県') }}>兵庫県</option>

          <option value="奈良県" {{ addressLevel1.value|selected('奈良県') }}>奈良県</option>
          <option value="和歌山県" {{ addressLevel1.value|selected('和歌山県') }}>和歌山県</option>
          <option value="鳥取県" {{ addressLevel1.value|selected('鳥取県') }}>鳥取県</option>
          <option value="島根県" {{ addressLevel1.value|selected('島根県') }}>島根県</option>
          <option value="岡山県" {{ addressLevel1.value|selected('岡山県') }}>岡山県</option>
          <option value="広島県" {{ addressLevel1.value|selected('広島県') }}>広島県</option>
          <option value="山口県" {{ addressLevel1.value|selected('山口県') }}>山口県</option>
          <option value="徳島県" {{ addressLevel1.value|selected('徳島県') }}>徳島県</option>
          <option value="香川県" {{ addressLevel1.value|selected('香川県') }}>香川県</option>

          <option value="愛媛県" {{ addressLevel1.value|selected('愛媛県') }}>愛媛県</option>
          <option value="高知県" {{ addressLevel1.value|selected('高知県') }}>高知県</option>
          <option value="福岡県" {{ addressLevel1.value|selected('福岡県') }}>福岡県</option>
          <option value="佐賀県" {{ addressLevel1.value|selected('佐賀県') }}>佐賀県</option>
          <option value="長崎県" {{ addressLevel1.value|selected('長崎県') }}>長崎県</option>
          <option value="熊本県" {{ addressLevel1.value|selected('熊本県') }}>熊本県</option>
          <option value="大分県" {{ addressLevel1.value|selected('大分県') }}>大分県</option>
          <option value="宮崎県" {{ addressLevel1.value|selected('宮崎県') }}>宮崎県</option>
          <option value="鹿児島県" {{ addressLevel1.value|selected('鹿児島県') }}>鹿児島県</option>

          <option value="沖縄県" {{ addressLevel1.value|selected('沖縄県') }}>沖縄県</option>
        </select>
        <input type="hidden" name="field[]" value="address-level1" />
      </div>
      <textarea
        id="address"
        name="address"
        rows="2"
        class="acms-form-width-full p-locality p-street-address p-extended-address"
        data-validator="address"
      >{{ address.value }}</textarea>
      <input type="hidden" name="field[]" value="address" />
      <input type="hidden" name="postal-code:v#required" id="postal-code-v-required" />
      <input type="hidden" name="postal-code:v#regex" value="^[\d]{7}$" id="postal-code-v-regex" />
      <input type="hidden" name="address-level1:v#required" id="address-level1-v-required" />
      <input type="hidden" name="address:v#required" id="address-v-required" />
      <input type="hidden" name="address:c" value="KV" />

      <label for="postal-code-v-required" class="validator-result-{% if postalCode.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>郵便番号が入力されていません。</p>
      </label>
      <label for="postal-code-v-regex" class="validator-result-{% if postalCode.v.regex %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>郵便番号はハイフンなしの数値7桁で入力してください。</p>
      </label>
      <label for="address-level1-v-required" class="validator-result-{% if addressLevel1.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>都道府県が選択されていません。</p>
      </label>
      <label for="address-v-required" class="validator-result-{% if address.v.required %}0{% endif %}">
        <p class="error-text"><span class="acms-icon acms-icon-attention"></span>住所が入力されていません。</p>
      </label>
    </td>
  </tr>
</table>
</div>

フォームの編集権限を変更する

config.system.yaml に1行追記し、フォームの編集権限を変更できます。この機能はVer.2.11から利用可能です。

フォームの編集権限は管理者または編集者を選択できます。初期値は編集者以上になっています。


項目 選択肢 初期値
form_admin_authority administrator | editor editor

キーワード検索フォーム(全文検索フォーム)

a-blog cms でキーワード検索フォーム(キーワード検索は全文検索とも呼ばれます)を実装する方法を紹介します。

a-blog cms でキーワード検索フォームを実装するには、POST_2GET モジュールを利用して、keywordのURLコンテキストに検索したいキーワードを含んだURLのページに遷移するフォームのテンプレートを作成します。

そのため、検索結果のページのモジュールIDの設定には「キーワード(keyword)」の項目にチェックをつけ、URLコンテキストを優先させる必要があります。

以下、キーワード検索フォームのサンプルになります。 検索結果のページは、input type="hidden"name="tpl"を記述して、テンプレートを指定しています。


<form action="/search.html" method="post">
    <input type="search" name="keyword" value="%{KEYWORD}">
    <input type="hidden" name="query" value="keyword">
    <button type="submit" name="ACMS_POST_2GET">検索</button>
    <input type="hidden" name="tpl" value="/search.html">
    <input type="hidden" name="bid" value="%{BID}">
</form>
<form action="/search.html" method="post">
    <input type="search" name="keyword" value="{{ KEYWORD }}">
    <input type="hidden" name="query" value="keyword">
    <button type="submit" name="ACMS_POST_2GET">検索</button>
    <input type="hidden" name="tpl" value="/search.html">
    <input type="hidden" name="bid" value="{{ BID }}">
</form>

キーワード検索の仕様

a-blog cms が行うキーワード検索の仕様について説明します。

a-blog cms では、keywordのURLコンテキストに指定された文字列を利用してキーワード検索(全文検索)を行います。

キーワード指定方法について、いくつかオプションがあります。

複数キーワード検索

A B のように複数のキーワードを「スペース(空白文字)」でつなげることで、複数キーワードを含むページを検索することができます。

除外検索

A -B のように除外したいキーワードを「-」の後に指定することで、キーワードを除外したページを検索できます。

A -B -C のように、「スペース(空白文字)」でつなげること除外したいキーワードを複数指定することも可能です。

フォームのセキュリティ対応

フォームのセキュリティ設定周りについて学びましょう。

フォームは、一般ユーザーが送信できる箇所になり、セキュリティをしっかりと考えないといけない箇所になります。 標準的なセキュリティ対策は標準でされていますが、フォーム設定などによってもよりセキュリティを高めれますので、設定する意味や設定内容をここで学びましょう。

入力チェック

できる限り、テンプレートで指定したバリデーションは、「フォーム設定(管理画面でのフォーム詳細画面)」でもするようにしましょう。
ここの設定をおこたると、少しHTMLの知識のある人なら、開発者ツールでHTMLを変更し、バリデーションを突破されてしまう為になります。

テンプレートでのバリデーション設定

テンプレートでのバリデーション設定は以下のコードのようにHTMLによって設定できます。 ただし単なるHTMLコードなので、ブラウザの開発者ツールなどを利用すると、簡単にバリデーションの記述を削除して突破されてしまいます。

<input type="text" name="name" value="{name}" data-validator="name" />
<input type="hidden" name="field[]" value="name" />
<input type="hidden" name="name:v#required" value="" id="name-v-required" />
<div data-validator-label="name-v-required" class="validator-result-{name:v#required}">
  <p class="error-text">
    <span class="acms-admin-icon acms-admin-icon-attention"></span>名前は必須入力です。
  </p>
</div>

フォーム設定でのバリデーション設定

フォーム設定でバリデーション設定すると、サーバーサイドでのチェックになるので、攻撃者はこのバリデーションを突破できなくなります。



メールアドレスのテンプレート指定

メールアドレスの「テンプレート指定」は出来るだけ無効化させましょう。 バリデーションと同じようにテンプレートでの指定は、攻撃者がブラウザの開発者ツールなどで、自由に変更できてしまいます。 必要のない項目は「テンプレート指定を無効」にチェックをつけて無効化させましょう。

To, From, AdminTo, AdminFrom に「テンプレート指定を無効」にチェックを付けた場合は、必ず管理画面でメールアドレスを設定しましょう。設定しないと宛先と差出人の情報が空となり、メール送信で失敗します。

おすすめ設定

以下は、おすすめの設定内容になります。

一般メール設定

お問い合わせ者に自動返信するメールの設定になります。 お問い合わせ者に送信先メールアドレスさえフォームで入力してもらえればいいので、「To」以外はテンプレートで指定できないようにします。


項目 テンプレート指定
To 有効
From 固定値 無効 ✅
Cc 空 or 固定値 無効 ✅
Bcc 空 or 固定値 無効 ✅
Reply-To 空 or 固定値 無効 ✅

一般メール設定の設定例

一般メール設定の設定例


管理者宛メール設定

管理者宛メールは、送信先が決まっているので「AdminTo」をテンプレートで指定できなくします。

「AdminFrom」はお問い合わせ者のメールアドレスをテンプレートで設定することも多いと思いますが、おすすめとしては「AdminFrom」も固定にしてしまいます。 というのも、メールはCMSがあるサーバー、またはSMTPサーバーから送信されますので、Fromのメールアドレスドメインと送信サーバーが合わずFromの偽装にあたり迷惑メール扱いになる可能性が高いためになります。

ただ、このままでは管理者に届いたメールを返信しようと思っても、返信できないので「AdminReply-To」にお問い合わせ者のメールアドレスをテンプレートで指定するようにします。 これで、メーラーで返信する時、お問い合わせ者に返信できるようになります。


項目 テンプレート指定
AdminTo 固定値 無効 ✅
AdminFrom 固定値 無効 ✅
AdminCc 空 or 固定値 無効 ✅
AdminBcc 空 or 固定値 無効 ✅
AdminReply-To 有効

管理者宛メール設定の設定例

管理者宛メール設定の設定例


複数指定

特に理由がない限り複数指定できないようにチェックをつけましょう。
複数指定できてしまうと、フォームで大量のメールアドレスをカンマ続きで指定する事により、大量のメールを送信できてしまうことになります。



そもそも自動返信メールを送らない

問い合わせ受け付けメール(自動返信メール)を投稿者アドレスに送信しない設定にするのも方法の一つです。 この場合、そもそもメールが送信されないので、セキュリティを高めることができます。

ただしお問い合わせ者が正常にメールが送信されたか判断しずらいので、ここは、利便性とセキュリティを比べて判断するようにしましょう。

メール送信しないように設定する方法

フォーム設定で、メールアドレスを全て空にして、テンプレートからも指定できなくしましょう。これでメールは送信されなくなります。


メール送信しないように設定する方法

メール送信しないように設定する方法


reCAPTCHAの導入

標準機能ではありませんが、よりフォームのセキュリティを高めるために、ロボットか判断するGoogleの「reCAPTCHA」サービスと連携する方法がございます。
a-blog cms の拡張アプリとして用意されていますので、こちらもご検討ください。

https://github.com/appleple/acms-recaptcha