IFブロック利用事例の紹介

ver2.0からの機能、IFブロックの利用事例を紹介します。
IFブロックの説明についてはドキュメントページを参考にしてください。

モジュールの変数を使う例

<!-- BEGIN_MODULE Category_EntryList id="clinicTop" -->
 <!-- BEGIN categoryEntryList:loop -->
 <!-- BEGIN category:loop --><!-- BEGIN entry:veil --><!-- BEGIN entry:loop -->
  
  <!-- BEGIN_IF [{entryCode}/eq/state.html] -->
  <p class="icon_camera">{entryTitle}</p>
  <!-- ELSE_IF [{entryCode}/eq/access.html] -->
  <p class="icon_pin">{entryTitle}</p>
  <!-- ELSE -->
  <p>{entryTitle}</p>
  <!-- END_IF -->
  
 <!-- END entry:loop --><!-- END entry:veil --><!-- END category:loop -->
 <!-- END categoryEntryList:loop -->
<!-- END_MODULE Category_EntryList -->

上記の例では、特定のエントリーコードの場合に、表示するアイコンを変えています。IFブロックを使わずに、カスタムフィールドにクラス名を登録し、それを表示するような方法も可能です。

<!-- BEGIN_IF [{url_a}{url_b}/nem/] -->
    <h2>リンク</h2>
    <!-- BEGIN url_a:veil --><p><a href="{url_a}" class="acms-btn">リンクA</a></p><!-- END url_a:veil -->
    <!-- BEGIN url_b:veil --><p><a href="{url_b}" class="acms-btn">リンクB</a></p><!-- END url_b:veil -->
<!-- END_IF -->

上記の例では、カスタムフィールド「url_a」「url_b」があり、どちらか一方でも値がセットされていれば表示されるようになっています。
{url_a}{url_b}と値をつなげて、nem(値が空ではない)かどうかを判断しています。
このように、複数のフィールドを文字列としてつなげて使うことも可能です。

また、nemのように比較対象がない記述は”{hoge}/nem”ではなく”{hoge}/nem/”と最後の/が必要になります。

<!-- BEGIN pager:veil -->
<div>
  <!-- BEGIN page:loop --><span <!-- BEGIN_IF [%{PAGE}/eq/{page}] -->class="itemPagerActive"<!-- END_IF -->>
  <!-- BEGIN link#front --><a href="{url}"><!-- END link#front -->{page}<!-- BEGIN link#rear --></a><!-- END link#rear -->
  </span><!-- END page:loop -->
 </p>
</div>
<!-- END pager:veil -->

上記の例では、今見ているページ(グローバル変数の%{PAGE})とページャーのページ番号(モジュール変数の{page})が一致した時だけクラスがセットされるようにしています。
グローバル変数をIFブロックに使うことができます、比較対象は必ずしも固定値である必要はなく、モジュール変数との比較にも利用できます。

<!-- BEGIN_IF [%{CID}/re/^(31|44)$] -->
<!-- END_IF -->

正規表現を使って、複数の値を許可する場合にも利用できます。

IFブロックの注意点

IFブロックはとても便利な機能ですが、いくつかのデメリットもあります。

メンテナンス性の低下

テンプレートファイルに直接条件を記入するため、FTPでテンプレートファイルを確認・変更できる方でないと修正ができません。サイト構築時には大きな問題ではありませんが、お客様での運用時に柔軟な調整ができません。
モジュールIDでの調整でしたら、管理ページから変更が可能です。

表示速度の低下

実行順序の関係で、IFブロックは最後に処理されます(これによって柔軟な条件分岐処理が可能になります)
そのため、テンプレート処理が一通り動いてから条件分岐処理が行われます。
例えば、エントリー一覧に出ている100件のエントリーからある1件だけを表示するような処理をIFブロックで行いますと、ページ表示には不要な99件のエントリーも一旦テンプレートに書きだされます。そのため表示速度は低下します。こういった用途でのIFブロックの利用はお勧めできません。

テーマの継承により送信できないフォームが表示される可能性

先日、a-blog cms のサイト上で http://www.a-blogcms.jp/production/contact/ という間違ったリンクされているところがありました。想定されていないページなので Not Found になるべきところなのですが、今回のケースでは表示されており、メールが送信できない状態でした。

よくありそうなケースですので、対策等を考えてみたいと思います。

状態

スマートフォンとPCの表示の振り分け方法

ユーザーエージェントによる振り分け


a-blog cms では、スマートフォン専用プラグインなどのプログラムはなく、このルール機能によって、ブラウザの名前(USER-AGENT)をチェックし設定を切り換えて表示します。


ルールを新規作成

ルールを新規作成


ルールの設定は 管理ページ>ルール から行います。


「スマートフォンの場合」のルール

「スマートフォンの場合」のルール


このルールの設定を行った後に、一覧のコンフィグのリンクから、スマートフォンの時のコンフィグについて設定を行います。最低限、テーマの設定を変更する事になります。
この場合、PCとスマートフォンでは同じURLで違ったテーマを表示させる事ができるようになります。a-blog cms で標準搭載のキャッシュ機能も、ルールによって個別に処理されます。


ルール別にコンフィグを設定します

ルール別にコンフィグを設定します


ルール名がついたコンフィグ管理画面

ルール名がついたコンフィグ管理画面


スマートフォン上で、PC・スマートフォンそれぞれの表示を可能にしたい場合


a-blog cms では、PC用とスマートフォン用のテーマをそれぞれ作成・適用できますが、スマートフォンでの表示の場合、スマートフォン用だけでなく、PC用の表示を見たいという場合があります。

ここでは、スマートフォン用テーマでの「PCモードに切り替える」ボタン、PC用テーマでの「スマートフォンモードに切り替える」ボタンの作成について解説します。

サンプルコード(スマートフォン用テーマの任意の場所に追加)

<form action="" method="post" id="switch_theme">
    <input type="hidden" name="cookie[]" value="acms_http_header_User-Agent" />
    <input type="hidden" name="acms_http_header_User-Agent" value="pc browser" />
    <input type="submit" name="ACMS_POST_Cookie" value="PCモードに切り替える" />
</form>

<script>
$('#switch_theme').submit(function(){
    $.cookie("js-switch_theme","on");
    return true;
 });
</script>

サンプルコード(PC用テーマの任意の場所に追加)

<form action="" method="post" id="switch_theme" style="display:none;">
    <input type="hidden" name="cookie[]" value="acms_http_header_User-Agent" />
    <input type="hidden" name="acms_http_header_User-Agent" value="Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_3 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7E18 Safari/528.16" />
    <input type="submit" name="ACMS_POST_Cookie" value="スマートフォンモードに切り替える"  />
</form>
 
<script>
$(function() {
    if ( 'on' == $.cookie('js-switch_theme') ) {
        $('#switch_theme').show();
    }
});
</script>

解説

基本的に、PC、スマートフォンとも、移行先のユーザーエージェントの内容を渡して再度同じページの読み込みをしているものになります。

上記のPC用テーマに追加するコード中では、移行先となるユーザーエージェントの内容はiPhoneのものになっていますので、必要に応じて変更してください。また、スマートフォン用テーマに追加するコード内では、移行先となるPCのユーザーエージェントとして仮に「pc browser」としてあります。こちらも必要に応じて変更してください。

PC用テーマのscript部分は、スマートフォンでの表示時のみ切り替えボタンを表示するためのものです。

フォームに reCAPTCHA を導入しよう


ウェブサイトにアクセスを試みるボットを遮断するために設置されているreCAPTCHAですが一度はどこかで体験したことがあると思います。webのフォームは一番攻撃されやすい箇所になります。reCAPTHAを導入して、ロボットによるスパム投稿を防ぎましょう。


ロボットでないことを証明する

ロボットでないことを証明する


下準備

まずreCAPTCHAを導入するために、reCAPTCHA にアクセスして、必要な情報を取得します。

「Domains」の項目はご利用のサイトのドメインを指定してください。


(スクリーンショット)

サイトのドメイン登録


(スクリーンショット)

Site key と Secret key の取得


サイトを登録し、以下2つのキーを使用しますのでメモしておいてください。

  • Site key
  • Secret key

クライアント実装

下準備ができましたので、まずはクライアントサイドを実装します。

JavaScript

以下コードを ご利用のテーマのフォームの head要素内に読み込んでください。

例えば、simple2016テーマなら themes/simple2016/contact/index.html です。

<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script>
  function validateRecaptcha ( code ) {
    if ( !!code ) {
      var form = document.querySelector(".recaptcha");
      form.removeAttribute('disabled');
    }
  }
</script>

HTML

次に送信フォームを少し修正します。simple2016テーマなら themes/simple2016/contact/form/main.html を開きます。

以下コードを送信フォーム内に挿入します。ここで、{Site key} は 下準備で取得した Site keyに置き換えてください。

<div class="g-recaptcha" data-callback="validateRecaptcha" data-sitekey="{Site key}"></div>

次に、送信ボタンに recaptcha クラスをふり、 disabled にしておきます。

<input type="submit" name="ACMS_POST_Form_Submit" value="送信する" id="btnSubmit" class="recaptcha btn-attention-block-large" disabled />

完成例

例として themes/simple2016/contact/form/main.html を編集しています。

<!-- BEGIN step#confirm -->
...

<form action="thanks.html" method="post" class="form-btn form-btn-send" enctype="multipart/form-data">

    <div class="g-recaptcha" data-callback="validateRecaptcha" data-sitekey="xxxxxxxxxxxxxxxxxxxxxx"></div>

    <input type="hidden" name="To[]" value="{email}" />
    <input type="hidden" name="AdminReply-To[]" value="{email}" />
    <input type="hidden" name="AdminFrom[]" 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="送信する" id="btnSubmit" class="recaptcha btn-attention-block-large" disabled />
</form>

クライアントサイドは完成です。実際に動かしてみましょう。フォームの確認画面まで行くと、reCAPTCHAが表示され、送信ボタンが押せないようになっているかと思います。reCAPTCHAで承認が通ると送信ボタンが押せるようになります。


(スクリーンショット)

チェックするまで送信ボタンが押せない


サーバーサイド実装

クライアントサイドの実装ができると、一見動いていそうに見えますが、このままだと送信ボタンの disabled を開発者ツールなどで削除してしまえば、送信できるようになってしまいます。そこで、サーバーサイドで認証を行いましょう。

認証の仕組み

ユーザーがreCAPTCHAの認証を通ると、ランダムな文字列のコードが生成され、フォーム送信時に一緒に送信されます。 このコードを使って、サーバーサイドでreCAPTCHAのapiにリクエストを投げ、正しいコードかチェックを行うことにより、正常な手段でフォームが送信されたことを確認することができます。

実装

実装にはHook機能を使います。php/ACMS/User/Hook.phpbeforePostFire に以下のコードを追加しましょう。

config.server.phpのHOOK_ENABLEを 1 にしておきましょう。

public function beforePostFire($thisModule)
{
    $moduleName = get_class($thisModule);

    if ( $moduleName === 'ACMS_POST_Form_Submit' ) {
        $secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        $response = $thisModule->Post->get('g-recaptcha-response');
        $api = "https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${response}";

        $valid = false;
        if ( $res = @file_get_contents($api) ) {
            $check = json_decode($res);
            if ( $check->success === true ) {
                $valid = true;
            }
        }

        if ( !$valid ) {
            $Field  = $thisModule->extract('field');
            $Field->setMethod('g-recaptcha-response', 'check', false);
            $thisModule->Post->set('step', 'forbidden');
        }
    }
}

ここで、 $secret を、下準備で用意した Secret key で置き換えます。これで実装は完了です。

確認

では実際に、サーバーサイドで認証ができているかチェックしてみましょう。フォームで確認画面まで移動して、 disabled になっている送信ボタンを、開発者ツールで disabled を外して送信してみましょう。


不正なアクセスとして処理される

不正なアクセスとして処理される


これでハンズオンは完了ですが、余力のある方は、reCAPTCHAの色々なオプションを試してみてください。お疲れ様でした!

時期バージョンの Ver. 2.8 では拡張アプリになり、簡単にreCAPTCHAが導入できるようになる予定です。お楽しみに!