Chapter 9
INTER-Mediatorの実環境での展開

INTE-Mediatorを実際にサーバー等で運用するまでの話題をこの章で扱います。具体的には、データベースとWebサーバーのインストールや運用、そして、INTER-Mediatorで作ったファイル群をどのように管理するのかなどを説明します。しかしながら、例えばMySQLの動作や設定方法の全てをここで説明するのはこのトレーニングコースのカバー範囲を超えてしまいます。データベースに関する知識は他の一般的な教材を使って習得済みであるとの前提で、INTER-Mediatorで使う場合のポイントなどを解説します。なお、筆者の新居は通常の開発はMySQLで行っているため、MySQLのみの詳細な解説となります。

9-1データベースのインストール

INTER-Mediatorがサポートする3種類のオープンソースデータベース、そしてFileMaker Serverについてインストールと運用のポイントを解説します。それぞれの製品の概要などは各製品のサイトなどで確認してください。

MySQLのインストール

 MySQLは最も人気の高いオープンソースデータベースであり、レンタルサーバーのプロバイダでも利用できる場合が多いこともあって、広く利用されています。

MySQLのライセンス

 MySQLはオープンソースソフトウェアとして開発されており、GNU GPLv2と商用ライセンスのデュアルライセンスとなっています。用途によって無償で利用できるCommunity Edition(以下、「コミュニティ版」)を利用できますが、そうでなければ有償のStandard Edition、Enterprise Edition、Cluster CGE等(以下、まとめて「商用版」)をライセンス料を払って使用します。コミュニティ版を利用できる条件をまとめると次のようなものです。必須条件をいずれも満たした上で、条件1ないしは条件2を満たせば、コミュニティ版を利用できます。

 MySQLを前提にした開発アプリケーションを外部に対して全く公開しないのなら、[条件1]に該当してコミュニティ版を無料で使えます。また、ソフトウェアの複製や配布が伴わなければ、ソースコードを譲渡・公開することまでは強制されません。したがって、システムを一般に販売するわけではなく、コミュニティ版を入手した開発者がシステムを利用する範囲においてはGPLの適用を過度に恐れる必要はありません。

 [条件2]は、解釈にもよりますが、受託開発したものについてはGPL運用しない限りはコミュニティ版を利用できる要求を満たさないと言えます。有償、無償を問わず複製および再配布の際にはソースコードも引き渡さなければいけないという点で、一般的なWebベースの業務システム開発への利用を躊躇する人もいます。GPLをそのまま適用するとしたら、開発物を複製・配布する際にソースコードを譲渡しない場合には商用版を購入して利用する必要がある一方、以下に示す例外措置とさまざまな情報を元にした解釈を元にすればGPL運用しなければならない範囲は限定的であると言えます。

 まず、MySQLのライセンスドキュメントでGPLに加えて宣言されているFOSS License Exception(Oracle's Free and Open Source Software License Exception、以下「FOSS」)で、オラクルはライセンスの例外措置を定義しています。FOSSによりオラクルが規定したいくつかのオープソースライセンスのソフトウェアに関して、MySQLと一緒に利用しても、オープンソース側のライセンスは変更する必要がありません。FOSSの範囲であれば、GPLを適用せずにコミュニティ版を利用できるケースがあるということです。関連するソフトウェアを対象としてライセンスがどうなるのかを検討すると、ApacheやPHPは本来のランセンスで利用でき、INTER-Mediatorも本来のMIT Licenseで利用が可能であることは確かです。

 ここで、[条件1]や[条件2]での「開発したソフト」がどの範囲までなのかということが問題になります。MySQLが主張するGPLv2では、MySQLを利用した全ての開発物を配布する際にはソースコードも譲渡すれば違反しないと読み取れる内容です。したがって、全ての開発物を複製・配布する際にはソースコードを引き渡すのが「必要である」という解釈がなされるわけです。しかしながら、FOSSを記述したサイトのQ&Aの最初の項目には、FOSS自体がMySQLのクライアントライブラリにおいてGPL以外のライセンスを可能にしているものだと説明されています。例えばPHPのMySQL向けドライバーは、MySQLが提供するライブラリをPHPから利用できるようにしたものであり、MySQLクライアントと強く結びついたものです。PHPのドライバーは明らかにMySQLを基にして作られたものであり、FOSSが宣言されていなければ、PHPのMySQLドライバーはGPLにしなければならないと言えますが、FOSSによってPHPライセンスであることを主張できます。

 この点を考慮すれば、GPLの及ぶ範囲すなわち「開発したソフト」は、ライブラリ利用や完全統合といった強いソフトウェアの結びつきに対して適用され、「プロセス間通信」や「ネットワーク経由の通信」のような独立プロセス間を接続した場合には適用されないと解釈できます。したがって、コミュニティ版をそのまま使い、Apache+PHPでサーバーを組み、INTER-Mediatorでシステムを作ったときに、自分で作ったHTMLやJavaScriptのプログラムなどは、条件にある「開発したソフト」に該当せず、GPLの及ばない範囲として独自にライセンスを適用できることを意味していると読み取れます。ただし、これは記述されている事実を基に判断したことであり、Webサーバーや開発したアプリケーションに対してGPLの適用はしないと明確に書かれてはいないということをどのように考えるかにかかわる問題でしょう。

 以上の解釈を元に、MySQLのコミュニティ版で稼働するINTER-Mediatorで受託開発をしたシステムを納品する場合について、いくつかの事例で考えてみます。自社で使用するシステムを開発する場合は[条件1]に該当するため、コミュニティ版を利用できます。顧客が契約したプロバイダのレンタルサーバーですでにMySQLをサービスとして稼働しているような場合は、受託開発部分にはGPL適用部分がないので[条件1]に該当し、コミュニティ版を利用できます。顧客が所有するサーバーにセットアップする場合、すでにMySQLがセットアップされているなら[条件1]に該当し、コミュニティ版を利用できます。一方、MySQLのセットアップを請け負った場合はやや難しいですが、顧客が入手したMySQLのセットアップ作業を代行するのであれば[条件1]に該当し、コミュニティ版を利用できます。一方、納品物に「MySQL」あるいは「MySQLセットアップ」という項目があり、業者側がMySQLを取得して顧客のサーバーにインストールするとしたら、クライアントライブラリも含まれるため[条件1]には該当しません。また、MySQLを搭載したサーバーとして納品する場合も最後の状況と同様です。この場合、開発した部分はGPL運用しなくてはいいものの、納品先でGPL運用する必要がある素材を渡すことになります。一般には、そのようなソースコード公開の必要がある品目を使用するよりも、商用版を購入してシステム全体を顧客が独占的に使用できる状態にする方が望まれるのではないかと思われます。

MySQLで使用するキャラクタセット

 本稿を執筆時点では、Ver.5.7がリリースされていますが、プロバイダーにあるものなどを含めて、Ver.5.5〜5.7が混在している状況です。バージョンの違いでまずは気をつけなければならないことは、Unicodeサポートです。Ver.5.1でUTF-8をサポートしていますが、この時は長さが3バイトまでしかサポートしていませんでした。日本語のカナや漢字のほとんどはUTF-8では3バイトですが、スマホの普及とともにUTF-8で4バイトになる文字も、クライアントで利用できるようになってきました。代表的なものは絵文字ですが、「𥔎」(サキ;石偏に立可)などの一部の人名で使われるような漢字も含まれています。3バイトまでのキャラクタセット名が「utf8」なのに対して、4バイトまでのUTF-8の文字を利用できるキャラクタセットは別の名前「utf8mb4」となりました。これはデータベースの設定やあるいはスキーマ定義の時などに意識してutf8mb4と記述をしなければなりません。Ver.5.5.3からのサポートなので、入手できるVer.5.5のものでは原則利用できると考えて良いでしょう。

インストーラを利用したインストール

 MySQLは、macOSやWindows向けのインストーラーを配布しているので、原則として、それを使えばOKです。ただし、ダウンロードにはユーザー登録が必要です。ダウンロードには、ダウンロードのページから適切なエディションやOS等を選択すれば可能です。Linuxの場合は、yumやapt-get、aptitude等を使うことになります。この時、公式のレポジトリでは古いバージョンしか入手できないかもしれません。これらのコマンドによるインストール機能向けのインストーラーも、MySQLのサイトで入手できます。ダウンロードのページで、サブメニューを見ると、Yum Repository、APT Repository、SUSE Repositoryといった項目が見えます。これらのページから、レポジトリとしてMySQLが用意した最新バージョンをインストールできる箇所を追加できる仕組みを提供しています。ここでの説明を見て、Linux上でレポジトリを追加して、インストール作業をすれば良いでしょう。

 リスト9-1-1は、CentOS 7での例です。最初のコマンドは、MariaDBのクライアントライブラリが入っていて、それが問題になる場合があるので、削除しています。2つ目のコマンドでレポジトリを追加します。URLは、「Yum Repository」のページにある「Download」のリンク先のURLを右クリック等で表示されるメニューで文字列で得て、それを指定すれば良いでしょう。その後、インストールし、バージョンを確認して、systemdの設定を行い、サービスの起動と起動時にサービスが自動的に起動できるようにしています。なお、サーバーのパッケージのインストールのみで、通常は利用できます。これでクライアントのソフトウェアもインストールされます。Ubuntuではパッケージ名は「mysql-server」となっています。

リスト9-1-1 CentOS 7でMySQLサーバーをインストールする例
sudo yum -y remove mariadb-libs
sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
sudo yum install -y mysql-community-server
mysqld --version
systemctl start mysqld
systemctl enable mysqld

 いずれの方法でインストールをしても、データベース領域の初期化が行われ、あらゆる権限を持ったrootアカウントを自動的に作成します。インストーラーがあるものは、途中でそれをダイアログボックス等で表示するので、基本的にはそこで書き留めるか、画面ショット等を作成しておくのが良いでしょう。CentOSのインストーラーだと、ログファイルにそのパスワードが残ります。例えば、CentOSにVer.5.7をインストールすると、/var/log/mysqld.logにその情報が残ります。そのファイルで、例えば、リスト9-1-2のような行を検索します。この場合のrootのパスワードは「_4WqoPzrPNdx」です。

リスト9-1-2 mysqld.logに残るルートのパスワード
2016-03-28T16:04:29.856241Z 1 [Note] A temporary password is generated for root@localhost: _4WqoPzrPNdx

 インストール後、mysql_secure_installationコマンドを実行するようにメッセージが出てきます。これを実行することで、セキュリティ上の問題点となりそうな状態を、そうでない状態にしてくれます。以下の処理を行いますが、rootのパスワードの変更以外は、するかしないかの選択、つまりYes/Noの選択です。通常はYesを選んで設定変更をすべきですので、コマンドを実行して設定を変更しておきましょう。なお、rootパスワードについては、特にVer.5.7では複雑な文字列にしなければなりません。ここで適当にパスワードを変更するのは意外に難しいので、後から変える方がいいかもしれません。

MySQL向けのスキーマはどこまで記述が必要か

 スキーマ定義では、テーブルとビューを定義します。テーブルでは、テーブル名やフィールド名とその型を記述するのは当然ですが、INTER-Mediatorの動作上はそこままでほぼOKです。ただし、主キー値を示す「primary key(フィールド名)」等の記述と、検索やソートに使用するフィールドに対するインデックスは必ず作成してください。なお、主キーについては定義ファイルでkeyキーで指定でき、スキーマ上での主キーをそのまま指定することがほとんどですが、動作上は別のフィールドも指定できますし、それが一意な値なら編集もできます。その場合はkeyキーに指定する値にインデックスを作成しておきます。

 一方、外部キー制約については、必ずしも必要ではありません。制約として設定しておいて、データベース上に不整合が起こらないようにすることが必要と考えるのであれば、記述しても構いません。しかしながら、実際の動作は定義ファイルのrelationキーでの指定が利用されるため、データベーススキーマ上にテーブル間の関係は記述してもINTER-Mediatorとしては使いません。通常、不整合が発生するようなユーザーインターフェースを作ることはありえないと思われるので、正しくユーザーインターフェースを作成していれば、外部キーの指定はスキーマになくてもいいでしょう。データベースの利用方法や設定については『2-1 データベースからの取り出し設定』を参照してください。

MySQLの設定のポイント

 MySQLの設定ファイルと言えば、/etc/my.cnfの変更ということになりますが、実際にはいろいろなファイルで指定ができます。したがって、現在、どんなパスのファイルが使用されるかを知る必要があります。そのためには、「mysql --help」を実行します。もちろん、mysqlコマンドのヘルプを表示しますが、その中にリスト9-1-3のような記述が含まれていて、2行目のパスのファイルが順次読み込まれます。つまり、/etc/my.cnfなどのファイルが読み込まれますが、これらの順番に読み込みを全て行い、ファイルがあれば、その設定も読み込まれます。もし、複数のファイルで同一の設定対象に対する定義がある場合には、後から読み込んだファイルの内容が有効になります。/etc/my.cnfを読む限りは、このファイルはMySQLのアップデート時に上書きされる可能性があるので、自分自身の設定は別のファイルにするのが良いと記載されています。INTER-MediatorのVMは、/etc/mysql/my.cnfに実際の設定を行っています。

リスト9-1-3 「mysql --help」コマンドの出力の一部
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf

 クライアントからの接続をするためには、ホスト接続の場合はポート番号、ソケット接続の場合はそのパスを知りたくなります。mysqlshowコマンドに--helpをつけて実行した結果の末尾に変数の値が出力されますが、その中にあるsocketやportを見ることで参照可能です。しかしながら、この場合は、my.cnfに設定がある場合には、この方法で参照できますが、コンパイル時の既定値で稼働させた時には、この方法でソケット等が確認できない場合もあります。

リスト9-1-4 「mysqlshow --help」コマンドの出力の一部
Variables (--variable-name=value)
and boolean options {FALSE|TRUE}  Value (after reading options)
--------------------------------- ----------------------------------------
character-sets-dir                (No default value)
default-character-set             utf8mb4
count                             FALSE
compress                          FALSE
	:
plugin-dir                        (No default value)
port                              3306
show-table-type                   FALSE
socket                            /var/run/mysqld/mysqld.sock
ssl                               FALSE
	:

 mysqlshowコマンドで参照できない場合には、mysql_configコマンドを使用します。ただし、このコマンドはWindowsでは使えませんが、LinuxやmacOSでは利用可能です。引数なしはUsage:が見えるのですが、その下のOptions:の右の [...] で示されているのは、実際に設定された値です。この値がコンパイル時に指定されたもので、ソケットやポートは設定ファイルで変更していない場合にはこの設定に従うことになります。もし、設定ファイルで変更している場合には、ここで見える値は実際には使用されていないソケットのパスになります。

リスト9-1-5 「mysql_config」コマンドの出力の一部
Usage: /usr/bin/mysql_config [OPTIONS]
Options:
        --cflags         [-I/usr/include/mysql -DBIG_JOINS=1  -fno-strict-aliasing    -g -DNDEBUG]
        --include        [-I/usr/include/mysql]
        --libs           [-L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -lm -ldl]
        --libs_r         [-L/usr/lib/x86_64-linux-gnu -lmysqlclient_r -lpthread -lz -lm -ldl]
        --plugindir      [/usr/lib/mysql/plugin]
        --socket         [/var/run/mysqld/mysqld.sock]
        --port           [0]
        --version        [5.5.49]
        --libmysqld-libs [-L/usr/lib/x86_64-linux-gnu -lmysqld -lpthread -lz -lm -lwrap -lcrypt -ldl -laio]
        --variable=VAR   VAR is one of:
                pkgincludedir [/usr/include/mysql]
                pkglibdir     [/usr/lib/x86_64-linux-gnu]
                plugindir     [/usr/lib/mysql/plugin]

設定ファイルへの記述

 my.cnfファイルに記述する内容としては、キャラクタセットを「default-character-set=utf8mb4」で指定しておくのが確実です。プロセスごとに [ ] で囲ってそれ以降の行に「変数名=値」の行を記述します。例えば、[mysqld]は、mysqldつまりMySQLのサーバーに対する処理を記述します。なお、現実には同じサーバーでMySQLのクライアントも利用しますし、SQLダンプでmysqldump等も使います。これらの設定も、my.cnfファイルに記述しておくと便利でしょう。リスト9-1-6はmy.cnfファイルの一例です。実際にはもっと多くの項目を設定することもあるでしょう。ソケットのパスを変えたいような場合でも、こちらに記述をすれば、コマンド起動時にパラメーターとして記述する必要は無くなります。なお、設定ファイルへの記述に問題があると、MySQLが起動しません。その場合、/var/log/mysql/error.logなど、エラーログを確認することで、問題のある記述がどの部分かは特定できます。

リスト9-1-6 my.cnfファイルの例
[mysqld]
validate_password_policy = LOW
character-set-server = utf8mb4
default_password_lifetime = 0
sql_mode = TRADITIONAL

[mysql]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4

[mysqldump]
default-character-set=utf8mb4

 ここで、mysqldにある設定項目は、Ver.5.7になってからの過去のバージョンとの互換性を確保するために、よく追加されるような項目を記述しました。まず、既定値のパスワードポリシーは非常に厳しく、複雑な文字と思って作ったものでもその一部に単語として読めるものがあると排除するなど、手作業でパスワードを変更するのは一苦労しそうです。「validate_password_policy = LOW」にすれば、ルールはかなり緩くなり、8文字以上であればパスワードとして認められます。その状態で、一定以上の複雑なパスワードを管理者が責任を持って指定することで、データベースサーバーのパスワード運用は問題なくできると考えます。このパスワードポリシーを運用するために、MySQLはプラグインを利用します。MySQLのサイトのレポジトリを利用してインストールした場合はこのプラグインが組み込まれます。

 Ubuntu 16.04.1の場合には標準のレポジトリからのインストールでMySQL Ver.5.7が入ります。しかしながら、パスワードチェックのプラグインが組み込まれないため、validate_password_policyの記述自体の解釈ができずエラーとなってMySQLが起動しません。そのままプラグインなしで利用するなら、validate_password_policyの記述は削除してください。

 MySQL Ver.5.7.4以降は、パスワードの有効期限が360日となっています。つまり、その期間内にパスワードの変更を行わないと、セットアップした1年後くらいにいきなり接続ができなくなります。しかしながら、これは、明らかに忘れてしまいそうな設定です。「default_password_lifetime = 0」と設定すれば、パスワードは無期限に使えます。なお、Ver.5.7.11以降は既定値でパスワードの期限は無期限となりました。

 MySQLはバージョンごとにSQLコマンドのエラー時の処理などが違っています。「sql_mode = TRADITIONAL」を使えば、Ver.5.6以前に一番近い状態になります。SQLのエラーが出る場合には、この方法を試してみると、うまく行く場合もあります。INTER-Mediatorは内部でSQLコマンドを生成しているため、「SQLコマンドを変更する」ためにはソースコードを変更しなければなりませんが、それは簡単なことではありません。sql_modeをTRADITIONALにしなくても原則稼働するようにチェックはしていますが、漏れがあるかもしれません。もし、生成されたSQLに問題がありそうなら是非ともバグレポートをするとともに、この設定でMySQLの動作を古いバージョンと同様になるようにして運用をしてみてください。

MySQLの「8KBの壁」問題

 MySQLでのストレージエンジンはInnoDBを使うことが一般的でしょう。MySQL 5.5 以上では、InnoDB がデフォルトのストレージエンジンとしてセットされています。InnoDBはトランザクションにも対応していますが、一方で書き込みのバッファのサイズの制限があって1レコードのサイズは8KB以上にはできないという仕様があります。長い文字列を扱うTEXT型等では、最初の768バイトだけがその8KBの中に含まれ全データは別途保存されますが、言い換えれば、TEXT型のフィールドが11個以上あって、それぞれ768バイト以上のサイズであるなら、8KBを超えてしまい、レコードの書き込みができなくなります。これが「8KBの壁」と呼ばれる問題です。これはMySQLのAntelopeファイルフォーマットの制限です。なお、Ver.5.6まではAntelopeが既定値でした。

 このようにTEXT型が10個を超えるということは普通にありそうです。現状では、改良されたBarracudaファイルフォーマットを使用すべきです。また、Ver.5.7は既定値がBarracudaになっています。こちらだと、長いデータはすべて別のところに記録して、8KBの1レコードのバッファ領域には1フィールドあたり20バイトしか使わなくなりました。TEXT型フィールドを400個もひとつのテーブルで作るようなことは普通はありえないことから、制限に当たるようなことはないでしょう。

 現在のファイルフォーマットを得るには、mysqlコマンドでrootユーザーでログインをして、リスト9-1-7のようなSHOW GLOBAL以下のコマンドをプロンプトで打ち込み、InnoDBのファイルに関する変数を見ます。最初のinnodb_file_formatの値より、Antelopeがファイルフォーマットとなっています。

リスト9-1-7 ファイルフォーマットの確認
mysql> SHOW GLOBAL VARIABLES LIKE '%innodb_file_%';
+--------------------------+----------+
| Variable_name            | Value    |
+--------------------------+----------+
| innodb_file_format       | Antelope |
| innodb_file_format_check | ON       |
| innodb_file_format_max   | Antelope |
| innodb_file_per_table    | OFF      |
+--------------------------+----------+
4 rows in set (0.00 sec)

 もし、ファイルフォーマットがAntelopeになっているのなら、リスト9-1-8のような定義を、my.cnfファイルに記述します。例えば、INTER-MediatorのVMのシステムの場合だと、/etc/mysql/my.cnfの中の[mysqld]セクションの適当な場所に定義を追加します。

リスト9-1-8 my.cnfに追加する内容
[mysqld]
innodb_file_per_table
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda

 ここでテーブルのファイルフォーマットを確認します。リスト9-1-9では、テーブルpersonのRow_formatを見れば、Compactになっています。これはAntelopeのテーブルファイルの形式です。Barracudaを利用するには、Row_formatはDynamic、あるいはCompressedを指定します。そこで、既存のテーブルであれば、ALTER TABLEコマンドでROW_FORMAT変数を書き換えることで、フォーマットをDynamicにできます。なお、Compressedは圧縮して保存する形式です。

リスト9-1-9 テーブルのフォーマットをDynamicにする
mysql> use test_db;
mysql> SHOW TABLE STATUS LIKE "person" \G
*************************** 1. row ***************************
           Name: person
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 3
	:
mysql> ALTER TABLE person ROW_FORMAT=DYNAMIC;
mysql> SHOW TABLE STATUS LIKE "person" \G
*************************** 1. row ***************************
           Name: person
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 3
	:

 なお、この後、新たにテーブルを作ると、やはりAntelopeのCompactフォーマットになってしまいます。そこで、CREATE TABLE文では、「CREATE TABLE test2 (id int) ROW_FORMAT=Dynamic;」のように、フィールド定義の後の設定に「ROW_FORMAT=Dynamic」を追加する必要があります。もちろん、Ver.5.7では最初からBarracudaが使われており、このようなことをする必要はありません。

 ここでVer.5.6までで気をつけたいのは、mysqldumpコマンドを利用してデータをSQLコマンドで出力するときです。通常、テーブルを定義するコマンドも出力しますが、上記の方法でROW_FORMATをDynamicにしても、mysqldumpコマンドが出力するCREATE TABLEコマンドにはROW_FORMATの記述がありません。その場合の対処法がJhonny Everson氏によってStack Overflowによって記載されています。ROW_FORMATの記述をsedを使って書き直すか書き足すかをする必要があります。

PostgreSQLのインストール

 PostgreSQLは古くからあるデータベースで、その起源は80年代にまで遡ります。早くから標準SQLの仕様のかなりの部分をカバーした本格的なRDBとして評価を得てきました。しかしながら、2000年前後は世界的に見ればSQLの制約があってもスピードの速いMySQLへの注目が集まる一方、なぜか日本ではPostgreSQLの方の割合が海外より高かった印象があります。日本人は「標準SQLに近い」ことに価値を感じるのかもしれません。その結果、日本語での情報も古くからインターネットを中心に共有されてきました。その後、PostgreSQLのVer.8の途中くらいからはMySQLとの性能差はほとんどなくなるくらい、パフォーマンスを上げてきました。もっとも、MySQLも制限のあったSQLのさまざまな機能をサポートしてきていることもあって、結果的にこれら2大オープンソースデータベースに大きな差がないのが現状です。

 PostgreSQLとMySQLの比較の上で語られることが多いのは、ライセンスです。PostgreSQLはBSDライセンスであり、PostgreSQLを使用して作成したシステムのソースコードの公開は必要なく、ライセンスを明示すれば再配布は可能です。そのため、MySQLに比べてより確実な「フリー」であるソフトウェアと認識されています。

 本稿を執筆時点では、Ver.9.5の安定版、そしてVer.9.6のベータ版がリリースされていますが、プロバイダーにあるものなどを含めて、Ver.8.4、9.0〜9.5が混在している状況です。macOSやWindows向けにはインストーラーを配布しているので、原則として、それを使えばOKです。ダウンロードには、ダウンロードのページから適切なエディションやOS等を選択すれば可能です。Linuxの場合は、公式のレポジトリでは古いバージョンしか入手できないかもしれません。しかしながら、ダウンロードのページにはディストリビューションごとのインストール方法が記載されており、基本的にはパッケージシステムに新しいレポジトリを追加して、そこからバイナリをインストールする形式です。インストールするパッケージは「postgresql」あるいは「postgresql-9.5」などのバージョン入りのものも含めて、データベースサーバーのパッケージだけで基本的には利用できます。サーバーだけでなく、クライアントとして動作するためのライブラリやコマンドなども一緒にインストールされます。データベースの利用方法や設定については『2-1 データベースからの取り出し設定』を参照してください。

SQLiteのインストール

 SQLiteはプロセスを起動しないタイプのデータベースです。ネットワークでの共有はSQLiteだけではできませんが、データベースファイルを用意するだけでいいので、手軽に利用できることがあります。利用するためにはOSに対応したライブラリが必要ですが、SQLiteのサイトからダウンロードできます。Linuxのパッケージでは、そのままの名前「sqlite」で検索をかけてみて、レポジトリの内容を確認しましょう。現在はUnicode対応したVer.3系列が主に利用されていますが、あまりバージョン間の違いについては話題にならないくらいなので、バージョンアップで大きな違いが発生するということはあまりないソフトウェアではないかと思われます。

 SQLiteは「パブリックドメイン」であるとして、ライセンス契約をするという考え方は基本的にはなく、自由に利用できるとされています。ただし、パブリックドメインという考え方が受容できない状況や、どうしてもライセンス契約が必要という場合には6000ドルでライセンス契約できることになっていますが、インターネット検索しても話題にもなっていないようなので、ほとんどの利用者はパブリックドメインで使用していると思われます。

 SQLiteの使用においては、データベースファイルのパスを指定するだけです。ファイルが存在しなければ自動的にファイルは作られます。INTER-Mediatorのサンプルファイルは「/var/db/im/sample.sq3」というパスを利用しています。拡張子は統一したものはなく、また、SQLite自体も拡張子はどんなものでも動作はするようです。注意が必要なのはファイルのアクセス権です。このファイルは、PHPが稼働しているプロセスのユーザーに対して読み書きの両方の権限が必要です。LinuxやmacOSの場合、Apache 2の内部でPHPは動くので、www-dataや_apache、_wwwなどのApacheのユーザーが何かをpsコマンド等で調べてみて、そのユーザーに対するアクセス権を設定します。そして、ファイルだけでなく、前のパスの例では、そのファイルが存在するフォルダー「/var/db/im」も、同様にApacheのユーザーで読み出しだけでなく書き込みの権限が必要です。実際には、ひとつのファイルではなく、複数のファイルを利用するため、フォルダーにも書き込み権限がないと、他のファイルが作成できず、データベースとしては動作しなくなります。データベースの利用方法や設定については『2-1 データベースからの取り出し設定』を参照してください。

SQL Serverのインストール

 MicrosoftのSQL Serverは、Windows版だけでなくLinux版もあります。開発に利用するDeveloper版であればライセンス料が不要ですので、手軽に試用することもできます。むしろ最近は、Azure上でのデータベースとしてSQL Serverが使いやすい状態になっていることもあり、注目されているとも言えるでしょう。

 Ubuntu 16 Serverだと、「sudo apt-get install -y mssql-server」でサーバー本体はインストールできます。さらに、サーバーを利用するコマンドであるsqlcmdを利用できるようにするためには、以下のコマンド入力してセットアップが必要になります。いくつかのLinuxディストリビューションについては、Microsoftの「SQL Server on Linux」というページに記載があるので、そちらも参考にしてください。

リスト9-1-10 SQL Serverのツールのインストール
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo add-apt-repository "$(curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list)"
sudo apt-get update
sudo apt-get install -y mssql-tools unixodbc-dev
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc

FileMaker Serverのインストールと設定

 2016年5月にはVer.15が登場したFileMaker Serverですが、Ver.13でサーバーの動作形態が変わったことや、セキュリティへの対応等によって、インストール自体は難しいものとなっています。もちろん、FileMaker Server自体のインストーラーを使ってインストールすれば基本的にはうまくいくはずです。しかし、インストールしようとするターゲットマシンの状況に応じてさまざまな注意点があります。

インストール時の注意点

 FileMaker Serverは、独自にWebサーバーをセットアップすることを原則としています。インストール以前にWebサーバーが稼働していたら、インストールはできません。例えば、macOSでServer.appをセットアップして、Webサービスを起動していたら、その状態を感知して、FileMaker Serverのインストールはストップしてしまいます。FileMakerのインストーラはWebが利用されていることを「httpdというプロセスがある」というかなり手を抜いた判定をしています。したがって、Server.appを使っていて、WebDAVでのファイル共有をオンにしていたり、他のさまざまなサービスが稼働していると、インストールは拒否されます。WebDAVは一度オンにすると、オフにしてもhttpdは起動し続けるなど、Server.appをインストールしたmacOSですでに運用で使っている場合には、FileMaker Serverは簡単にセットアップできません。さまざまなサービスを手作業で止める必要がある場合もあります。Server.appを使っていなくても、以前あったWeb共有がオンのままになっていたり、MAMPやXAMPPによってhttpdが稼働していたりと、さまざまな理由でhttpdは起動した状態になっています。それらすべてを止めなければなりません。筆者のブログでいろいろな事例を紹介しています。参考にしてみてください。FileMaker Serverは、httpやhttpsを80/443ポート以外でも運用できるようになっているにもかかわらず、インストーラがそうした手抜きな判定を行っている点は早急に改めるべきところでしょう。

 Windows版のFileMakerは、対応OSがWindows Serverのみとなっています。通常のWindows 10等は動作対象になっていません。インストールできなくはないようですが、トラブル等があった時には自分で解決しなければなりません。また、OSによってはMicrosoftから配布されているKB2919355の情報に従ってアップデートソフトウェアをインストールする必要があります。なお、Windows 2012 R2は、KB2919355がすでに適用された状態になっています。適用されているかどうかは、コントロールパネルの「システムとセキュリティ」にある「Windows Update」の「更新履歴の表示」で確認ができます。FileMakerデータベースのサーバー機能は、5003番ポートを利用しますが、Windows 2012以降はポートが閉じられた状態になっており、FileMaker Serverを利用してもそのままではFileMaker Pro等からの接続ができません。ポートを開くには、「サーバーマネージャー」の「ツール」から「セキュリティ強化されたファイアウォール」を選択して設定ユーティリティを起動し、左側で「受信の規則」を選択し、右にある操作パネルから「新しい規則」を選択して、TCPの5003番ポートに対しての許可を与えます。

 INTER-Mediatorは、FileMaker ServerのカスタムWeb機能のひとつであるXML共有とPHP共有を利用します。以前のINTER-Mediatorは、FileMaker Serverとの通信にFX.phpを使用していたためXML共有のみで稼働していました。現在、FX.phpだけでなくCWPKitや独自実装の部分でPHP共有も使用するようになっているため、XML共有とPHP共有の両方を利用できるようにしてください。データベースの利用方法や設定については『2-1 データベースからの取り出し設定』を参照してください。

 FileMaker Serverのインストール方法については、マニュアルを参照してください。マニュアルにはしっかり手順は記載されていますし、よくあるトラブルはファイルメーカー社のサイトで検索すれば、見つかります。また、インターネット上での各種コミュニティでも情報があるので、トラブルに対する対処は何らかのヒントはあるはずです。なお、Linux版は残念ながらありません。

FileMaker Serverのライセンス

 FileMaker Serverはパッケージでの販売は現在はされておらず、通常は5種類のライセンス(FLT、AVLA、VLA、ASLA、SLA)のいずれかのライセンスとして購入します。VLAは購入数が増えれば単価が下がる「ボリュームライセンス」で、FileMaker Serverは1ライセンスからの購入が可能です。SLAは組織の規模に応じて価格が決定され、その組織内で利用できる「サイトライセンス」です。名称にAが付くものは年ごとの契約を行い、Aが付かないものは特定バージョンに対する継続使用契約です。FileMaker Ver.15から、FileMaker Licensing for Teams(FLT)がライセンスのひとつとして加わりました。FLTには購入ユーザー数分までが可能なFileMaker Server 15のライセンスがひとつ含まれます。ライセンスユーザー数は5ユーザー単位で100ユーザーまでの設定があります。最小単位である5ユーザーであれば、年間96,000円でシステム構築、カスタムWebアプリケーションの公開ができますから、スタートアップには最適です。なお、学校教育関係・NPO向けにはさらに低価格の設定があり、5ユーザーライセンスで57,600円となっています。なお、INTER-Mediatorを使う前提で費用を最小限にしたいのなら、AVLAでFileMaker Serverを33,000円で1本購入し、同時にAVLAでFileMaker Pro(12,600円)ないしはAdvanced(20,400円)を購入するという方法があります。AVLAでFileMaker ProまたはAdvancedを購入するには5ライセンス以上の購入が必要ですが、AVLAのFileMaker Server所有者なら1本から購入可能です。これらのライセンスとINTER-Mediatorの利用について気になるところだと思われます。

 FileMaker ProやFileMaker GoなどからFileMaker Serverへのネットワーク接続は、保有している同時接続ライセンス数やユーザー接続ライセンスに制限されますが、カスタムWeb(CWP)に関しては不必要です。例えば、5ライセンスのものを利用しても、PHPなどで作成したWebアプリケーションから接続する場合はライセンス上あるいは機能上の接続数や接続範囲の制限はありません。もちろん、処理性能の限界はありますが、ライセンスで定義されたクライアント数の制限はかからないということです。FileMaker社によるとCWP接続は、持続的な接続よりもむしろ、同時にリクエストされるイベントを基にしたものであると認識されており、そのため、接続のためのライセンスは不要としているのです。

 注意したい点は、カスタムWebとWebDirectは異なる仕組みであるというところです。WebDirectはライセンスされるユーザー数が決められていますが、カスタムWebはその対象外です。

 なお、サイトライセンス(ASLA、SLA)については、ライセンスそのものが単一組織に対してのものであり、Web接続して利用する場合であっても組織内からである必要があります。機能上はINTER-Mediatorで作ったアプリケーションを誰でもアクセスできるようにすることはできます。しかしながら、FileMaker社のライセンス情報に関するページでは『SLA にてライセンスされた企業が第三者向けにサービス提供すること、およびインターネットを含むその他ネットワーク経由で不特定多数にアクセスさせることを禁止しています。』とあることから、ASLAあるいはSLAで不特定多数にサービスを展開することはできません。ご注意ください。

 FileMakerデータベースに納めた情報をINTER-Mediatorを使って構築したシステムを使ってカスタムWeb公開するには、AVLA、VLA、またはFLTのFileMaker Serverライセンスを購入して運用するようにしてください。これらのどれかのライセンスを用意すれば、一般ユーザー向けのアンケート収集、会員サイトやオンラインショップなどの業務を運用する場合や、地域のコミュニティサイトを構築できます。

 なお、ライセンスの条件は当然ながら契約書に従うことになります。筆者はあらゆるFileMaker社のライセンス条文を確認してはいません。また、ライセンス条項は時に変更が加わることもあります。実際の使用に当たっては、必ずご自分で再確認をしてください。

このセクションのまとめ

 INTER-Mediatorでサポートされているデータベースを利用するための情報について、MySQLを中心に説明をしました。いずれのデータベースも、インストールや運用の情報は、製品に添付されていたり、インターネットで検索することができます。それらの情報を有効に活用しましょう。

9-2Webサーバーのインストールと準備

サーバーサイドには、データベース以外にPHPが稼働するWebサーバーが必要です。もちろん、適度に分散したり、あるいはデータベースサーバーとWebサーバーが別ホストといったこともあるかもしれませんが、基本は「PHPが稼働するWebサーバー」です。

Webサーバーのインストールと管理

 WindowsではIIS、LinuxやmacOSではApacheが最も一般的なWebサーバーです。このところ、nginxも使われ始めていますが、IISやLinuxを使う上では、最新版のこれらのWebサーバーサービスを使うことで、おおむね目的は達成できるでしょう。また、WindowsでApacheを使うにはXAMPPを利用する場合もあるでしょう。XAMPPにはMac版やLinux版もあります。こちらだと、PHPとMySQLも一緒にインストールできるので、手軽にWebサーバーを始めることができます。ここでは、nginxやXAMPPについてはそいういうソフトウェアがある点だけを紹介するに留めます。

 Webサーバーの管理では、「ドキュメントルート」と呼ばれるWebサーバーで公開されるファイルシステムの領域の中の一番上位のディレクトがどこにセットされているかを知ることが重要です。また、Webサーバーを稼働させるための設定がどのディレクトリにあるのかを知る必要があります。

WindowsでのWebサーバー

 IISをインストールするには、Windowsサーバーの管理ツール「サーバーマネージャー」で、「役割の追加」の作業を行い、「Webサーバー(IIS)」を追加します。他に必要なサービスなどは通常は自動的に判定してインストールをしてくれます。

 IISはWindows Serverの管理ツールを利用する事以外はありえないと思うので、それを使いこなしましょう。通常は、Cドライブのルートにinetpubフォルダー作られて、そこのwwwrootフォルダーがIISのドキュメントルートになっています。ルートのディレクトリの変更なども管理ツールで行います。また、ログファイルはCドライブのinetpubフィルダ内にあるlogsフォルダーの中のLogFilesフォルダーが既定値となっています。ここにW3SVCという名前で始まるファイル名で、ログファイルが作られています。エラーログなどそのほかのログは、logsフォルダー内にフォルダーで分類して作られます。

LinuxでのWebサーバー

 Linuxについては、通常はOSのディストリビューションでかなり新しいバージョンのビルドが常に手に入ります。例えば、apt-getでは「apache2」を、yumでは「httpd」をインストールすれば良いでしょう。

 UNIX系ではOSやディストリビューションによって管理方法が微妙に違っています。ドキュメントルートは、以前は/var/wwwが多かったのですが、最近のディストリビューションでは/var/www/htmlであることが一般的となってきています。一方、設定ファイルについては、/etc/httpdの場合と、/etc/apache2の場合があります。いずれも、そのフォルダーにあるhttpd.confファイルが主要な設定で、そのファイルから別のファイルが取り込まれる設定になっているのが一般的です。その取り込まれる側の設定ファイルに、ホスト名ごとの設定やモジュールごとの設定が含まれるのが一般的です。そこでファイルを作ったり修正すれば事足りる、という簡単な話ではありません。ディストリビューションによって最適な管理手段が違う場合があります。例えば、CentOSは「設定ファイルを変更する」ことが主要な作業ですが、Ubuntuではモジュールやサイトの有効/無効をa2enmod、a2dismodといったコマンドを使い、設定ファイルをmods-availableに用意するとともにコマンドを使ってmods-enableディレクトリにシンボリックリンクを作成し、Apacheはmods-enablesディレクトリの設定だけを取り込むといったことを行います。このようなディレクトリに設定ファイルを用意して、コマンドでモジュールだけではなく、サイトの設定(a2ensite、a2dissiteコマンド)や、あるいは設定ファイルそのもの(a2enconf、a2disconfコマンド)の有効/無効を指定します。他のOSで設定ファイルの変更に慣れていると、Ubuntuの管理方法は最初は戸惑いますが、Ubuntuでは用意されている手法を活用することが重要ですので、まずはどのような手法なのかを確かめておきましょう。

 なお、最近のLinuxではCentOS 7のように、ファイアウォールが最初からセットアップされていて、一切のサーバー動作ができない状態になっている傾向が強くなりつつあります。セットアップしたけれども繋がらないという場合には、ファイアウォールで一切ポートが開いていなかったというのがよくある原因です。セットアップしたOSはもちろん、スイッチ等ネットワーク上でのファイアウォールを含めて、その状態を確認した上でトラブルシューティングを進めましょう。

macOSでのWebサーバー

 macOSでは以前は「パーソナルWeb共有」として、システム環境設定からWebサーバーの起動もできましたが、Ver.10.8のMountain Lionからシステム環境設定よりその設定項目は消えました。しかしながら、必要なモジュールはすべてインストール済みになっていて、Webサーバーとして起動できます。リスト9-2-1のコマンドを入れればWebサーバーが起動し、再起動後も続けて利用できます。ドキュメントルートは、/Library/WebServer/Documentsで、設定ファイルは/etc/apache2です。ログファイルは、/var/log/apache2ディレクトリに作られるのが既定値です。

リスト9-2-1 macOSでWebサーバー機能を有効にする
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

 なお、macOSにServerアプリケーションをインストールすると、管理ツール上でWebサービス管理運用ができるようになります。既定のWebサイトのドキュメントルートは/Library/Server/Web/Data/Sites/Defaultですが、管理ツールを使ってバーチャルホストの追加などができるようになります。しかしながら、管理ツールで設定できる機能は限られています。さらにきめ細かい設定をしたい場合には設定ファイルを変更する必要も出てきます。最初に読み込まれる設定ファイルは、/Library/Server/Web/Config/apache2/httpd_server_app.confになりますので、ここから辿って必要な設定を見つけたり、あるいは設定を追加するファイルを探すなどします。ログファイルは/var/log/apache2ディレクトリに作られます。

PHPのインストール

WindowsでのPHP

 PHPのインストーラに関して、まずWindowsについてはさまざまな方法がありますが、Microsoftが配布しているWeb Platform Installerを利用してPHPをインストールするのが一番確実な方法です。ただし、更新頻度が低いこともあって、求めるバージョンのものがインストールされるかどうかはやや問題があると言えるでしょう。Windows Server 2012には対応していますが、Windows 10対応についてはリリース時期が古く明記されていません。ただし、WebMatrixのページからは、PHP7がダウロードできます。MicrsoftはPHP単体をリリースしているわけではなく、他のさまざまな素材のひとつとして配布しています。そのため、ページによって得られるものが違っており、どれを使うべきなのかはなかなか判断しにくいところですが、Web Platform Installerを利用するのが一番確実と考えられます。また、PHPのページでは、IISの設定を変更しながら手動でインストールする方法も説明されています。

LinuxでのPHP

 Linuxの場合はyumやaptでインストールはできますが、各バージョンが揃っているという状況ではなく、比較的古いバージョンのものです。新しいバージョンのものを入れたい場合には、レポジトリを追加する必要があります。例えば、リスト9-2-2はCentOS 7で、PHP 5.6をインストールする方法のひとつです。EPELというライブラリを入れた後、remiというレボジトリを利用しています。--enablerepoで、PHP 5.6のレポジトリに固定をして作業しています。加えて、必要なPHPのモジュールのインストールも行っています。

リスト9-2-2 CentOS 7でのremiレポジトリを使ったPHPのインストール
sudo yum -y install epel-release
cd /etc/yum.repos.d
sudo curl -O http://rpms.famillecollet.com/enterprise/remi.repo
sudo yum install --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel -y
sudo yum install --enablerepo=remi --enablerepo=remi-php56 php-mbstring -y
sudo yum install --enablerepo=remi --enablerepo=remi-php56 php-pdo -y
sudo yum install --enablerepo=remi --enablerepo=remi-php56 php-mysqlnd -y

 リスト9-2-3は、INTER-Mediator-Server VMを構築するスクリプトの一部を抜粋したものです。こちらはUbuntu Server 14です。このコマンドではVer.5.5.9のインストールを行いますが、Ver.5.6以上をインストールする場合には、ondrejというレポジトリを追加する方法がインターネットではよく見られます。ただし、Apache2もこのレポジトリのものを利用しなければなりません。詳細はこちらのサイトなどをご覧ください。

リスト9-2-3 Ubuntu Server 14でのサーバーモジュールのインストール
aptitude install apache2 --assume-yes
aptitude install openssh-server --assume-yes
aptitude install mysql-server --assume-yes
aptitude install postgresql --assume-yes
aptitude install sqlite --assume-yes
aptitude install libmysqlclient-dev --assume-yes
aptitude install php5-mysql --assume-yes
aptitude install php5-pgsql --assume-yes
aptitude install php5-sqlite --assume-yes
aptitude install php5-curl --assume-yes
aptitude install php5-gd --assume-yes
aptitude install php5-xmlrpc --assume-yes
aptitude install php5-intl --assume-yes

 Ubuntu Server 16.04.1では、パッケージ名を単に「php」と指定すれば、PHP Ver.7.0.8がセットアップされます。Ver.5系のPHPをインストールしたい場合には、「php5」というパッケージ名を利用します。Ver.7でも、リスト9-2-2およびリスト9-2-3に示したPHPのモジュールを入れれば原則問題ありませんが、これらに加えて「libapache2-mod-php」もインストールしてください。これにより、Apacheの設定としてPHPモジュールを利用する定義が加わります。以前はその定義はphpのパッケージに入っていたようですが、Webサーバーとしてnginxを利用する機会が増え複数の種類のサーバーを使い分けるようになったことが理由と思われますが、WebサーバーとPHPのつなぎの部分を、明示的に指定してインストールする必要が出てきています。

macOSでのPHP

 macOSで、OSに標準のApacheを稼働させた場合、PHPは初期値ではオフになっています。設定ファイルのルート(例えば、/etc/apache2)にあるhttpd.confファイルを開き、「#LoadModule php5_module libexec/apache2/libphp5.so」という記述の行の最初の#を取り除いて保存します。これで、PHPのApache用モジュールが有効になります。なお、Apache Webサーバーを再起動する必要があります。Serverアプリケーションをインストールした場合、管理ツールのWebサービスの設定に、PHPを使用するかどうかのチェックボックスがあるので、それをオンにすればPHPは機能します。

 macOSでPHPのライブラリ集であるpearを使えるようにするには、「/usr/lib/php/install-pear-nozlib.phar」というスクリプトをコマンドラインからsudoを使って実行します。これでpearコマンドは使えます。なお、homebrewやmacportsなどを使うと、使用するディレクトリなどが違ってきます。これらのパッケージシステムを使う場合には、該当するドキュメントをよく調べてください。

PHPのモジュールとphp.iniの設定

 PHPをインストールした結果を参照する代表的な方法は、PHPプロセッサで「phpinfo()」という関数をひとつ呼び出すことです。この関数はPHPの内部状態を検査して、その結果を見やすいWebページとして表示します。Webサーバーで公開しているディレクトリに、中身が「<?php phpinfo(); ?>」とだけ記述し、例えば、そのファイルをinfo.phpというファイルに保存します。ファイルがWebサーバーの公開ディレクトリのルートにあるなら、「http://ホスト名/info.php」とブラウザーに入力します。すると、サーバー側でphpinfo関数の処理が行われ、そのサーバーのPHPの状況が分かります。INTER-Mediator Server VMでは、「http://192.168.56.101」に接続してVMのホームを表示すると、「phpinfo()関数の実行」というリンクがあり、そこをクリックすると、phpinfo関数の処理結果が参照できます。

図9-2-1 phpinfo()関数の実行結果

 PHPをインストールすると、このページを必ず確認します。まず、一番最初のPHPのバージョンは当然として、「Loaded Configuration File」で、各種動作の設定を記述するphp.iniファイルのパスを確認します。パスは「/etc/php5/apache2/php.ini」となっているので、設定はこのファイルを書き直すのが基本です。しかしながら、そのすぐ先に、「Additional .ini files parsed」という設定もあり、他に読み込んでいるファイルもあります。これらはPHPのモジュールをインストールすると自動的に入ります。モジュールの動作を変更する場合は、php.iniではなく、その他の.iniファイルを変更した方がいい場合もあるでしょう。

 そして、必要なモジュールが含まれているかを、ページをスクロールして、あるいはページ内部を検索して確認します。例えば、図9-2-2は、PDOおよび関連するデータベースのPDO用ドライバーがインストールされていることが確認できます。タイトルの文字の「PDO」や「pdo_mysql」から判断します。

図9-2-2 phpinfo()関数の実行結果

 表9-2-1には、INTER-Mediatorの稼働に必要なモジュールを、phpinfo関数で表示されるページの見出しのキーワードで示しました。「必須のモジュール」は、これらがなくてはINTER-Mediatorが動かないものです。ただし、curlとmbstring以外は多くの場合は最初から組み込まれていると思いますが、これら2つについては入っているかどうかを念のために確認しましょう。「データベース関連モジュール」は、使用するデータベースに依存しますが、MySQLを使うには、PDO、mysql、mysqli、pdo_mysqlが必要になります。XML関連のモジュールは、FileMaker Serverとのやりとりで必要になります。「オプションのモジュール」は、機能を使用する場合に必要です。IM Ver.5.4以降、OPcacheをファイルのアップロードのプログレス表示に利用しています。「あった方がいいモジュール」は、一般には最初から組み込まれていると思われますが、gdを使うライブラリなどもあるため、これらは最初からあった方がいいでしょう。なお、macOSやFileMaker Serverに付属のPHPにはgdは入っていません。INTER-Mediatorの利用に支障はありませんが、PHPのライブラリを利用するときにはその有無に気をつけておきましょう。

種類モジュール名
必須のモジュールcurl、date、dom、ereg、hash、iconv、intl、json、mbstring、openssl、pcre
データベース関連モジュールmysql、mysqli、PDO、pdo_mysql、pdo_pgsql、pdo_sqlite、pgsql、sqlite3、libxml、xml、sqlsrv、pdo_sqlsrv
オプションのモジュールexif、ldap、Zend OPcache
あった方がいいモジュールfileinfo、ftp、gd、session、xmlrpc、xmlreader、xmlwriter
表9-2-1 INTER-Mediatorの稼働に必要なモジュール

 SQL Serverについては、やはりPDOのドライバーをインストールしなければなりません。PHP 7以降で利用できるドライバーが「Microsoft Drivers for PHP for SQL Server」として公開されており、Windows版 UNIX OS版のそれぞれのページに、インストール方法が掲載されています。例えば、リスト9-2-4はUbuntu 16へのインストール時のコマンド例です。

リスト9-2-4 UbuntuでSQL ServerのPDOドライバーをインストールする
sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv
sudo a2dismod mpm_event
sudo a2enmod mpm_prefork
sudo echo "extension=pdo_sqlsrv.so" >> /etc/php/7.0/apache2/php.ini
sudo echo "extension=sqlsrv.so" >> /etc/php/7.0/apache2/php.ini

 ファイルのアップロードを行う場合、php.iniは必ず修正をしてください。初期値では、数メガバイト程度のファイルのアップロードしかできません。表9-2-2のディレクトティブに対する設定を指定します。時間は整数のみで秒単位で指定します。サイズは、「100M」や「1G」などの補助単位も指定できます。例えば、php.iniファイルの中に「post_max_size = 500M」といった行を追加します。この時、ファイル内にすでに同一のディレクティブの設定がないかを検索してから記述しましょう。コメントも含めて、すでに「post_max_size」という単語が見つかれば、その値を修正するか、あるいはコメントの行の頭のセミコロンを削除して有効にして、右辺の値を記述します。

ディレクティブ定義される内容
memory_limitメモリー利用量の上限
post_max_sizePOSTデータの最大サイズ
upload_max_filesize1ファイルあたりの最大ファイルサイズ
max_input_time入力にかける時間の上限値
max_execution_time処理時間の上限値
表9-2-2 ファイルのアップロードに関わるphp.iniの設定

 ファイルのアップロードでは、ファイルのデータをそのままPOSTリクエストに載せます。同時に送られる情報は他にもありますがごく一部ですので、post_max_sizeギリギリまでのサイズのファイルはアップロード可能です。upload_max_filesizeはファイルのアップロード処理側で判定される値です。データは一度メモリーにロードされるので、memory_limitのサイズはファイルのサイズよりも大きくなければなりません。この3つの設定が、ファイルのアップロード処理に影響します。例えば、全部100Mに指定すれば、100M弱程度のファイルまではアップロードが可能になります。max_input_timeは、アップロードにかかる時間の上限値を指定します。これ以上時間がかかるとタイムアウトします。高速インターネットが当たり前な一方、モバイルでは極めて低速の通信しかできない場合もありますので、大きなファイルをアップロードさせたい場合には、この値を300など(つまり5分程度)大き目の値にしておきます。max_execution_timeはファイルのアップロードの時間には関係ありませんが、PHPのスクリプト処理のタイムアウト値を指定します。場合によっては、大量のデータを集計するなど、PHPの処理に時間がかかる場合もあります。その時には、この値を例えば300など(つまり5分程度)大き目の値にしておきます。

FileMaker ServerでのWebサーバーとPHP

 FileMaker Serverをインストールするとき、PHPを使用する上で、WebサーバーやPHPをどのようにすればよいかという問合せが多くあります。 FileMaker Serverインストーラーのセットアップアシスタントには、あらかじめ2つの選択肢が用意されています。選択肢は「はい、FileMaker Server がサポートするバージョンの PHP をインストールします」「いいえ、すでにインストール済みの PHP エンジンを使用します」の2つです。すでにセットアップが正しく行われている前提で「いいえ」を選ぶこともありますが、「はい」を選択してFileMaker Serverが用意したWebサーバーやPHPを使うのが一般的でしょう。後者の方が当然ながら、トラブルの元になる要素は少なく確実な方法であると言えます。WebサーバーとPHPの連動はそれぞれの環境で色々な条件が絡みますが、その上でさらにFileMaker Serverを稼働させるのは、WebとPHPに対するしっかりとした知識は必要です。あまりよく理解していないのにもかかわらず、寄せ集めの手順でFileMaker Serverを構築するのは、結局動かないサーバーを作ることにもつながります。FileMaker Serverを利用する場合は、可能な限り、FileMaker Serverが用意したWebサーバーとPHPを使用するのが安全かつ確実な方法です。

 「はい、FileMaker Server がサポートするバージョンの PHP をインストールします」を選択した場合には、前のセクションの『FileMaker Serverのインストールと設定』で説明した通り、OSに標準添付されているWebサーバーやXAMPPのApacheサーバーなど、あらゆるWebサーバーを事前にオフにしたうえで、インストール作業を始めなければなりません。セットアップを最後まで進めると、Webサーバーのドキュメントルートは、Windowsの場合「C:¥Program Files¥FileMaker¥FileMaker Server¥HTTPServer¥Conf」、macOSの場合「/Library/FileMaker Server/HTTPServer/htdocs」になります。macOSの標準設定のドキュメントルートである「/Library/WebServer/Documents/」から変わりますので、注意が必要です。また、Apacheを使用するmacOSの場合、最初に読み込まれる設定ファイルは「/Library/FileMaker Server/HTTPServer/conf/httpd.conf」であり、ログファイルは「/Library/FileMaker Server/HTTPServer/logs」に保存されるように変化しますので、注意しましょう。

 FileMaker ServerをWindows Serverにインストールすると、IISが自動的に設定されます。ただし、アクセスログの作成や、規定のドキュメントファイルとしてindex.htmlを使用するような設定は省かれています。これらを有効にするには、サーバーマネージャーの「管理」より、「役割と機能の追加」を選択し、ウィザードで、サーバーの役割に関して、「Webサーバー(IIS)の項目内にある「Webサーバー」「HTTP共通機能」の「ディレクトリの参照」や、「状態と診断」の中にあるログ関連の項目にチェックを入れて進めます。もちろん、必要に応じて他の機能も追加します。IISの設定を行いたい時には、サーバーマネージャーの「ツール」より「インターネットインフォメーションサービス(IIS)マネージャー」を呼び出します。PHPが呼び出される設定については、FileMaker Serverのインストーラーが自動的に行なっていますので、IISマネージャーで設定変更をする必要は通常はありません。

 FileMaker ServerのPHPを使用すると、使用されるphp.iniファイルは、macOSでは「/Library/FileMaker Server/Web Publishing/publishing-engine/php/yosemite/lib/php.ini」(OSのバージョンによって「yosemite」の箇所が変わる)、Windowsでは「C:\Program Files\FileMaker\FileMaker Server\Web Publishing\publishing-engine\php\php.ini」となります。macOSではそのままでも利用できますが、Windowsの場合は、php.iniファイルを開いて以下の部分を探し、行頭の ; を削除して、この設定が有効になるようにします。つまり、初期状態ではmbstringは使用していない状態ですので、利用可能にします。

リスト9-2-5 php.iniでmbstringを読み込むようにする
;extension=php_mbstring.dll

 PHPのエラーログを残すために、以下の定義のどちらかを有効にしておきます。syslogを選択していると、イベントビューアーのWindowsログの分類にある「Application」の項目にログが追加されます。もし、error_logの項目に対してパスを指定すると、テキストファイルにPHPのエラーが記録されます。error_logはファイル内で後に設定した項目だけが有効になります。

リスト9-2-6 php.iniでログの出力先を指定する
error_log = syslog
error_log = "C:\inetpub\logs\LogFiles\php_log.txt"

 php.iniを修正した後は、IISを再起動します。IISマネージャーで、サーバー名の項目を選択して、右側に出てくる「再起動」をクリックすることで、すぐに再起動ができます。

プロバイダを利用した場合のデータベースとWebサーバー

 サーバーを1台分自由に使えるサービスの場合、通常のサーバーと管理は特には変わりません。一方、共用サーバー(レンタルサーバー)の場合には、Webサーバーやデータベースがすでにセットアップされた状態で利用するのが一般的です。Webサーバーにモジュール等は追加できないことが一般的ですが、例えばMySQLやPostgreSQLと一緒に使えるサービスであれば、PHP側での必要なモジュールはインストールされているのが一般的です。しかしながら、どうしても必要なモジュールが使えない場合には、プロバイダー側に要望を出して、対処してもらうしかないでしょう。

 なお、レンタルサーバーの場合、Webサーバーとデータベースサーバーが異なるホスト、あるいは異なるIPアドレスである場合があります。その場合、dsnキーでは、「mysql:host=ホスト名:ポート番号;dbname=データベース名」の形式で指定します。ホスト名やポート番号は必ずサイト等に記載があります。データベースをSQLコマンドを記述したファイルから作成できる場合にはそれを使うのがひとつの方法ですが、myPhpAdminなどの管理ツールを使ってデータベースを定義する必要がある場合もあります。

 安価ながら非常に古い時代に構築したままのプロバイダーだと、データベース側の文字コードをUTF-8でうまく扱えない場合もあるかもしれません。INTER-Mediatorではデータベース処理の前後に、SQLコマンドを実行できる機能があり、そのコマンドを実行させることで、正しく文字コードを処理できるような場合もありました。具体的には、MySQLでは以前のバージョンでは「SET NAMES utf8」というコマンドを実行すれば、UTF-8で処理が行われるといった対処をした時期もあったのですが、あるプロバイダではたまたまMySQLのバージョンが低く、一方でmy.cnfファイルの設定は変更できない事情があってエンコードの指定ができなかったのですが、この方法が使えました。リスト9-2-7は定義ファイルの一部です。コンテキスト定義のscriptキーは連想配列の配列で指定可能ですが、この設定だと、readつまりデータベースのクエリーにおいて、preつまりはSELECTコマンドを送る前に、definitionで定義したコマンドをMySQLに送ってエンコードの指定をしています。最近はほとんどのプロバイダでこうしたことは不要かもしれませんが、プロバイダあるいはたまたまインストールするサーバーが古いものだったりしたときにはこのような手法も考慮しなければならないでしょう。

リスト9-2-7 scriptキーを指定したコンテキスト定義
IM_Entry(
    array(
        array(
            'name' => 'postalcode',
            'view' => 'pcode',
            'script' => array(
                array(
                    "db-operation"=>"read",
                    "situation"=>"pre",
                    "definition"=>"SET NAMES utf8"
                ),
            ),
        ),
    ),
    null,
    array('db-class' => 'PDO'),
    false
);

対応するPHPのバージョン

 INTER-Mediator Ver.5.4がサポートするPHPのバージョンはVer.5.2〜Ver.5.6となっています。この項目を執筆している2016年9月ごろの状況では、Ver.5.2についてはほぼ使わなくなくなりつつありますが、FileMaker Server 10で付属するのがPHP Ver.5.2.5です。また、FileMaker Server 11はWindowsではPHP Ver.5.2.11が必要であり、データベースフォーマットが変更されるFileMaker Server 12以前の最後のバージョンを使い続けているユーザーの存在を意識したものです。また、プロバイダーによっては古いPHPがインストールされている状態のままだったりすることもあります。ただし、Ver.5.2をサポートすることによるプログラミング上の制限があることから、遠くない将来にはVer.5.2のサポートは止めて、Ver.5.3以降にする予定です。

 INTER-Mediator Ver.5.5は、PHP Ver.7.0をサポートしました。リリース時点ではVer.7.1についてはベータ版やRC版が出ているところではありますが、小規模な変更なので、Ver.7.1にも対応できているかについてはおそらく問題はないでしょう。サーバーOSのディストリビューション等ではPHP 7の利用はこれからというところかもしれませんが、スピードが速くなっている点がメリットして言われており、アップデートする価値はあると思われます。

PHPのサーバーモード

 開発しているPC/Macで手軽にINTER-Mediatorを動作させたい場合の選択肢として、PHPのサーバーモードがあります。ディレクトリにサイトに必要なファイルを作成し、加えて別途データベースサーバーの稼働が必要です。しかしながら、そこまでできていれば、Webサーバーのルートになるディレクトリをカレントディレクトリにして、「php -S localhost:8000」といったコマンドを入力します。そして、Webブラウザーからは「http://localhost:8000」とアドレス欄に入力します。すると、カレントディレクトリをWebドキュメントのルートとしてWebサーバーが稼働するような動作が行われます。引数のlocalhost:8000は、ループバックのIPアドレスでサーバー動作させて、そのポート番号が8000ということです。8000ではなくても、自由に利用できる適当な番号(9000や18000など)でも構いません。localhostで運用すれば、別のコンピューターから接続されて見えることもありません。

 phpコマンドは、通常はPHPのインストール時に一緒に組み込まれます。コマンドがないと言われたら、インストール等で何か足りないのかもしれません。コマンドを起動したら、ターミナルのウインドウにはアクセスログおよびエラーログに相当する表示が行われます。何かエラーがないかを調べたい場合は、ターミナルのウインドウを眺めるなどの作業も行います。サーバー動作を止めるには、ターミナルのウインドウでcontrol+Cのキー操作を行います。なお、何もかもがApacheやIISと同じではありませんので、それぞれの利用環境に応じて読み替えるなどしてください。しかしながら、ブラウザーからページファイルを正しいパスで指定してひらけば、INTER-Mediatorの動作は確認できるはずです。

システムロケールについて

 Ver.5.7-devより、システムのロケールを利用して、小数点などを取得しています。macOSのようなデスクトップ利用が主体のOSの場合は、当然ながらロケールの設定は各国に対して行われていて、日本語で利用している場合には現在のロケールとして日本語が設定されています。コマンドの「locale」が現在の設定を表示し、「locale -a」でシステムに登録されているロケールが表示されます。

リスト9-2-8 macOSについてのシステムロケールの確認
$ locale
LANG="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_CTYPE="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_ALL=
$ locale -a
en_NZ
nl_NL.UTF-8
pt_BR.UTF-8
fr_CH.ISO8859-15
eu_ES.ISO8859-15
en_US.US-ASCII
af_ZA
:

 ところが、Linuxの場合だと、ロケールが存在しない場合があります。リスト9-2-9は、Ubuntu 14 Serverの一例ですが、インストール時に英語を指定したので、英語であるen_US.utf8が設定されています。全部のロケールを見ても、他にCやPOSIX等の最低限のものがあるだけです。

リスト9-2-9  Ubuntu 14 Serverでのロケール設定
$ locale -a
C
C.UTF-8
en_US.utf8
POSIX
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US:
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

 システムがこのような状態であれば、日本語のロケールを追加しましょう。Ubuntuでは、ロケールは存在しないものの、ロケールの元データがあるはずなので、まずは、/usr/share/i18n/SUPPORTEDディレクトリに対して、jaというキーワードが含むファイルがあるかを調べます。すると2つ存在することが分かります。そこで、locale-genコマンドを実行して、日本語のロケール「ja_JP.UTF-8」を生成します。再度「locale -a」でロケールの登録状況を確認すると、確かに増えています。

リスト9-2-10 
$ grep ja /usr/share/i18n/SUPPORTED
ja_JP.EUC-JP EUC-JP
ja_JP.UTF-8 UTF-8
$ sudo locale-gen ja_JP.UTF-8
[sudo] password for msyk: 
Generating locales...
  ja_JP.UTF-8... done
Generation complete.
$ locale -a
C
C.UTF-8
en_US.utf8
ja_JP.utf8
POSIX

このセクションのまとめ

 WebサーバーとPHPが稼働する状況が、INTER-Mediatorには必要です。OSや稼働環境で色々な状況がありますが、きちんと動作して、かつ、PHPでは必要なモジュールが組み込まれていれば、問題なく利用できるはずです。

9-3INTER-Mediatorを利用する開発プロセス

データベースとWeb/PHPをセットアップした状態で、INTER-Mediatorを利用したソリューションを構築することができるようになります。ページファイルや定義ファイルの作成方法は、本書で説明してきた通りですが、ここでは実際の開発作業に入るまでの設計に関することをまとめておきましょう。

開発プロセスについて

 システム開発のプロセスは、各社あるいは各自でさまざまな手法が採られていることもあり、一般的には特定のプロセスに依存した仕組みをフレームワークに取り込むということは行わないと思われます。しかしながら、業務分析を行い、システム化する範囲と内容を定め、それを実装できる形式で記述し、実際に実装してテストするという、抽象度の高い世界から実際の開発タスクにまで徐々に抽象度を下げていく手法は、ほとんどの場合踏襲するルールと考えます。その意味で、INTER-Mediatorを使った開発では、どのような流れで進めることができるのかを紹介しましょう。ここで紹介する方法は、エンジニアでないような方が、何かの業務でWebシステムを作りたいと考えたとき、INTER-Mediatorを使えばどのように進めることができるのかを紹介します。想定する開発者は、HTMLでページを作成できるものの、プログラミングについてはちょっとかじった程度とします。つまり、システム設計のプロが行うような本格的・包括的な手法ではなく、普段は会社の業務を行っているような方でも行えるような手法を紹介します。

システムへの要求をまとめる

 本来はまず業務分析から入ります。業務分析は現実にはかなり困難な作業であり、専門家でなければ十分にこなすことはできません。現場の皆さんの場合は、シンプルに、「誰が」「何をする」ということを、言葉で記述して、明確化することで、システムの要求を記述することから始めましょう。「誰が」「何をする」という考え方と、「誰にとって」「何ができる」という考え方もあります。まずは、やりたいことをリストアップします。ここで重要なことは、「文字として書く」ことです。頭の中で考えたり、話し合ったりするだけではなく、記述をしましょう。そうしないと重要な項目を後から忘れてしまうなど、欠落の多い要求定義しか残りません。

 一方で、システム化したい作業があるからシステムを作るということもあります。例えば、部署内で共有化したい情報をExcelのワークシートにしてサーバーに入れて使っているけれども、2人同時に更新したり、手元にコピーを作って作業した場合には古い情報を見て作業することになり、2人の間で情報の不一致が生じてしまう問題などが起こりえます。これをシステム化して問題解決したいということがあるでしょう。その場合、ワークシートが作られているので、業務の分析がすでに行われていて、一定の範囲で電子化されていると言えます。その場合は、「現在、このようなワークシートで作業している」という結果からスタートすることができます。

 まずは頑張って思いつく情報を、例えば次のように、「記述」をします。もちろん、必要なら作図をしてもいいでしょう。すでにワークシートができている場合でも、そこで展開されている作業をひとつひとつ洗い出すことで、要求の記述を進めます。

 しかし「誰が」と言われても結構迷います。もちろん、「事務担当の山田さん」「事務担当の田中さん」がいずれも、「入金を受け付けて記録する」という作業をして、この2人が同一の作業を行うような状況では「事務担当者が」「入金を受け付けて記録する」ということを記述するだけで十分かもしれません。つまり、事務の担当者の数だけ要求の項目を書いても無駄なだけです。一方、それだったら、「誰が」というのは、「全部、『従業員が』になる」というは逆に広すぎないかをよく考えましょう。社長から末端の社員まで、皆が同じ作業をしていますか? していない人、役割が違う人がいるかもしれません。そこに注目して「誰が」をうまくまとめて「何をしている」のかを考えます。

 「何をするか」は要求の記述ではさらに難しいものです。しかし、ここは考えすぎず、「なるべくひとつのこと」を「数多くピックアップ」しましょう。「何をする」かについて記述したことは、おそらく分類できるかと思います。つまり、小さな作業に分割されていれば、それをまとめて大きなひとつの作業を定義できるでしょうし、逆に大きさな作業を小さな作業に分割するという流れもあります。これらは、思いついた「何をする」をともかく記述して、分類していく作業を行いましょう。「入金を受け付けて記録する」というのは、もしかして「入金の受付」と「入金の記録」に分離できるかもしれません。入金は、銀行振り込みなら、受付処理は、「通帳記入(オンライン確認)」「前回確認日時以降の入金を調べる」「記録すべき入金かどうかを判断する(判断基準を明示)」などの作業に分解されているでしょう。また、クレジットカードであれば処理が違っているかもしれません。「入金の受付」は、もしかするとシステムを作ってやらないといけないようなものではなく、通帳やオンラインバンキングのアカウントがあればできてしまうかもしれません。しかしながら、その後の「入金の記録」は自社のシステムに記録したいとします。このようなシステム化する業務としない業務を細部で検討が必要になります。ここで、システム化する部分を細かく検討するのは当然ですが、しない部分も検討しつつ、どこかで線をきちんと引かなければなりません。これを大まかに考えるのは間違いの元で、ある箇所をシステム化対象を外してしまったために、別の作業がより大変になってしまうかもしれません。線引きはざっくり考えがちですが、比較的小さな単位に分割して検討をした上で、対象外と決定し、設計期間中は可能な限りその決定が間違っていないのかを検証しながら進めるべきです。

 こうした業務の詳細化を進めるとき、「どのような」ということもやはり思いつくでしょう。それも記述しましょう。「どのような」には、「一覧から選択する」といったシステム化に直結するようなものや、「直近の10件の内容を一覧表示する」といった付帯的な表示物を指定するものなどさまざまなものがあります。また、「素早く処理を終える」といったいわゆる非機能要求もあるでしょう。こうした思いを全て記述します。

 一般的なモデリングでは「なぜ」を重視します。特に要求を記述するときには、なぜを明確にします。しかしながら、そのレベルでのモデリングは専門家でもなかなか難しいものです。ここでは、要求をまとめる作業をともかく進めていただきたいので、専門家ではない方やモデリングに慣れていない方は、「なぜ」の答えとなる記述を深追いせずに、後回しにしましょう。業務内容を検討する中で、要件がスムーズに列挙でき、記述できる範囲内で、ともかくそれを書き下していくことをお勧めします。

 本来、こうして考えた結果は、UMLのユースケース図で記述するのが、業界標準的な手法ではあります。しかしながら、ルールに従ったダイアグラム作成は、やはり専門的な知識とトレーニングが必要です。また、システムに対してさせたいことを記述する「要求」を基にして、システムが何を達成しなければならないのかといった「要件」の記述に進むのが、システム開発の一般的なプロセスでは提唱されています。しかしながら、要件が重要になるのは比較的大きなシステムであり、要件の記述には技術的な知識が必要です。状態遷移を伴うプロセスの場合は、一足飛びに「要求を満たすユーザーインターフェースを作る」ステップに進んだほうが効果的な場合もあります。イメージがつかみやすくなりますし、そのプロセスで必要な要求が明確に見えてくる、といったメリットもあります。例えば、電話番号はハイフンを入れた状態で入力してもらうのか、そうではないのか。もし、ハイフンなしで入れさせるのなら、そのやり方が自明となる入力フィールドの配置はどうすればいいのか、が見えてきます。全ての開発がこうした流れでできるわけではありませんが、それほどの複雑な仕組みは要求されないことも比較的多いので、まずはシンプルな手法を理解するようにしましょう。現場レベルで要求定義の作業においては、やはりExcelのワークシートに、思いついたことをともかく記述する方法が手軽です。ワークシートだと、分類や階層化などのアレンジもしやすいでしょう。また、ともかくキータイプすればいいので、記録もされやすいです。

ページ単位の設計

 Webサイトは、「ページ」あるいはひとつのHTMLファイルで表現される範囲が、設計上、ひとつの重要な塊になります。前述のシステム要求をまとめるうちに、ある一定の範囲の作業をまとめたひとつのページが見えてくるのが一般的です。ひとつのページには、同時あるいは連続して行う作業を実現するためのテキストフィールドやボタンなどが含まれているというのが一般的な形態でしょう。ただし、1ページ範囲があまりに多い場合には、処理のレベルごとに要求をまとめ、複数のページに展開して実現することになるかもしれません。一方、同一の前提条件で行われる作業は、複数の作業をひとつのページにまとめたほうが分かりやすく、かつ操作しやすくなります。例えば、会員登録ページで住所、氏名、生年月日、電話番号を入れるとともに、本人確認書類をアップロードしてもらいたい場合などが良い例でしょう。住所氏名を入れるページと、本人確認書類のアップロードのページを別々に作ると、入力時の作業も煩雑で分かりにくいものになる上に、それを確認する担当者の作業も煩雑になります。したがって、これら一連の作業をひとつのページにまとめます。つまり、前提条件を揃える仕組みを共通化することで、開発効率を高めたり、ユーザーインターフェースを分かりやすく、かつ使いやすくすることができます。

 ページへの分割、あるいは1ページの識別は、画一的に考えないで、柔軟に考える方がいいのですが、こちらは「デザイン」的な意味での慣れは必要です。そして、ペーパープロトタイピングと呼ばれる紙にページのデザインを描いて、実際に指で触れるなどして実感を見ながらページレイアウトを考える方法や、ワイアフレームグラフィックスのツールを使ってページを設計する方法などがあります。さて、INTER-Mediatorでの開発の場合はどうでしょう。この場合はここでページファイルの作成を始めるのが得策です。ただし、最初はデータベースの連動を考える必要はなく、ページにどんな種類の情報が、どんな風に見えてほしいのかということを、形に表すという意味で、ページファイルというよりも実際に画面表示できるHTMLファイルを作り、それを利用者がブラウザーで表示してみて業務の流れを実体験できるようにしてあげましょう。こうすることで、具体的な問題点や、注意すべき点を露わにします。「セミナーの出席者リストを作る」という作例では、例えば、次のようなページをプランすることになるでしょう。ページのデザインを考えながら、ページのデザインに直接出てこない注意点(図中の「郵便番号から自動的にある程度の住所入力を行う」など)は、要件定義と同様にどこかに記述することを心がけましょう。

図9-3-1 ページとその要素をページないしはワイアフレームで記述

 最近は、シングルページアプリケーション(SPA)として、見かけ上複数のページに見えるものの、実はひとつのHTMLファイルで実現するような仕組みのアプリケーションがあります。もちろん、INTER-MediatorはSPAの作成に対応しています。SAPは実装の手法のひとつであり、このセクションで説明しているページは、SAPにおける1ファイルの意味ではなく、利用者が見えるページのことです。

 ここで、ページ内に配置するそれぞれの要素は、要求定義で抽出した各項目を配置していきます。よく使われる手法のひとつを紹介すると、要求の定義項目が確実に実現されているかをチェックするために、要求の項目に番号をつけて管理する方法があります。ともかく、業務洗い出しで出てきた必要な要素はもれなく配置していきましょう。もし、要求定義にないものがページ上にあった場合は、要求として漏れていたということになります。要求の記述そのものが曖昧なために、ページにできなかったということもあります。可能であれば、要求に戻って気づかなかった要素を追加して改めて検討します。

 一方、要求の定義にあるものがページ上で登場しない場合はどうすべきでしょうか? もちろん、それは何か問題があります。例えば、テキストフィールドを忘れていては、そのデータは変更できません。しかしながら、本質的に実現できない要求を記述している場合もあります。例えば、「荷物が到着したときに日付が自動的に入力される」という要求があったとします。そのためには、例えば宅急便のサイトの情報と連動したり、あるいはサイトから荷物の状況が得られるようにあらかじめ準備すればできると思いがちですが、他のシステムとのやりとりは難易度が高いですし、仮に機能上できるとしても、自分のシステムのデータベース内で整合がとれた状態でデータのやり取りを実現するのはかなり大変です。場合によっては、システム稼働開始前と稼働後ではデータの形式が異なってしまっており、うまく統合できないかもしれません。場合によっては既に大量のデータが蓄積されているかもしれません。そのような場合は無理に自動化、統合化を図ろうとせず、単にテキストフィールドを用意しておいて、手作業で入力していくのが最も確実で早いという結論になるかもしれません。

 ページを検討している時には「こういうことをやりたいけれども、ページとしてどうなるのかさっぱり分からない」ということもあるでしょう。この場合は、やはり専門家にまずはヘルプをお願いし、要求の上での過不足を見極めた上で実現可能な手法を考えてもらうのがいいと思われます。業務の流れを変えないと、システムとして実現しづらいということもあるかもしれません。

コンテキストの抽出とスキーマ定義

 ページファイルを作ると、結果的に、必要なコンテキストは抽出されていると言えます。ユーザーインターフェース上でのデータの塊は、コンテキストに含まれるレコードの現れであると考えることができます。そして、レコードの「繰り返し」になる場所と、レコードと別のコンテキストのレコードが「1対多」になる場所を特定して、ページ内のひとつのコンテキストを展開する場所の割り出しを行います。そして、それに対応するコンテキストを定義しつつ、データベースに必要なテーブルを割り出してスキーマを定義します。

 例示している「セミナーの出席者リストを作る」という作例に戻って考えてみましょう。スタッフが参照するページの様子を見ると、「参加者」というテーブルからの複数レコードのコンテキストが表示されているということになります。同様の情報が参加者のページにもあるので、参加者のページも同じテーブルを基にしたコンテキストであれば良いと考えます。そして必要なフィールドは、名前、メールアドレス、会社名など、参加希望の登録フォームのページの項目があれば良さそうです。例えば、一般的なSQLであれば、次のようなCREATE文でテーブルを作れば良いでしょう。そして2つのページとも、このテーブルをコンテキストとして利用するコンテキスト定義を記述することになります。型は可変テキストかTEXT型が無難でしょう。最大桁数がどれくらい必要かは、過去のデータなどから検討します。キャンセルしたかどうかは数値で記録することにし、例えば「1」はチェックボックスがオンでキャンセルしたことにし、そうでないデータならチェックボックスはオフでキャセルしていないことにします。

リスト9-3-1 「参加者」を管理するテーブルの例
CREATE TABLE attendant (
	attendant_id	INT PRIMARY KEY,
	cacel	INT,
	name	VARCHAR(32),
	yomi	VARCHAR(32),
	mail		VARCHAR(64),
	company	VARCHAR(64),
	section		VARCHAR(64),
	title		VARCHAR(64),
	zipcode	VARCHAR(7),
	address	TEXT,
	tel		VARCHAR(20),
);

 このテーブル定義、そして想定しているユーザーインターフェースに限れば、コンテキスト定義として次のようなものを用意すれば目的のものが作成できるのではないかと思われます。参加申し込みのページも、参加者一覧のページも、どちらも同一のコンテキストで可能ではないかと考えられます。スタッフが見る参加者一覧のコンテキストとしては、attendantテーブルを表示しつつ、名前のフリガナでソートされており、さらにキャンセルした参加者が含まれていないようなものとなります。そのため、sortおよびqueryキーによる設定を追加しました。

リスト9-3-2 コンテキスト定義の例
name:	attendant
view:	attendant
table:	attendant
sort:	[field: yomi, direction: ASC]
query:	[field: cancel, operator: !=, value: 1]

 通常、専門家がこうした作業を行うときには、業務分析、そして要求に応じて、まずはスキーマを設計します。実はこうした作業はなかなか難しいのですが、専門家がこういったことができるのは、Webページやそこでのコンテキストについて、実物がなくてもおおむね正しい判断ができるスキルを積んでいるからであると考えられます。むしろ、業務と要求が実現できるようなデータ記録の仕組みを抽象的に考えることで、言い換えれば「どんな場面でもうまく動く」ことを目指します。そして、分析がしっかりなされたスキーマは、要求が後から追加されてもそのスキーマで運用できる例もたくさんあります。データベースを定義し、その上で動くプログラムを作るという専門家を投入するワークフローが展開でき、実際にうまく運用できれば効率良くシステム開発が可能です。

 しかしながら、専門家ではない方が、いきなりデータベースのスキーマを考えるのはかなり大変です。まずは、ページを考えて、その内容からコンテキストを抽出し、そのコンテキストに必要なテーブルを用意するという流れの方がうまくいくと思います。それでもテーブル設計では難しい問題が頻繁に発生します。専門家ではない方で、自信がない方は、要求定義、ページのモックアップを見せた上で、スキーマとして正しいのかどうかを判定してもらうということも必要かもしれません。

設計内容のレビューとイテレーション

 ここまでは、「思いついたことを要求定義として記述」して、それを基に「必要な画面設計」を行い、その結果から「コンテキストとその基となるテーブルの抽出」を行いました。細かなルールは特に定めないで、直感的に作って行った流れかもしれません。しかし、ここで一度、じっくり観察をします。「セミナーの出席者リストを作る」という点ではこれだけでなんとかなりますが、セミナーが終わってしばらくして次のセミナーが開催されたらどうなるでしょうか? 参加者の項目を全部キャンセルして、再度同じことを最初からやり直す、という単純な方法もありますが、これはとても無駄の多いシステムになってしまいます。また、セミナーがたまたま2日連続で発生するようなとき、このシステムはうまく働くでしょうか? 参加者も、スタッフも「どちらのセミナーか」ということをどこでどう区別させるのでしょうか? ではどうするかというと、結論としては、セミナーの実施日をフィールドとして持つ「セミナー」テーブルを作ることが最良の対策と考えられます。

 最初の要件には「セミナーの日程」ということに明確な記述がありません。強いて言えば「当日」などと記述されているあたりが落とし穴だったと思われます。実際こうした要求はシステム化する場合の最もあいまいな「抜け」となってしまいます。このままではデータベースのどこにも日付の情報がありません。つまり、attendantテーブルを探っているとき、ある参加者がいつのセミナーに参加したのが分からないのです。では、attendantテーブルに「セミナー日」のフィールドを追加するだけで問題は解決するでしょうか? また、シンプルに出席者を集約したいだけであれば、それでも機能しないわけではありませんが、例えば特定の日に実施されたセミナーの参加者をリストアップするのに、検索条件として日付を正確に入力しないといけないなど、使い勝手が悪くなりそうです。そこで、セミナー日や実施時間、あるいは場所なども含めた、「セミナー」という存在を意識します。そうすると、1回のセミナーに複数の参加者が存在することになり、ここでテーブル間の1対多の関係が見えてきます。例えば、テーブルとしては次のようになるでしょう。

リスト9-3-3 「セミナー」と「参加者」を管理するテーブルの例
CREATE TABLE seminar (
	seminar_id	INT PRIMARY KEY,
	thedate	DATE,
	starttime	TIME,
	title		TEXT,
	place	TEXT,
	memo	TEXT
);
CREATE TABLE attendant (
	attendant_id	INT PRIMARY KEY,
	seminar_id	INT,
	cacel	INT,
	name	VARCHAR(32),
	mail		VARCHAR(64),
	company	VARCHAR(64),
	section		VARCHAR(64),
	title		VARCHAR(64),
	zipcode	VARCHAR(7),
	address	TEXT,
	tel		VARCHAR(20)
);

 しかしこうなると、複数のセミナーが存在するということを基にしたページ設計が必要です。スタッフが参照するページは、セミナー自体の選択をして、その参加者一覧が表示されるような、マスター/ディテール形式のユーザーインターフェースが一般的でしょう。そして、参加申し込みで日付が入力される方法を考えなければなりませんが、これは実はビジネスモデルによって大きく変わると思われます。いずれにしても、「セミナーそのものを管理しなければならない」ということを考えれば、ユーザーインターフェースの設計は図9-3-2のようになります。スタッフが見るページがひとつ増えていて、そのセミナーの一覧はseminarテーブルを基にしたコンテキスト定義より作成が可能です。

図9-3-2 ページとその要素をページないしはワイアフレームで記述

 これでいいでしょうか? こうして実際に動きそうな画面を見ると、いろいろな要求が欠けていたことが分かります。それらを列挙すると次の通りですが、これらで全てであるかどうかは分かりません。さらに要求が出てくるかもしれません。いずれにしても、これらの要求のひとつひとつについて、要求として記述し、それを元に開発プロセスを回します。ユーザーインターフェースの変更だけで終わるものもありますし、ユーザーインターフェースの追加や新たなコンテキストの識別が発生するでしょう。

 開発作業のプロセスとしては、要求定義、ユーザーインターフェースとページファイル、コンテキストの識別、定義ファイルでのコンテキスト定義、スキーマ定義といった流れになりますが、立て板に水を流すかのような一方向の流れで終わるということはありません。ある要件を実現するうちに気付かなかった、つまり明言できなかった要求がどこかの段階で増加し、その結果ユーザーインターフェースを追加したり変更したりすることが必要で、結果的にコンテキストやスキーマ定義への変更も必要です。このように、いくつかの作業をぐるぐると繰り返しながらなるべく完成に近づける作業を「イテレーション」と呼びます。

図9-3-3 イテレーションを含む開発プロセスの流れ

 いくつかのプロセスが一方向に進められるのは、一般にはひとつのプロセスでの作成結果を変更することに多大なコストがかかる場合に取られる方法です。そのため、時間やコストをかけて、ひとつのプロセスの成果物を出し、その完成度が高いものとして、次のプロセスに引き継がれてプロセスが進行するということになります。しかしながら、ここで紹介したようなイテレーションは、ひとつひとつのプロセスの作業はそれほど重くなく、修正も容易です。むしろひとつひとつのプロセスをじっくりやるよりも、手のつけられるところから進められるという意味ではより気軽な手法と言えるでしょう。また、結果的にINTER-Mediatorを使ったアプリケーションの骨格部分を構築している作業に一部は対応しており、上記の作業は設計でもありますが、構築でもあるのです。

 アジャイル開発の原則をシンプルな言葉でまとめた『アジャイルソフトウェア開発宣言』の記述(この段落では「」で記載)と、ここまでに紹介したプロセスの対比をしてみましょう。開発プロセスを一人で行う方もいらしゃるかもしれませんが、職場で作業をするとしたら何人かのスタッフ同士で検討をするでしょう。その結果「個人との対話」が発生します。そして、INTER-Mediatorで作成した場合は、データベース、定義ファイル、ページファイルが揃えば何かしら「動くソフトウェア」ができ上がります。そして、作り込む部分が少ないうちは「変化への対応」も容易です。他に「顧客との協調」という記述がありますが、ここで紹介する手法を顧客あるいは開発者と顧客が取り組むとしたら、まさにそれは協調以外の何物でもありません。このように、INTER-Mediatorを利用した開発プロセスは、アジャイル開発であると言えます。

 ちなみに、こうした「まずはHTMLファイルを作って考える」という手法は、アジャイル開発のひとつのプラクティスである「モックアップ駆動開発(mockup driven development)」として提唱されています(英語で検索するとさまざまな論文が出てきますが日本語だと何も出ません)。HTMLだけだと、手続き的なプログラミングを習得していないような非プログラマーの利用者も作成できますし、さまざまなツールがあってコードを書かないで作り込むこともできるというメリットが大きいでしょう。加えて作成にそれほどの時間がかからないことや修正が容易ということもあり、開発の早い段階で最終的なイメージを見せることができます。その後にデータがそのページに乗るような流れでスムーズに発展させられます。しかしながら、INTER-Mediatorは単なるモックアップ駆動開発ではなく、モックアップが「動作する」ところにひとつの進歩があります。

 一方で、「HTMLを作って開発するのは良くない方法である」という論調もあります。このような論調の根底にある原因は、「HTMLにはすべての情報が込められていない」ということに尽きると思います。確かに、単にHTMLをいきなり作るだけでは、実際の表示内容はどうなるのか、きちんと提示できないということもあります。しかしながら、このセクションで説明している方法は、最初に要求を記述して、要求を定義し、何をやりたいのかということが比較的細かなレベルまでも記述されているということがあります。もちろん、読みやすさや記述の的確さなどの要求定義のクオリティの問題もありますが、最初に何ができるようになっているのかという議論を経た上でHTMLでのページのモックアップ(システムの見本)を見ることは、それらの議論がより具体化された結果を見ていることであり、開発フェーズとしては無駄なものではなく、さらに進めた結果を見ていると言えるでしょう。

必要な実装を進める

 短期間で設計・テスト・検証・改善というイテレーション作業を繰り返すうちに、次第に定義ファイルやページファイルには詳細な記述が増えることになるでしょう。このとき、要求定義として記述したやりたいことを実際に開発結果に組み込むとき、その処理をINTER-Mediatorが用意しているかどうかで対処が変わります。例えば、記録しているデータを表示するだけならば、単にページファイルにdata-im属性を記述するだけです。データを表示するとき、ちょっと変更して表示したい場合、それが書式設定のような単一のフィールドに関連するものや、同一レコードから求められるものであれば、calculationキーをコンテキストに記述して計算プロパティを定義して、そのプロパティ名をdata-im属性に記述します。一方、ボタンを押したらフィールドの値が更新されるようにしたい場合は、INTER-Mediatorはそのような機能を持ちませんから、通常はJavaScriptでプログラムを書くことになるでしょう。

 ここまでで示している「セミナーの出席者リストを作る」という作例で考えていきましょう。まず、参加申し込みを行うページでは、単に申し込みの受付を行うので、これはポストオンリーモードでのページ作成で実現できそうです。ポスト時にバリデーションを行うため、コンテキスト定義にはvalidationの設定を行います。また、このままではデータを誰もが読めてしまいますので、データベース処理のうちレコード作成以外は存在しないグループdummyでしかできないように設定して、事実上誰もレコード作成以外のデータベース処理はできず、レコード作成のみ誰でもができるようにしておきます。また、「申し込む」ボタンをクリックしたあと、ボタンの位置に「お申し込み受付ました。確認のメールをごらんください。」と表示して、再度ボタンが押されないようにしつつ、受け付けられたことを利用者にフィードバックするとします。ページファイルの主要部分をリスト9-3-4、コンテキスト定義をリスト9-3-5に示します。ページファイルにあるseminar_idフィールド向けの隠しフィールドにある「20」という値は、何らかの方法で、参加受付しているセミナーのテーブルの主キー値を得て手作業で記述したものとします。

リスト9-3-4 参加申し込みページのページファイルの主要部分
<table>
	<tbody data-im-control="post">
	<tr><th>名前</th><td><input type="text" data-im="attendingpost@name"/></td>
	<tr><th>メールアドレス</th><td><input type="text" data-im="attendingpost@mail"/></td>
		:
	<tr><th></th><td>
		<input type="hidden" data-im="attendingpost@seminar_id" value="20"/>
		<button data-im-control="post">申し込む</button>
	</td>
</table>
リスト9-3-5 コンテキストattendingpostの定義
name: attendingpost
view: attendant
table: attendant
id: attendant_id
validation:
    [field: name, rule: length(value)>0, message: 入力必須です, notify: inline]
    [field: mail, rule: length(value)>0, message: 入力必須です, notify: inline]
authentication:
    [read: [group: [dummy]]],
    [update: [group: [dummy]]],
    [delete: [group: [dummy]]]
post-dismiss-message: お申し込み受付ました。確認のメールをごらんください。

 同様に、スタッフ側のページも設計を進めるとさまざまな要素が必要になります。ここでは数多くなるので、ポイントだけを示します。まず、セミナー一覧と出席者一覧については、マスターディテール形式の仕組みを利用することにします。ただし、ディテール側はいきなりattendantテーブルを表示するのではなく、seminarテーブルを1レコード配置し、その内部にattendantテーブルのコンテキストを一覧として展開します。これは、参加者リストにもセミナー日やタイトルなどのseminarテーブルの値を表示したいというところから来ています。seminarテーブルは一覧用のseminarlistとディテール領域用のseminardetailの2つのコンテキストとして実現します。セミナー一覧は日付の逆順とするので、sortキーの定義がコンテキスト定義には必要です。出席者一覧では、名前の読みの順でsortキーの定義を記述します。また、出席者一覧では、キャンセルしていない人の一覧を出すためのqueryキーの定義を行います。なお、セミナー一覧上でフィールドの値を変更できるようにINPUTタグにしているので、これで全てのフィールドではありませんが、主要なフィールドの入力はできます。attendantテーブルの方は、このページファイルでは修正はできないので、別途作成することになると思われます。ページファイルの主要部分をリスト9-3-6、コンテキスト定義をリスト9-3-7に示します。なお、定義ファイルの2つ目の引数(オプション指定)において、全てのデータベースアクセスを認証が必要であるように設定するようにします。

リスト9-3-6 スタッフ向けページのページファイルの主要部分
<table>
	<thead>....</thead>
	<tbody>
	<tr>
		<td></td>
		<td><input type="text" data-im="seminarlist@thedate"></td>
		<td><input type="text" data-im="seminarlist@title"></td>
	</tr>
</table>
<div data-im-control="enclosure">
<div data-im-control="repeater">
<p>ID:<span data-im="seminardetail@seminar_id"><span> 
セミナー実施日:<span data-im="seminardetail@thedate"><span></p>
<div id="IM_NAVIGATOR"></div>
<table>
	<thead>....</thead>
	<tbody>
	<tr>
		<td></td>
		<td data-im="attendantlist@name"></td>
		<td data-im="attendantlist@mail"></td>
				:
		<td><input type="checkbox" data-im="attendantlist@cancel" value="1"/></td>
	</tr>
</table>
</div>
</div>
リスト9-3-7 スタッフ向けページで利用する3つのコンテキスト定義
name: seminarlist
view: seminar
table: seminar
id: seminar_id
sort: [field: thedate, direction: DESC]
repeat-control: confirm-insert-top, confirm-delete
navi-control: master-hide

name: seminardetail
view: seminar
table: dummy
id: seminar_id
records: 1
navi-control: detail

name: seminarlist
view: attendant
table: attendant
id: attendant_id
paging: true
sort: [field: yomi, direction: ASC]
query: [field: cancel, operator: !=, value: 1]
relation: [foreign-key: seminar_id, join-field: seminar_id, operator: =]

 もちろん、これで完成ではありません。まだまだ、積み残した要求があります。実際に業務ができるところまで、要求を実現しなければならないのは言うまでもありませんが、ここでは作業の流れを示したいので、開発作業結果の紹介はここまでとします。

 要求を考えるときに「何をする」のかがしっかり抽出されていれば、あとはその機能があるかどうかの判断で、あるのならページファイルや定義ファイルに記述を加えます。ないのであればJavaScriptやPHPでの拡張ポイントを検討して組み込みを行います。しかしながら、実際に組み込みを行うと、要求で考えた以上のことをやらなければならないことが多々あります。それらは頑張って新しい視点で実装をするしかないでしょう。例えば、単にデータやページ上の表示を考えれば、一覧された結果の中のあるフィールド値の合計は簡単に求められそうに見えます。もちろん、単なる合計は、計算プロパティで求めることも可能です。しかしながら、条件付きの集計をしたい場合はどうでしょうか? 別のフィールドの値が一定以上であれば、合計対象に含めても、そうでないなら合計に入れないという仕組みの実装はどうすればいいでしょうか? これについては、いくつかの答えがあります。SQLデータベースなら、そうした計算処理を組み込んだビューを作っておくことで対処できます。また、エンクロージャーに全てのリピーターが合成された後に呼び出されるメソッドをコンテキスト定義で指定し、JavaScriptのプログラムにおいて、コンテキストの値を参照しながら、自分で繰り返し処理を記述して条件付きの合計計算をするという方法もあります。後者の手法は、ページ合成処理に割り込む処理の記述、コンテキストの取り出し、JavaScriptによる計算処理といった知識が必要になるでしょう。手続き的なプログラミングが必要な拡張点に限っては専門家に作ってもらうという手もあります。

 コンピューターでのシステム開発に限らないのかもしれませんが、中間に存在するさまざまな議論をすっ飛ばして最終結果に目が向きがちです。例えば、「○○というフレームワークを使うと良いらしい」という結論ありきで、なぜそのフレームワークが良いのかということを考えていない関係者が散見されます。問いただして出てくる答えも「ブログで偉い人が言っていた」くらいの理由しかありません。どんなフレームワークでも、適用範囲とその利用プロセスが妥当かどうかという判断が先にあるはずです。ここで紹介したプロセスは最初に説明した通り、エンジニアでない人でも頑張ればできる範囲を想定したものです。INTER-Mediatorは、エンジニアでもない人が全てできるとは主張しませんが、エンジニアでない人でも開発作業やメンテナンス作業の一定部分を賄えるというシナリオを描けるという点を理解していただきたいと考えます。

 フレームワークを使うとしたら、それをどのようにマスターすればいいのかということに注目が集まるのは世の常です。しかしながら、本当に重要なのは、INTER-Mediatorにタッチするまでの分析にあり、その分析を効率よく進める開発プロセスにあります。分析で俎上に上がったことはなんとかなるものです。しかし、分析で一切気付かないでいたことがシステムに組み込まれるのは奇跡に近い話です。そのため、初期の段階からきちんと記述を残すことを意図した要求のピックアップを重視すべきだと考えます。そして、INTER-Mediatorで利用できる機能で要求が実現できるかどうかを検討し、直接実現できるものはともかく組み込みましょう。場合によっては何段階かの作業が必要なものもあります。しかしながら、手続き的なプログラミングが必要な要求もあるということです。

 UMLによる設計記述は、批判も多々あるものの共通のルールでダイアグラムを作成できるメリットは大きいでしょう。一方、「クラス図」「オブジェクト図」とあるように、原則としてオブジェクト指向の考え方が根底にあります。もちろん、ユースケース図やシーケンス図のような、オブジェクト指向という視点ではないものもありますが、UMLの成立過程を見ても、オブジェクト指向開発のひとつの達成点であることは間違いないでしょう。そのため、UMLを使いこなすにはオブジェクト指向プログラミングを基礎として習得している必要があります。しかしながら、INTER-Mediatorのように最終的にクラスを作ることを意図しないようなフレームワークでは、オブジェクト指向的にまとめ上げる必要性はあまりありません。特に最近のWebクライアント系フレームワークは、オブジェクト指向色が少ないこともあり、開発プロセスとしてどのような手法を取り入れていくのかについてのアイデアはこれから出てくるといったところでしょうか。この書籍の最後のセクションを書きながら、筆者はブログ上に記事を書き溜める形式で、現在のクライアントとサーバーを巻き込んだWebシステムのモデリングをどのようにすればいいかを考え始めています。クラスやオブジェクトというより、「やりたいこと」「させたいこと」という要求レベルでの単位をベースに、フレームワークの機能で分解して記述したニーズをまとめ、フレームワーク外の機能を抽出してオブジェクト指向的に手続き的なプログラムを作成するといった流れを想定しています。こちらは時間がかかるかもしれませんが、まとまった結果が出れば、INTER-Mediatorコミュニティには必ず還元できるものが得られると信じています。

データベーススキーマを用意する

 データベースを利用したアプリケーションでは、データベース設計であるスキーマが肝であることは当然です。データベースの設計がすべての基礎になることはもちろんです。データベース上で想定していないことは、どんなに頑張っても実現できない可能性が高く、「想定されるあらゆる状態を記録できる」ようなスキーマを設計するのが基本であるとも言えます。そのため、SQLの定義言語は実にさまざまな機能があります。

 INTER-Mediatorでアプリケーションを作成する場合、どこまでを実際にデータベースのスキーマとして込めるのかということがあります。機能的には、テーブル定義、フィールド定義、フィールドの型くらいの定義で構いません。ただし、実用的には、主キー設定とユニークなインデックス、検索フィールドに対するインデックスは必要になります。その他の外部キー、初期値あたりは必須ではありませんが、設計時には意識はすることになると思われます。外部キー自体の設定は、relationキーでコンテキストに定義することになりますし、初期値はコンテキストやあるいはJavaScriptで指定するなどさまざまな方法があります。制約をどこで記述したいのかによって記述場所をよく検討しましょう。一般に外部キー制約は、リンクされていないレコードの作成を阻止するなどの目的を持って行われます。

 SQLデータベースを利用する場合は、ビューを積極的に活用しましょう。データを取り込んでから処理をプログラムで書くよりも、SQLの段階で集計をしてしまう方が、一般には処理時間が短くなります。また、リレーションシップを適用した後の結果をビューとして取り込む方が、コンテキストの階層化により複数回のサーバーアクセスを行うよりも明らかにスピードアップの効果が出ます。あまりに節操なくビューを作ると何が何だか分からなくなりますので、用途を整理しながらビューを作って、それを元にコンテキストを組み立てるように進めれば良いでしょう。

 データベースを作成してユーザーを作り、権限を与えてテーブルを作成するという一連のスキーマ定義コマンドは、INTER-Mediatorフォルダーのdist-docsにある各データベースごとのサンプルのスキーマファイルが参考になると思われます。SQLデータベースでの認証関連のテーブルについては、このファイルから必要な箇所をコピー&ペーストすればいいでしょう。また、Samples/templates/least_schema_mysql.sqlというファイルは認証関連のテーブル定義とひとつのサンプルのテーブル定義なので、このファイルを基にして作成してもいいでしょう。

 

このセクションのまとめ

 一般的なWebアプリケーションフレームワークでは、旧来からの手続き的プログラミングを主体とした開発プロセスを踏襲あるいは改良した手法で語られることが多いでしょう。一方、INTER-Mediatorは、利用開始初期段階では手続き的プログラミングのコードを「書かない」ことを主眼としており、その点では他のフレームワークと大きく異なります。書かないのは存在しないのではなく、フレームワークにいつも最初に書くようなプログラムが内包されていて、アプリケーションを作る人はそのフレームワークに込められた仕組みを再利用しているのです。Webシステムを一般化すれば、ページとデータベースの連携が根底にあり、その仕組みを基礎として自分が必要な仕組みをさまざまな手法で組み込むという考え方でINTER-Mediatorは利用できます。

9-4Webアプリケーションの構築作業

INTER-Mediatorを使ったWebアプリケーションを実際に作る時のディレクトリ構成や、あるいはフレームワーク自体のセットアップなどを説明します。

Webアプリケーションのディレクトリの用意

 実装作業は、ページファイルの作成、定義ファイルの作成、そして場合によってはプログラムを含めるjsファイルや、PHPの拡張のためのクラスを定義するということに尽きます。ファイルは、テキストエディターで作成してもいいですが、できれば開発用のツールを使うことをお勧めします。特に、基本的な文法チェックは重要です。この機能のないエディターで定義ファイル等を作成すると、カッコがひとつ足りないとか、カンマがないといった簡単なミスが多発します。こうした文法上の細かなミスは人間の目では分かりづらいものです。開発ツールでは、実際にサイトを稼働させずにソースコードの状態で問題点を指摘してくれます。もし、現在、その種のツールを何も使っていないなら、フリーのものとしてはVisual Studio CodeAtom、有償のものではPhpStorm IDEを検討しましょう。

 定義ファイルエディターを使いたい場合には、可能な限り、INTER-Mediator-Server VM上で開発して、完成後に実環境に移動することをお勧めます。もし、どこかのサーバーで定義ファイルエディターを使いたくなった場合には、定義ファイル自体あるいは定義ファイルを保存するディレクトに対して、Webサーバーを稼働しているユーザーにファイル読書きの権限を厳密に制限してセットしておく必要があります。また、INTER-Mediator-Supportフォルダーにある定義ファイルのdefedit.phpの末尾の行にあるコメントを削除してください。リスト9-4-1はdefedit.phpの最後の数行ですが、最後の行の頭にある//を削除してファイルを保存しておいてください。INTER-Mediatorのレポジトリにある定義ファイルエディターの機能は意図的に無効化してあります。有効な状態でファイルをサーバーに登録すると、それはあからさまなセキュリティホールになるからです。ここで有効化した場合は、いったんサイト全体を、Webサーバーの認証機能を利用して、ユーザー名とパスワードを入れないと使えない状態にしておくのがいいでしょう。もちろん、システム完成後はdefedit.phpの最後の行の頭に//を入れて、定義ファイルエディターを無効にしてください。そうしないと、誰もが定義ファイルを参照あるいは変更できる状態になります。

リスト9-4-1 定義ファイルエディターを利用可能にする
/**
 * Don't remove comment slashes below on any 'release.'
 */
// IM_Entry($defContexts, null, array('db-class' => 'DefEditor'), false);

小規模なサイトのファイル配置例

 実際のシステムを作るときには、レポジトリのルートに当たるINTER-Mediatorはフォルダーごと、公開フォルダーのルート等にコピーします。レポジトリから直接更新をしたい場合には、サーバー上でgit cloneコマンドを使ってインストールしてもいいでしょう。例えば、数ページ程度のシステムであれば、Web公開ディレクトリの内容としてはリスト9-4-2のようなものになります。それぞれのページが独立したページファイルと定義ファイルから構成されるのであれば、それらは同一のファイル名にしておくのが一番わかりやすい整理方法でしょう。ごく小規模なサイトの場合、ひとつの定義ファイルに対してページファイルが複数存在することもあるでしょう。そのような状態でも問題はありませんが、定義ファイル名であること識別しやすい名前(例えば「def_file.php」など)にしておくと管理しやすくなります。

リスト9-4-2 シンプルなサイトのファイル構成
Page1.html(ページファイル)
Page1.php(定義ファイル)
Page2.html(ページファイル)
Page2.php(定義ファイル)
INTER-Mediator(INTER-Mediator全体を含むフォルダー)
 └ INTER-Mediator.php
 └ ...
params.php(設定ファイル)

 まず、リストの最後のparams.phpファイルですが、INTER-Mediator/params.phpファイルをコピーして、ひとつ上の階層に配置します。そして、params.phpファイルの変更は、INTER-Mediatorフォルダーの外、つまりルート階層にparams.phpファイル側に行います。このファイルがあれば、INTER-Mediator/params.phpの方は無視されます。システム開発の途中でINTER-Mediatorを更新した場合、params.phpファイルがINTER-Mediatorフォルダー内にあれば、更新時にファイルを消してしまうかもしれません。そうなると、細かな設定は全て消えてしまう可能性もあります。それを避けるために、params.phpファイルは外側(つまりINTER-Mediatorフォルダーと同じ階層)に置いて変更して利用しましょう。

 ページファイルに定義ファイルを読み込ませるためには同じディレクトリにある定義ファイルを参照すればよいので、ヘッダー部に直接「src=ファイル名」と指定します。例えばPage1.htmlでは「<script type="text/javascript" src="Page1.php"></script>」のように、SCRIPTタグでsrc属性に単にファイルを記述すれよいでしょう。

 定義ファイルでは、「require_once("INTER-Mediator/INTER-Mediator.php");」のようにして、INTER-Mediator本体を読み込み、IM_Entry関数を利用します。PHPのコードとして記述する場合には、そのまま必要な情報を記入します。もし、定義ファイルエディターを使って定義ファイルを編集したい場合には、リスト9-4-3のように、このrequre_onceコマンドと、IM_Entry関数の呼び出しがあれば良いでしょう。ブラウザーから「http://ホスト名/INTER-Mediator/INTER-Mediator-Support/defedit.html?target=../../Page2.php」のようにURLを指定します。ホスト名以降は、ページファイルヘディタのURLです。これに対してパラメーター指定を行います。パラメーター名は「target」で、定義ファイルエディターがあるフォルダー(つまり「INTER-Mediator-Support」フォルダーから、編集したいファイル(ここでは/Page2.def)までの相対的なパスを指定します。

リスト9-4-3 定義ファイルの最小限の定義
<?php
require_once("INTER-Mediator/INTER-Mediator.php");
IM_Entry(null, null, null, 2);

多数のファイルがあるようなサイトのディレクトリ構成

 ページファイルが数えられる程度なら、ページファイルと定義ファイルを同一のディレクトリに並べても、それなりに管理はできるものです。しかしながら、10種類以上のページファイルがあるような場合にはディレクトリに分類した方がいいでしょう。ひとつのディレクトリ内に複数のページファイルや定義ファイルがあってもいいのですが、これも数が増えてくれば、複数のディレクトリにさらに分類します。さらに、JavaScriptのファイルや、PHPの拡張機能として利用するアドバイス定義ファイルについても、ページファイルや定義ファイルと同じディレクトリに入れておくのが混乱のない方法です。なお、INTER-Mediatorやそのほかのライブラリは、ルートにlibなどのディレクトリを作っておいて、そこにまとめて入れておきます。params.phpはルートではなくlibディレクトリの中に作成します。libにはそのほかのライブラリなどを入れてもいいでしょう。リストには記載はありませんが、CSSについてはルートあるいはlibの中など、配置は自由にできます。

リスト9-4-4 規模の大きなサイトのファイル構成例

FuncA
 └ index.html(ページファイル)
 └ Page1.php(定義ファイル)
 └ Page1.js(JavaScriptファイル)
 └ Extending.php(PHPファイル:アドバイス定義クラスのファイルなど)
 └ Page2.html(ページファイル)
 └ Page2.php(定義ファイル)
FuncB
 └ index.html(ページファイル)
 └ Page3.php(定義ファイル)
 └ Page4.html(ページファイル)
 └ Page4.php(定義ファイル)
lib
 └ INTER-Mediator(INTER-Mediator全体を含むフォルダー)
   └ INTER-Mediator.php
   └ ...
 └ params.php(設定ファイル)
 └ tcpdf(PHPによるPDF生成ライブラリ)

 ページファイルのヘッダー部には、同じディレクトリにある定義ファイルを参照すればいいので、例えばFuncA/index.htmlでは「<script type="text/javascript" src="Page1.php"></script>」のように、SCRIPTタグでsrc属性に単にファイルを記述すればよいでしょう。定義ファイルでは、「require_once("../lib/INTER-Mediator/INTER-Mediator.php");」のように相対パスで指定して、INTER-Mediator本体を読み込み、IM_Entry関数を利用します。

params.phpファイルの修正

 実際にアプリケーションとして使うときに、params.phpファイルの一部を必ず書き換える必要があります。このファイルには、一部の暗号処理で利用される秘密鍵と公開鍵がコードに含まれています。コードに含まれているからといってこれがWebに公開されることはありません。.phpファイルの内容なので、ソースコードは通常は見えませんが、INTER-Mediatorの初期状態のままだと、複数の人が同じ秘密鍵を使ってしまうことになります。これでは鍵を利用して暗号化している意味がなくなるので、鍵の変更をして運用開始しない限りはエラーが表示されるようにしています。

 params.phpのリスト9-4-5の部分を参照してください。この変数$generatedPrivateKeyの値を運用環境に合わせて置き換えていただく必要があります。その直上に暗号キー生成のコマンドが書いてあります。

  実行環境にsshでログインした後、「openssl genrsa -out gen.key 2048」というコマンドを入れると、カレントディレクトリに、gen.keyという秘密鍵を記録したファイルが作成されます。そのファイルの中身を、「-----BEGIN RSA PRIVATE KEY-----」から「-----END RSA PRIVATE KEY-----」の部分にコピー&ペーストして、ファイルの内容に置き換えてください。ファイルの内容は、「-----BEGIN RSA PRIVATE KEY-----」で始まり「-----END RSA PRIVATE KEY-----」で終わっているはずですので、エディターで開き、コピーして元からの値を置き換えるようにペーストすればそれで構いません。保存も忘れないようにしてください。

リスト9-4-5 params.phpの秘密鍵と公開鍵を記録している部分
/*
Command to generate the following RSA key:
$ openssl genrsa -out gen.key 2048
 */
$passPhrase = '';
$generatedPrivateKey = <<<EOL
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyTFuj/i52z0pXsoa6HNTUFcmWBcaG5DodB5ac6WAKBxn4G/j
knKwIBjRluCjIcRdFk6m91ChSOoDvW3p3rk2UFMIfq9e6ojhsWO3AFrHXOVHt+P/
QWnI2KUtUmxO0jw9hbqK/Hl4IbWc8aGnxP/uGOmLJnLSP3wEtahXXaVSJrGTPZuk
	:
UeplZBKmxW3+wQ5gVWIguqisfvi9/m07Z/3+uwCLSryHU6Kgg7Md9ezU9Obx+jxp
cmyuR8KhUNJ6zf23TUgQE6Dt1EAHB+uPIkWiH1Yv1BFghe4M4Ijk
-----END RSA PRIVATE KEY-----
EOL;

INTER-Mediatorフレームワークのビルド

 INTER-Mediatorのフォルダーは、そのままでもアプリケーション稼働に利用することができますが、さらに効率を少しでも上げたい場合には、「ビルド」の作業をして、効率アップが可能です。ビルドの作業により、以下の状態になります。

 ビルドを行うには、INTER-Mediatorフォルダーのdist-docsフォルダーをカレントディレクトリにして、buildup.shスクリプトを稼働させてください。macOSの場合はターミナルで実行します。Windowsの場合はCygwinで実行できるようになっています。macOSの場合、カレントディレクトリを移動してスクリプトを実行することになるので、例えばINTER-Mediatorディレクトリのひとつ上位のディレクトリがカレントの場合だと、リスト9-4-6のようにコマンドを入れます。「./buildup.sh」をタイプインすると、どのようなタイプのビルドを作り上げるか聞いてきます。「Type 1, 2, 3 or 4, and then type return」と出てくるので、アプリケーション公開のために必要な最小限のファイルを用意するなら「2」を選択します。

 ちなみに。「1」は文字通りINTER-Mediatorの全ファイルを含むパッケージを、「3」はユーザー認証や定義ファイルエディター/ページエディターを含むシステムを書き出します。これらを選択するときは公開サーバーで運用するために本当にそれが必要か、攻撃者から守るための完全なセキュリティブロックが構築できるか、を十分に考慮した上で、選択してください。

 なお、yuicompressorは、INTER-Mediatorの配布ファイル内にはありません。INTER-Mediatorフォルダーと同じ階層にダウンロードしたファイル(例えば「yuicompressor-2.4.7.jar」)を配置してください。もし、異なるバージョンのyuicompressorを使用するなら、buildup.shスクリプトの最初の方に、ファイル名を記載する場所があるので、そこを修正して実行してください。

リスト9-4-6 INTER-Mediatorのビルド作業
$ cd INTER-Mediator/dist-docs
$ ./buildup.sh
=================================================
 Start to build the INTER-Mediator Ver.5.6-dev
-------------------------------------------------
 Original: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator
 Build to: /Users/msyk/Documents/INTER-Mediator_develop/im_build/INTER-Mediator
-------------------------------------------------
Choose the build result from these:
 (1) Complete (everything contains)
 (2) Core only (the least set to work wep applications)
 (3) Core + Support (add Auth_Support and INTER-Mediator-Support)
 (4) Write just version and release date to metadata.json
Type 1, 2, 3 or 4, and then type return----> 2

PROCESSING: Copying php files in root
PROCESSING: Merging JS files
Detected OS: Darwin
PROCESSING: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator/DB_Support
PROCESSING: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator/lib
PROCESSING: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator/dist-docs/License.txt
PROCESSING: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator/dist-docs/readme.txt
PROCESSING: /Users/msyk/Documents/INTER-Mediator_develop/INTER-Mediator/themes

=================================================
 INTER-Mediator Ver.5.6-dev was successfully Build
 Check out: /Users/msyk/Documents/INTER-Mediator_develop/im_build
================================================= 

 スクリプトを実行すると、最後の行に作成したディレクトリが記載されます。これを見るとbuildup.shからさかのぼって、INTER-Mediatorフォルダーと同じ場所に、im_buildフォルダーを作成していることが分かります。その中にある「INTER-Mediator」フォルダーが、最小限のファイルのディレクトリです。

 作成された「INTER-Mediator」フォルダーを、実際に利用する公開サーバーにINTER-Mediatorとして配置して利用すればいいのですが、いくつか注意点があります。まず、オリジナルの形式の「INTER-Mediator」フォルダーに比べて、buildup.shで生成した「INTER-Mediator」フォルダーの中身は、サンプルなどがないだけでなく、プログラムのファイルのうち.jsの拡張子を持つJavaScriptのファイル群について構成を統合し、ファイル数を減らします。オリジナルの「INTER-Mediator」フォルダーがファイルサーバーにアップされている状態で、そのフォルダーをbuildup.shで作った「INTER-Mediator」フォルダーに置き換えてアップロードすると、手順によっては本来はないはずのファイルが、サーバー上に存在してしまうこともあります。具体的には、オリジナルには存在する「INTER-Mediator-Lib.js」ファイルは、buildup.shの処理により「INTER-Mediator.js」ファイルに取り込まれます。しかしながら、サーバー側で稼働するINTER-Mediatorにはもともとの「INTER-Mediator-Lib.js」が存在するため、「INTER-Mediator.js」に統合されているにもかかわらず実行時に同じコードを重複してマージしてしまい、エラーとなります。このことを避けるには、build.shで作成したものに置き換える前に、サーバー上の「INTER-Mediator」フォルダーを一度確実に消してしまうことをお勧めします。また、ビルドした「INTER-Mediator」フォルダーは、gitのレポジトリとは切り離されます。レポジトリとの連動をしたい場合には、再度別のディレクトリを用意するなどが必要ですので、INTER-Mediatorの中身をタッチしながら開発する場合には、実際に運用に入る直前にビルドをするのが良いと思われます。

 ビルドした結果、パフォーマンスがどれくらい向上するかですが、ネットワークが細い場合には、効果が体感できるでしょう。Ver.5.6-devでビルドしないでJavaScriptのプログラムをダウンロードすると569KBでしたが、ビルドしたものであれば231KBと半分以下になります。イントラネットの場合ではそれほど体感的には速くならないかもしれませんが、キャリアの通信で遅い場合には影響が出そうなくらいのサイズです。

INTER-Mediatorディレクトリを非公開にする

 INTER-MediatorディレクトリをWebサーバーの公開ディレクトリに置くのは危険と思われるかもしれませんが、一方で、定義ファイルエディターや、ユーザー管理のアプリケーションなどが最初から稼働しないような仕組みにしてあるので、PHPが動く状態になっていれば問題はないと考えます。params.phpファイルにデータベースのパスワード等を記述しますが、これもPHPが稼働していれば、クライアントにパスワードの文字列が漏洩することはありません。

 それでも、やはりINTER-Mediator自体を非公開のディレクトリ(例えば「/usr/local/share」など)に置いて運用したいと思われるかもしれません。しかしながら、現状、一部の機能で、公開ディレクトリに存在することを前提としたものがあります。将来的には非公開ディレクトリでの運用も可能にはする予定ですが、Ver.5.4-dev現在ではWebで公開したディレクトリ内に配備してください。なお、非公開ディレクトリで運用するには、PHPのクラス検索パスを必ずカスタマイズする必要が出てくると思われます。

このセクションのまとめ

 INTER-Mediatorを使ったWebサイトのファイル配備の例や、params.phpファイルで置き換えの必要な箇所、そして、INTER-Mediatorをビルドして、若干の高速化を行う方法などをこのセクションで説明しました。