任天堂検索ポータルができるまで

この記事は約19分で読めます。
スポンサーリンク

以前「今週のひとこと」自動化の仕組みをザックリと記した記事を公開しましたが、関連して今回は本サイトに設置している任天堂検索ポータルの仕組みをこれまたザックリとメモ程度に残します。

検索ポータル、今週のひとこと自動化については以下をご覧ください。

自動化ほど凝ったことはしておらず、技術に対してもあまり踏み込んだことは書いていません。分からない方もなんとな~くの道筋を理解してもらえればと。

ただ、ちょっとWeb周りかじったことがある人ならスムーズに読めるかも。
ゲーブラの動作環境ですが、サーバーはロリポップサーバー、WordPressテーマはcocoonになります。

任天堂検索ポータルとは?

任天堂から発売/販売されたゲームソフトのほぼ全てを検索できる機能
設置当初に機能概要を紹介した記事もあるので以下を読んでもらえると良いと思います。

検索の柔軟性を上げるために機能の拡張、レイアウトの改善など構想は色々あるのですが、なかなか着手できていません。

使用した機能とか

使用した機能は以下。サーバーがあり、WordPressでサイトを運用しているのであれば、新たに追加しなければいけないミドルウェアなどはありません。

ロリポップサーバー

ゲーブラ運営用レンタルサーバー。まささんの身を削った投資。

データベース(MySQL)

データの保管場所。サイト内記事、ユーザに関する情報などサイトで使用するありとあらゆる情報を保持しています。

今回の検索ポータルではソフトの情報を保持するために新たに2つテーブルを作成しました。詳細は後述しますが、おおよそ以下のようなテーブル。

・ソフトの情報を保持するテーブル:
ソフトの名称、発売日、対応ハードなどを保持するテーブル。対応ハードについてはIDで保持。下記のハード情報テーブルから名前解決を行います。

・ハードの情報を保持するテーブル:
ゲームハードの名称、発売日などをソフト同様に保持するテーブル。発売日などを保持しているので、ソフト同様に節目を計算させることも仕組上可能です。(現状は未実装だけど)

HTML

ページの見た目を作るための言語。今見ているこのページも土台はHTMLでできています。

CSS

HTMLの見た目に対して色を付けたり文字のサイズを整えたり…と見栄えを調整するための言語

JavaScript

ページの土台、見た目…と来て今度はページに動きを加える言語。ボタンにカーソルを合わせると色が変わったり、チェックをつけるとページの一部の表示が変わったりといったことができます。

jQueryについて

JavaScriptって正直使いにくい!書き終わった後読みにくい!といったことが人によっては…少なくとも私は起きます。(習った順序が何故かjQueryが先だったのもあるけど)

そんなJavaScriptを使いやすく、見やすく書けるのがこのjQueryというライブラリ。

WordPressでは初めから使用されているので、新たにjQueryを導入する必要は基本的にないです。

PHP

サーバー側で動かしたい処理内容を記述したファイル
HTMLの記述にも対応しているので、サーバー内の何かしらの処理結果値をページ内に使用したい場合など動きを付けたい時は重宝します。

今回は検索処理や検索結果の表の生成を行ってます。

作成手順

実装に至までの流れをご紹介。

ゴールは検索ポータル用固定ページから検索ポータル実施PHPファイルを呼び出すこととします。

テーブルの作成

まずはソフトやハードの情報を保持するためのテーブルを作りましょう。

ロリポップの場合管理画面からデータベースへアクセスすることができます。

WordPressで自作したテーブルを使用する場合、wp-db.phpを編集する必要があります。

内容は自作したテーブル名を追記するだけの簡単なものなので以下を参考にしてください。

ソフト情報保持テーブル

今回作成したテーブルの内の1つはソフトの情報を保持するテーブル。

ソフト名、発売日などの基本的な情報に加えて、パッケージ、ダウンロードの有無を判断するフラグを持たせています。

各項目の説明は省略しますが、パッケージ/ダウンロードフラグだけ補足します。

基本的にパッケージ版とダウンロード版は同日発売になるのですが、ダウンロード版正式運用開始前の3DSソフトの内一部はダウンロード版が後日発売になっていたり、最近のソフトではテトリス99などダウンロード専用ソフトが好調で後になってパッケージを発売するケースもあります。

そのため、同じソフトなのに形態によって発売日が異なるケースがあるため、別レコードで管理しなければならず渋々パッケージ/ダウンロードのフラグを持たせました。

現状、検索ポータルには一切絡んでいない項目なのですが、ダウンロード専用ソフトの判断もこのフラグを用いれば判断可能なのでその内実装します…

ハード情報保持テーブル

ソフトのハードIDの名前解決、その他、将来的にハード自体の検索を実装する場合を想定してソフト同様に発売日も持たせています。

記事内でPHPを呼び出す準備

次にPHPを動かす準備をしましょう。

PHPを作成したとしても通常は記事内では動きません。準備が必要になります。

そこでWordPressに標準搭載されているショートコードと呼ばれる機能を使用します。
WordPressユーザーなら使用用途はともかく見たことのある人は多いはず。

WordPressのウィジェットブロック群の内の一つ
実際の入力ブロック

ショートコードをただ使うだけであれば簡単にできるので下記サイトを参考にしてみてください。

上記サイトではショートコードによって予め用意したイベントを動かしているのですが、今回はイベントだけでなく、ショートコードから検索ポータルに使用するPHPファイルを呼び出す必要があるので、少し捻った作業が必要になります。

そこで、テーマ内のfunction.phpを以下の通り編集する必要が出てきます。

/ PHPの読み込み
---------------------------------------------------------- /
function my_php_Include($params = array()) {
extract(shortcode_atts(array('file' => 'default'), $params));
ob_start();
include(STYLESHEETPATH . "/$file.php");
return ob_get_clean();
}
add_shortcode('call_php', 'my_php_Include');
イッキ
イッキ

※重要

functions.phpはどんなテーマを使用していても大抵はコアとなる重要なファイルです。編集をする場合はサイト全体のバックアップをとっておく、それが面倒であっても最低限functions.phpの編集前のバックアップをとっておきましょう。

このファイルが狂うとだいたいサイトが無に帰します。

functions.phpに限らず重要なファイルの編集前にはバックアップをとってください。

ゲーブラの場合、テーマはcocoonを採用しています。
cocoon製作者のわいひらさん自身がWordPressによるサイト運営を行っていて、技術記事も豊富にあるのでサポート面でもお勧め。

cocoonの場合は/wp-content/themes/cocoon-child-master/
にあるfunctions.phpに追記しましょう。

また、ファイルをアップロードする際はサーバーの管理画面から直接アップロードを行っても良いのですが、FFFTPを用いると便利です。

ということで、ゲーブラでも以下のように追加。

<?php //子テーマ用関数
if ( !defined( 'ABSPATH' ) ) exit;

//子テーマ用のビジュアルエディタースタイルを適用
add_editor_style();

-----------------省略-------------------

//コメントのメールアドレス、サイト名削除コード
add_filter('comment_form_default_fields', 'my_theme_remove_url');
function my_theme_remove_url($arg) {
$arg['url'] = '';
$arg['email'] = '';
return $arg;
}
add_filter('comment_form_defaults', 'my_comment_notes_before');
function my_comment_notes_before( $defaults){
$defaults['comment_notes_before'] = '';
return $defaults;
}

// PHPファイルの読み込みショートコード定義 [call_php file="ファイル名"]で呼び出し
function my_php_Include($params = array()) {
extract(shortcode_atts(array('file' => 'default'), $params));
ob_start();
include(STYLESHEETPATH . "/$file.php");
return ob_get_clean();
}
add_shortcode('call_php', 'my_php_Include');

これでショートコードを呼び出す準備ができました。

検索ポータル用PHPの作成

さて、準備ができたので次は実際に検索ポータルのプログラムを作ります。
プログラムを作る前に画面構想を確認します。既に公開しているものと同じになりますが、以下の画像のとおりです。

入力項目としてはソフト名、ハード、発売日の3つ。アクションとしては発売日の年月日指定方法の切り替え、検索ボタンの2つ。

ページレイアウト

ページ見た目を左右するレイアウトはHTMLなどを駆使することになりますが、面倒なのでWordPressの助けを借りましょう。

実際の記事を作成する画面でWordPress要素を使用してある程度ひな形を作成HTMLに変換し内容を一部書き換えていく方法をとります。

作成画面を開くとレイアウトは予め何パターンか用意されていることが分かります。
とりあえず、レイアウトを選択し入力してみましょう。

これだけで上記画面構想にある項目名、入力フィールドの並びができました。見出し1ソフト名内容1ソフト名入力フィールドのイメージです。この組み合わせを複数作成すれば、ハード名や発売日も同じように並べることができます。

ひな形ができたらHTMLに変換しましょう。
要素のオプションに【HTMLとして編集】があり、選択するとHTMLが表示されます。タグの中身を任意のものに書き換えれば、HTMLの作成を省略することができます。

ただ、要素によっては何故かHTMLへの変換が用意されていません。先ほど選択したカラムもHTMLへの変換が用意されていません…。

何で無いの…

その場合はブラウザの開発者ツールを起動しましょう。私の環境ではGoogle Chromeで行ってます。

起動させる前に記事を一旦プレビューします。

そして、キーボードのF12を押します。
デベロッパーツールが起動し、ページ内のソースなど解析に必要な情報が現れます。

デベロッパーツール左上にある矢印を選択した後、ページの解析したい箇所を選択します。

矢印で選択すると以下の画像のように要素に使われているHTMLやCSSなどを特定することが出来ます。

この例ではwp-block-columns内を置き換えれば、レイアウトを維持したまま任意のものにすることができそうです。

他にも表形式で表示出来るwp-block-tableなどもあるので、既存の要素を色々確認してみてください。

入力項目

ひな形もできたので、次は入力項目。

入力項目はユーザーが自由に入力できてしまうのでとても危険です。まずはこちらが意図したものではない文字や値が入力された場合を防ぎます。

最低限以下の制約が必要になります。

XSS対策

検索ポータルにはあまり関係ないのですが、ユーザーの入力値を使用するので念のため。

HTMLに使用される文字が入力された場合にエスケープ処理を行うなど…。
PHPに予め用意されているhtmlentities()を使用します。

  /*
   * エスケープ処理
   * @param 処理対象 $s
   */
  function escape($s){
    return htmlentities($s, ENT_QUOTES, "UTF-8");
  }

値が書き換えられた場合の対策

ハードのチェックボックスにはどのハードをチェックしたか確認するためのIDを保持しています。

先ほど使用したデベロッパーツールを用いればIDの改竄は可能なわけで、ソフト名の入力項目同様好きに入力できてしまいます。

なので、検索ボタンクリック後に数値であるかどうかのチェックを行って、数値以外であれば入力されていない場合と同等としたいと思います。
正規表現による数値チェックを使用しましょう。

  /*
   * 数値チェック
   * @param 処理対象 $value
   */
  function valueIntCheck($value){
    return preg_match("/^[0-9]+$/", $value);
  }

ハードIDに対してだけでなく、年月日も数値のみを許容しなければならないので同様の処理を通します。

ということで作成したおおよそのPHPファイルが以下。(一部割愛してます。)

<?php

  /*
   * エスケープ処理
   * @param 処理対象 $s
   */
  function escape($s){
    return htmlentities($s, ENT_QUOTES, "UTF-8");
  }

  /*
   * 数値0埋め処理
   * @param 処理対象 $value
   * @param ゼロ埋め後の長さ $length
   */
   function zeroComp($value, $length){
     $ret_value = $value;
     $str_len = mb_strlen($value);
     for($i = $str_len; $i < $length; $i++){
       $ret_value = "0".$ret_value;
     }
     return $ret_value;
   }

  /*
   * 数値チェック
   * @param 処理対象 $value
   */
  function valueIntCheck($value){
    return preg_match("/^[0-9]+$/", $value);
  }

  /*
   * 年範囲チェック
   * @param 処理対象 $year
   */
   function yearRangeCheck($year){
     global $this_year;
     return ($year > 0 && $year <= ($this_year + 1));
   }

   /*
    * 月範囲チェック
    * @param 処理対象 $month
    */
    function monthRangeCheck($month){
      global $this_month;
      return ($month > 0 && $month <= 12);
    }

    /*
     * 日範囲チェック
     * @param 処理対象 $day
     */
     function dayRangeCheck($day){
       global $this_day;
       return ($day > 0 && $day <= 31);
     }

   /*
    * 日付算出関数
    *
    * @param スタート数字 $start
    * @param エンド数字 $end
    * @param 比較対象年月日 $comp_date
    * @param 使用可能フラグ $available_flag
    */
   function optionLoop($start, $end, $comp_date, $available_flag){
     echo "<option value='0'>-</option>";
     for ($i = $start; $i <= $end; $i++) {
       if($i == $comp_date && $available_flag){
         echo "<option value='".$i."' selected>".$i."</option>";
       } else {
         echo "<option value='".$i."'>".$i."</option>";
       }
     }
   }

<!-- 検索フォーム自体のコードは省略 -->

<?php
  /* 検索フラグが立っている場合のみ検索実施
   * ページ遷移初回は検索結果を表示しないため
   */
  if($_GET['search_button_flag'] == '1'){
    // 検索クエリ発行
    $sql = $wpdb->prepare($query);
    // 検索クエリ実行
    $rows = $wpdb->get_results($sql);
    if($wpdb->print_error()){
      return;
    }

    // 検索結果メッセージ
    $message = (!$rows) ? "該当なし" : count($rows)."件ヒット";

    echo "<p>".$message."</p>";
    if($rows){
      // テーブルヘッダー
      echo "<div>";
      echo "<table class=\"wp-block-table has-subtle-pale-pink-background-color has-background\">";
      echo "<tbody>";
      echo "<tr>";
      echo "<td style=\"width:60%\"><strong>ソフト名</strong></td>";
      echo "<td style=\"width:28%\"><strong>発売日</strong></td>";
      echo "<td style=\"width:12%\"><strong>ハード</strong></td>";
      echo "</tr>";

      // 検索結果出力
      foreach ($rows as $row) {
        $replace_release_date = str_replace('-', '/', $row->発売日);
        echo "<tr>";
        echo "<td>".$row->ソフト名."</td>";
        echo "<td>".$replace_release_date."</td>";
        echo "<td>".$row->ハード名."</td>";
        echo "</tr>";
      }
      // テーブルタグ〆
      echo "</tbody></table></div>";
    }
  }
?>

完成したらこのファイルを一旦は先ほど編集したfunctions.phpと同階層に置きましょう。

JavaScriptについては今回はファイルを設置する方法はとっておらず、記事ごとに指定できるカスタムJavaScriptを使用しました。これについては後述します。

記事に呼び出しショートコード定義を設置

全てが揃ったら記事に設置します。

記事作成/編集画面で、ショートコードウィジェットを設置し、画像の通り入力。イコール以降は作成したPHPファイル名(拡張子なし)と入力します。

その他、わざわざPHPで作成する必要のない項目は通常の記事作成と同様に直接記事に文字を入力しましょう。

JavaScriptについては同じく作成/編集画面内で下部にあるカスタムJavaScriptに記入します。

先ほどアップロードした自作PHPファイル内から自作したJavaScriptファイルを呼び出すことももちろん可能なので、他の記事でも使用するような共通のJavaScriptがあればカスタムではなくアップロードして使用しましょう。

全ての準備が終わったので記事を表示してみましょう。

データベース最終更新日より下の項目がPHPで作成された内容になります。

最後に

今週のひとこと自動化に続いて技術アウトプットを行いましたが、どの層に向けて解説すべきか、どこからどこまで解説すべきかが明確に定まらず迷いました。

ただ、冒頭で述べたとおり、今現在WordPressで奮闘中の方々よりはこれからWordPressに手を出そうと思っている方々に向けて、無料ブログに比べると自由度は遥かに高いけど、自分の思ったことを実現しようとするとこれだけの道のりがあるんだよという若干のハードルの高さを示せたなら良かったかなと思います。

お気軽にコメントをどうぞ!