Comments
Description
Transcript
プロジェクト サービス提供型のホームページを作る 第1章
プロジェクト サービス提供型のホームページを作る 第1章 プロジェクトの概要 [1] プロジェクトの概要 最近のアプリケーション提供の傾向として、ホームページを介したサーバーによるサービス提供が目立つようになった。こ のプロジェクトでは、このスタイルのサーバーを作る。 ここで目指すのは、そのようなサーバーの仕組・構造を理解し使いこなすことであり、実はサービス本体の内容はあまり 気にしていない。といっても、つまらないサービスでは作る気がしないので、自分たちで面白いサービスを考えてくれれば よい。 プロジェクト期間の前半は仕組・構造の理解とそのための予備実験に充て、後半で自分たちの創意工夫に基づくサービ ス提供を考えよう。但しサービスにはこのプロジェクトの目的から導かれるいくつかの条件を、満たすことを要求する。そ の範囲内で、自由に工夫して欲しい。 Web サーバ [2] 仕組の概要 端末 静的 仕組を理解するのに、2つの見方を示しておく。 ページ データ ≪見方1: 動的なホームページ≫ 旧来のホームページは、予め作られた内容(コンテンツ)がサーバ 動的 ー上のデータ(ファイル)として置かれており、ユーザ端末上のブラ ウザ(Internet Explorer, Netscape, Firefox などの閲覧アプリケーシ アプリ ケー ション プログ ラム ョン)はそのコンテンツをサーバーから取り出して表示する。この時、 コンテンツはいつでも同じ内容であり、変化しないので、静的と呼べ るだろう。 それに対して、サーバーがコンテンツとして何らかの計算処理の結 果を送り出すような場合がある。たとえば、オンラインショッピングの サイトでは、ユーザが商品を選択し個数を入力すると、合計金額が 表示され、更にクレジットカードなどでの決済の処理が行われる。こ れは、ユーザが端末から与える情報(商品の選択・個数など)を、サ ーバーが受け取って計算処理をし、結果をサーバー側に保存する と同時にユーザ端末にも表示している。このようにサーバー側で処 理を行いその処理結果(状況によって結果が異なる)を表示するよ うな場合を、動的と呼べるだろう。 このプロジェクトで扱うのは、動的なホームページの構築方法であ る。 アプリケーション プログラム アプリケーション プログラム ≪見方2: ネット越しのアプリケーションサービス提供≫ たいていの動的なホームページでは、端末に座るユーザが何かの 入力データを与え、サーバー側にあるアプリケーションプログラム 単独PCアプリ (上記で言えばオンラインショッピングのアプリケーション)が処理し、 出力結果をユーザの端末にホームページの形で表示する。言い換 えると、従来のアプリケーションは手元のPCにプログラムをインスト ールし、それを起動して必要な入力を与えるとプログラムが処理し、 アプリ ケー ション プログ ラム 出力結果を画面に表示するのに対して、ここで構築するアプリケー ションはサーバー側に置かれており、ユーザとの入力・出力はホー CGIプロジェクト1 ネット越しのアプリケーション提供 1 ムページ画面(Web 画面)を通じて行う。つまり、従来の、手元 PC にアプリケーションをインストールする代わりに、サーバ ー上にアプリケーションを置いて、その入出力だけを手元PCのホームページ画面(ブラウザ上の画面)に引いてきたもの、 と考えることが出来る。 上記の2つの見方は同じものを指しており、見る立場が異なるだけである。 [3] Web とアプリケーションの繋がりと、CGI (Common Gateway Interface) アプリケーション提供を考えるとき、サーバー上に置いたアプリケーシ ョンの入出力を、Web 経由で行うことが、この方式の特徴である。ネッ 固有 アプリ 固有 トを越えて入出力を手元のPC端末に見せる方法としては、別にホー 固有のルール サーバ ムページ(Web)技術に頼らなくても、たとえば独自の方法でやり取りし ても構わない。のではあるが、このやり取りをホームページ技術にす ることによって、たいていのPC(たいていのPCにはブラウザが搭載さ れているから)を入出力端末として使うことが出来るようになる。独自 Web のやり取りだと、それに対応する端末側のソフトを手元 PC にインスト ブラウザ ールしなければならず、何かと不便になる。手元PCのブラウザの機 Web サーバ Webのルール 能は、もちろん万能ではなく制約も多いという欠点もあるが、とにかく どのPCでもたいてい使えるという利点がある。 手元PCのブラウザと、(Web)サーバーとの間のやり取りの仕方は、イ ンターネット上で標準化されている。データのやり取りの手順は HTTP (HyperText Transfer Protocol) 、 デ ー タ 自 体 の 形 式 は HTML Web ブラウザ Web (HyperText Markup Language) と呼ばれる仕様が標準として定められ サーバ ており、ブラウザはこれにしたがって作られており、この仕様の範囲 HTTP: やり取りの仕方 「データXXを下さい」 「了解、以下データです」 HTML: データ中身の書き方 タイトルは***** 本文段落開始 ここへ絵を入れる など 内での動作はどのブラウザでも利用できる。この約束についてはあと から詳細を学ぶことにする。 このやり取りの仕方の約束は、右図にあるようにサーバーと端末の ページ データ 間(図ではネットの線に直交する面を通過するとき)のやり取りの約束 であることに注目して欲しい。だから、この約束さえ守れば、端末側のプログラム(Web ブラウザ)がどんな形をしていよう と、またサーバー側のプログラム(Web サーバ)がどんな形をしていようと、構わない。たとえば、端末側のプログラムが通 常のブラウザと違って、全く表示をしないがその代わりにその内容を溜め込むプログラムでもよいし、サーバーから送ら れてきたデータを更に別のサイトに送りつけるプログラムでもよい。 この約束の決め方こそが、動的ホームページを可能にしている。つま Web り、Web サーバーの側でどのような形でデータを提供しようと、ネットワ ブラウザ ークの境界面(図の直交する面)で約束を守っていれば、端末側は普 通のブラウザで表示できる。静的な(予め用意したホームページ画面 を表示するような)ページでは、保存されたページデータを(ディスクか ら)読み出してネットワークへそのままの形で送出するが、動的なペー ジでは保存されたページデータの代わりにサーバー側のアプリケーシ ョンプログラムが計算処理を行い、その結果を Web サーバを介してネ Web サーバ HTTP: やり取りの仕方 「データXXを下さい」 CGI 「了解、以下データです」 HTML: データ中身の書き方 アプリ タイトルは***** ケーション 本文段落開始 プログラム ここへ絵を入れる など ットワークへ送出する。 なお、、アプリケーションプログラム(計算処理を担当)と Web サーバ CGIプロジェクト1 2 (やりとりを担当)の間の受け渡し(境界、インターフェース)を CGI (Common Gateway Interface) と呼ぶことがある。 [4] プロジェクトで使う枠組み まず初めに、このプロジェクトで使う枠組み(Apache+PHP+MySQL)を説明する。動的な Web サイトを作る方法は他にも いくつかあるが、それらはあとから紹介するので、ここではこの枠組みが唯一ではないこと、条件によっては他の方法の 方がよいこと、を心に留めておいて欲しい。 ≪Apache Web サーバー≫ Apache は Web サーバプログラムであり、最初は(おそらく)静的ページを表示するものだった(注: 細かい歴史は apache のホームページ http://www.apache.org/httpd や Wikipedia などで調べてみるとよい)。 現在は静的ページと動的ペー ジの両方をサポートしている。動的ページの実現には CGI (Common Gateway Interface) を提供している。 プロジェクトでは、apache の Web サーバーが既に動作しているサーバーマシン上で、ページを作る作業に終始する。言い 換えると、apache Web サーバー自体のインストールや設定は自分では行わない。もちろん、興味のある学生は自分の PC へインストールしてみるのもよいだろうし、その環境が自分で用意できないが是非やってみたいという学生には、イン ストールできる PC を一時的に提供することも考えるので、相談して欲しい。 プロジェクトでは、静的なページと動的なページを両方作って見たい。静的なページの内容は、HTML(HyperText Markup Language)という規約(仕様)に従って記述する。これは CGI に入る以前の知識として、一通り試してみたい。 ≪PHP プログラミング言語≫ 動的なページ(実はプログラム)は、PHP (正式名称は PHP: Hypertext PreProcessor) という言語を用いて記述するこ とにする。動的ページの実現方法は多数あり、それぞれに使われているが、比較的簡単で学習が容易、かつ、世の中で は結構使われている(いた)、という理由から PHP 言語を選んでいる。PHP の大きな特徴として、静的なホームページデ ータを格納したのと同じ場所に PHP のプログラムを用意し、実行できることが挙げられる。簡単に使えるので便利なのだ が、それによる欠点(たとえば、設定が甘いとプログラムを読まれてしまう)もあり、賛否は分かれる。PHP 言語の詳細は ホームページ http://www.php.net を参照のこと。プロジェクトでは PHP を使ってどんどんプログラムを書いて欲しいが、 プログラムの書き方については、後からまとめて学習する。 PHP はインタープリタ(逐次解釈)型のプログラミング言語である。PHP 単体でプログラムを作ることも可能であるが、プロ ジェクトでは Apache Web サーバーの後方に居て、ホームページからデータを受け取って起動され、処理結果をホームペ ージに返す形の使い方をする。PHP で書いたプログラムと Apache Web サーバーとの間のやりとりのインターフェースは、 CGI に相当するもの(mod_php)を使うが、PHP プログラムから見ると、端末から入力されたデータはいくつかの特別な変 数によって伝えられる。また端末で「送信」(submit)ボタンをクリックすると、指定した PHP プログラムが起動される。出力 側は、普通に文字列を print すると端末のブラウザにそのまま送られて、HTML として解釈される。 これらは、後から実例 を持って試してみる。 PHP の処理環境、つまり PHP の実行エンジンや Apache Web サーバーとの間のインターフェースモジュール(mod_php) は、プロジェクトではすでに提供されている。これらのインストールや設定は自分では行わない。興味のある学生は、 Apache Web サーバー同様に、自分の環境へインストールしてみるとよい経験になるだろう。 ≪MySQL SQL データベース管理システム≫ 最後に紹介するのが SQL 型データベース管理システム MySQL である。Apache Web サーバーと PHP で動的 Web ペー ジは作成できるし、そのようなシステムも多数使われているが、ここでは比較的定番である、データベースと組合せた利 用についても見ておきたい。そもそも、データベースは授業で理論は学ぶのだが、黒板だけではおよそ実感が湧かない。 データベースを体感する(Apache や PHP を抜きにしても)意味でも、プロジェクトの要素にデータベースを入れておく。 CGIプロジェクト1 3 データベース データベースは、同じ形のデータをたくさん保持し、検索 したり並べ替えたりできる、データ管理のソフトウェアで ある。たとえば学生に関する情報(氏名・学籍番号・生年 月日・現住所…)を1人の学生の記録(レコード)とし、東 アプリ ケーション 邦大学全体の学生の記録を集めたデータベースを考え 検索 取出し ソート 追加 … 山田 の 記録 田中 の 記録 佐藤 の 記録 ると、右図のようになる。 オペレーティングシステムとユーザアプリケーションの中間に位置するこ のようなソフトウェアシステムを、ミドルウェアと呼ぶこともある。つまり、い ろいろなアプリケーションがデータベース管理システムを使いに来るとい SQL インター フェース アプリ アプリ アプリ (関係)データベース うモデルである。 OS 実はデータベースの種類には(データのモデルの違いによって)いくつか のものがあり、ここでは現在広く用いられている「関係」モデルに基づいた関係データベースに限定して考える。データモ デルなどの細かいことはデータベース論の授業で学んで欲しい。 このとき、アプリケーションと関係データベースの間のインターフェース(共通の操作言語)として、SQLが広く使われてい る。MySQL はこのような関係データベースの管理ソフトウェアの1つである。関係データベース(とSQL)を提供する管理 ソフトウェアは MySQL 以外にもいくつも製品化されており、たとえば PostgreSQL、SQLite、Oracle、IBM DB2 などの名前 を聞くことがあるだろう。MySQL の詳細はホームページ http://www.mysql.com を参照のこと。なおホームページは有料 版(MySQL Enterprise)と無料版(MySQL Community Server)があり、わかりにくいが、学生が実験するには無料版で十 分であろう。 SQLを使った関係データベースの簡単な操作を、このプロジェクトの中で試して欲しい。 では、そのような関係データベースが利用できるとして、なぜ Apache Web サーバー+PHP CGI という「Web アプリケーシ ョン」と呼ばれるような枠組みの中に出てくるのだろうか? おそらくは、Web アプリケーションのかなりの部分が、サーバ ーにデータを保存し、検索し、表示するような目的を持っているからではないだろうか。 たとえば、皆さんがいつも使う成 績のシステムを考えてみると、成績のデータをサーバーに保存しておき、学生は学期の初めに授業登録するときに変更 し、教員は学期の終りに成績を出して追記する。成績データをデータベースに保存し、必要に応じて検索したり情報を抽 出したり並べ替えたりして、表示したい。別の例として掲示板がある。掲示板に今までに書き込まれたデータをデータベー スに保存し、ユーザが書き込むときにはデータベースに追記し、見るときには検索したり抽出したり並べ替えたりして表示 する。これもデータベースがあれば簡単にできる。ショッピングも然り、アンケードも然りであろう。検索・抽出・並べ替えな どを自分でプログラムするのは面倒だし、安定して安全にデータを保存できる仕組を作るのも経験が要る。それを、デー タベースシステムは提供してくれているので、便利に使おうということになる。 Web アプリケーションからデータベースを利用するためには、(1)データ操作のためのSQL言語、(2) PHP プログラムから データベースへSQL言語のコマンドを出す方法と、データベースからの結果を取り出す方法(つまり PHP と MySQL との 間のインターフェースの使い方)、の2点を知っている必要がある。幸いなことにいずれもそれほどややこしくない。後から 具体的に紹介する。 [5] 余談1 Apache Web サーバー+PHP 以外の、動的 Web サーバーを作る枠組み ≪CGI を使う方法≫ CGIプロジェクト1 4 CGI のインターフェースを使うのだが、Web サーバー(ネットワークとのやり取りをする側)に使うソフト、アプリケーション (CGI インターフェースの裏側で動くプログラム)を作るのに使うプログラミング言語、の2つの要素が変更可能である。 Web サーバー側は、CGI を使うという前提では、おそらく Apache Web サーバーと、Microsoft 社の Windows Server に付随 する IIS (Internet Information Server)がほとんどであろう。それ以外のソフトもあるが、あまり多くは使われていないようだ。 この2者は、サーバーのOSが Windows であれば両方とも利用可能(Apache Web サーバーも Windows 用バイナリが提供 されている)であるが、その他のOS、具体的には Linux, Unix, MacOS X(OSコア部分は UNIX 系)では IIS は提供されな いので Apache のみとなるだろう。 Web アプリケーションのプログラム言語は、ここで挙げた PHP の他、Perl、Java、Ruby などが多く使われているだろう。本 質は、CGI の約束さえ守れば何の言語で記述してもよい。たとえば C 言語でも作ることが出来る。使い勝手やデバッグの 容易さから、インタープリタを介するスクリプト言語が多く使われているようだ。Cのようなコンパイル言語の場合は、コン パイル済みの実行ファイルを CGI の裏側に準備し、端末の「送信」によって実行ファイルを立ち上げるような形になる。 ≪専用の Web サーバー(コンテナ)を使う方法≫ 裏側でアプリケーションを走らせることを最初から念頭に置いた構造のサーバーが作られ使われている。たとえば、Java のアプリケーションを想定したサーバーとして Apache プロジェクト内で作られている TomCat が挙げられるが、これは Web アプリケーションを記述した Java プログラム(クラスになる)を、サーバー内に取り込んで実行する形になる。コンテナなど と呼ばれることがある。 コンテナにするメリットの1つに、実効効率がある。CGI 方式の場合は裏のプログラムをプロセスとして「立ち上げる」のが 標準的なスタイルで、立ち上げの時間がかかったり、メモリが余分に必要になったりする。立ち上げ時間を短縮するため に予めプロセスをプールしておいて与える方式も使われているが、プールの数が固定されるなど完全に解決しているわ けではない。コンテナ方式の場合はサーバーとして動いているプロセスがそのまま変身するので、プロセス立ち上げなど のOS操作に伴う手間は必要なくなる。 今回のプロジェクトではこちらは使わない。 CGIプロジェクト1 5 第2章 ホームページとHTML(タグ) ここでは HTML タグについて、今まで使う機会が無かった学生を対象に説明する。既に HTML タグを使ったことのある学 生にとっては、知っている話になると思うので、ざっと目を通すだけでよいだろう。初めての学生は、演習等を通じて使い 慣れて欲しい。 [1] HTML 通常の(静的な)ホームページは、ホームページサーバー(Web サーバー)から手元の端末に、ページ画面の情報が転送 され、それを手元の端末上で動いているブラウザ(Microsoft Internet Explorer とか Netscape Navigator とか Mozilla Firefox とか Opera ブラウザとか)が解釈して画面に表示している。 サーバーから端末に送られてくるページ画面の情報は、たとえば下記の例のようなデータになっている。このような情報 の書き方(の規則、言語)を、HTML(HyperText Markup Language)と呼んでいる。 <html> <head> <title>私のページ</title> <meta http-equiv=Content-Type content="text/html; charset=shift_jis"> </head> <body> <p>あーたらどーたら</p> </body> </html> 三角カッコ(angle bracket)に囲まれている<html>とか<head>などのことをタグと呼ぶ。別の授業・実験などでタグを見てい るかも知れない。 上記の例で使われているタグは、次のような意味を持っている。 始めのタグ 終りのタグ 意味 ブラウザの解釈 <html> </html> これは HTML 文書です ページを始める <head> </head> ヘッダー部分です タイトルはブラウザの枠に表示 <title> </title> この部分がタイトルです 同上 メタ情報 メタ情報はブラウザが記憶。表示はしない <meta ...> <body> </body> この部分が本文(body)です タグに指定されたように表示 <p> </p> この部分がパラグラフです パラグラフとして表示。上下に1行ずつ空白行。 あとは文字列を流し込み この他にもいろいろな種類のタグが定義され、使われている。たとえば、箇条書き(リスト形式)を作る一連のタグ(ul、ol、 dl などと、その中に項目を書く li タグ)や、表(テーブル)を作る一連のタグ、文字の大きさや色を指定する一連のタグ(文 字の大きさ、色、フォントなど)、文字の修飾をする一連のタグ(太字、強調、上付き、下付き、下線など)などは、すぐにで も使うかもしれない。また、上の表にある meta タグは、タグの中で文書のメタ情報を指定する様々なパラメタを書くことが できる。 ここはタグの参考書ではないので、細かい点は割愛する。参考書が多数出版されているし、ホームページを探してみると いろいろに解説されている。 CGIプロジェクト2 1 なお、細かく言うと、HTML にもバージョンがあり 1998 年 4 月の HTML4.01 が使われているが、(1)ブラウザの種類によっ て機能のサポートに差がある、(2)ホームページデータも厳密に最新の規約に従っていないものが多く散見される、など、 細かい点ではかなりあいまいになっているようにも見える。プロジェクトで使う HTML は全体から見るとごく一部で、あまり 厳密さも要求されていない部分である。 [例題演習 2-1] 簡単なホームページデータを作って、アップしてみよう。 まずは、いろいろなタグを試してみて慣れることにしよう。 やることは、 <html> <head> (1) 簡単なホームページデータをファイル(テキスト)として作り、 <title>私のページ</title> (2) ホームページとしてアップしてみる、 </head> の2段階である。 <body> <p>これは私のページです。</p> ≪アップのやり方≫ テキストをタイプインする前に、(2)の点について先に説明しておこう。今作ろ うとしているのは、静的な Web ページである。右図にあるような、HTML で書 </body> </html> かれたファイルを、Web サーバーのディスク上に置くと、端末からの閲覧要求に応じて Web サーバーソフト(Apache Web サーバー)がこの内容を端末側に転送する。端末側ではこの内容を受け取ってブラウザが HTML タグを解釈して表示す る、というシナリオだったはずだ。だから、この HTML データはサーバーのディスクに置けばよい。普通はこの HTML デー タをファイルとして作る作業は、ユーザの手元の端末であり、Web サ ーバーマシン上で編集することはない。 もちろん、サーバーマシン上で編集しても構わない。自分用の Web サーバーマシンを手元に立ち上げて、その端末からファイルを編 Web ブラウザ Web 集すれば、直接編集することも可能である。でも大抵はプロバイダ や大学が用意したサーバーを使うので、編集は手元の端末PCで 行うことになる。 手元PCで作成したホームページコンテンツをサーバーのディスクに 移すことを、「アップする」と呼ぶ。 アップ (転送) HTML ファイ ルの編集 サーバ ページ データ 編集 プロジェクトで使う情報科学科実習室のシステム環境は、上で述べた通常のものと少し異なる。実習室で使う手元のPC は、実験室サーバー(これが Web サーバ ーを兼ねている)のディスクを共有してい る(正確には、サーバーのディスクを手元 Web のPCが遠隔参照~リモートマウント~し サーバ ている)。具体的にはPC上の Z-disk とし ユーザ foo の Z-disk て見えているものが、実体はサーバー上 のディスク(正確には各ユーザのホーム ディレクトリ)になっている。であるから、 Z-disk 上の public_html ユーザ foo の ホームディレクトリ ユーザ foo の中の public_html 手元の PC 上で Z-disk にファイルを置け ば、そのファイルはサーバー上のファイ ルになっている。 サーバー上の foo のホームディレクトリを 端末PC上では Z-disk として見せている 更に、各ユーザが自由にホームページを持てるように、Web サーバーはサーバーマシンの各ユーザのホームディレクトリ の中の特別な名前「public_html」のディレクトリを、ホームページとして公開するという設定になっている。したがって、 Z-disk 上の直下にディレクトリ(フォルダ)public_html を作成し、そのフォルダ内にホームページとして公開したい HTML ファイルを置けば、Web サーバーを介してそのファイルが公開される。なお、このホームページは URL http://pegasus.is.sci.toho-u.ac.jp/~********/ファイル名 CGIプロジェクト2 2 但し、半角~は波線(正式名称ティルダ tilda)であり、その後の*******の所に学生番号(本当はこのシステムのユーザI D)7桁(550????)を入れたものである。波線~の入力は、キーボードではシフトキーを押しながら上線(キーボード最上段 のひらがな「へ」の上)でできるはずである。(場合によってはシフトを押しながら~キーのこともある) まとめると、手元の端末PCの Windows 上の Z-disk に、フォルダ public_html を作り、その下にホームページとして公開し たいファイルを置く。そうすると、上記の URL として公開される。 ≪HTML ファイル作成≫ では、上に掲げた HTML テキストを、Windows のテキストファイルとして入力・作成せよ。Windows であれば、たとえば「秀 丸」や、メモ帳(notepad)などのテキストエディタで作ればよい。ファイル名は、Z-disk 上の public_html の下で、index.html という名前を付けておこう。 ( Z:\public_html\index.html )この時使う URL は http://pegasus.is.sci.toho-u.ac.jp/~********/index.html となる。但し、*******のところに学生番号 550????を入れること。 もし既に public_html フォルダを使っていてそこに index.html などのファイルがある学生は、このプロジェクト用のフォルダ myproject を、public_html の中に作成すればよい ( Z:\public_html\myproject\index.html )。 この時は URL は http://pegasus.is.sci.toho-u.ac.jp/~********/myproject/index.html となる。上と同様に、*******のところは学生番号 550????である。 ところで、この index.html というファイル名はちょっと特別なものである。普通は URL でページを指定するときは http://pegasus.is.sci.toho-u.ac.jp/~5555555/index.html のように、ファイル名 index.html まで記述しなければならない。だが、よくファイル名を書かず、ディレクトリ名(フォルダ名) までで終りになっている URL を見かける。たとえば http://www.toho-u.ac.jp/ のように、ファイル名を書かないとき、Apache Web サーバーの指定で、自動的に index.html というファイル名が使われる ようにできる。実験室のサーバーもこの設定がしてあるので、実は http://pegasus.is.sci.toho-u.a.cjp/~5555555/ まで書くだけで、その下の index.html ファイルが表示される。 注) pegasus サーバーは UNIX (正確には Sun Solaris)を使っている。OS によってど の漢字コード体系を使うかが違うので、注 意を要する。Windows 系は Shift-JIS が標 準的に使われているし、UNIX 系は原則的 に EUC か UTF-8 を使っていることが多い。 上で説明したようにディスク空間を共有して いると、たとえば Windows で書いた漢字を 含むファイルは、Unix では漢字コードが異 なるために文字化けして読めない。 特に、ファイルの名前については、漢字(か なを含む2バイトコード)を使わないこと。さ もないと、相手側の環境では一切ファイル 名が指定できず、操作できないということに なる。 注) Windows では、ファイル一覧を表示するときに、ファイル名の拡張子(ファイル名の最後につく、ピリオドから後の CGIプロジェクト2 3 文字列、たとえばワープロファイルなら「.doc」、エクセルファイルなら「.xls」、テキストファイルなら「.txt」、写真を撮った JPEG ファイルなら「.jpg」など)のうち一部のものについては≪表示しない≫というモードに、初期値が設定されている。 たとえば.txt 拡張子を表示しないと、ユーザが index.html というファイルを作ったつもりでも、index.html.txt となってい たりすることがある。(これは、テキストエディタが自動的に.txt を追加することがあるためである。) これは混乱の元なので、原則は≪表示する≫モードにしておくのがよい。具体的には、ファイルの一覧表示 (Exlplorer というプログラムですが)で、上のほうにある「ツール(T)」から「フォルダオプション(O)」を選び、「表示」タ ブを開いて、次の2つの設定を変更する。 (1) 「ファイルとフォルダの表示」で、「すべてのファイルとフォルダを表示する」を選ぶ。 (2) 「登録されている拡張子は表示しない」にチェックマークを入れる。 ここでOKを押せば、このフォルダだけでこの設定がされるが、後のためには、まず「適用(A)」をクリックした後、上か ら 1/3 ぐらいにある「すべてのフォルダに適用(L)」をクリックする。 注) public_html フォルダの内容は、外部(学外つまり全世界)からホームページとして見えているので、ファイルの内 容に注意すること。たとえば、住所・電話など公開したくない個人情報が含まれないように気をつけること。公開され た内容について責任を問われるので、いい加減な情報や虚偽の情報、誹謗中傷などを掲載しないこと。大学として のサイトであるから、大学を傷つけるような内容を含まないこと。 また、このフォルダ内に作りかけのファイル等を不用意に置かないこと。そのままの形で公開されてしまっている。 ここまでで、自分の作った HTML ファイルのページが、手元の PC のブラウザで見えただろうか? ページの中には「これ は私のページです。」という文字が入り、枠の部分に「私のページ」というタイトル(<title>タグで指定した内容)が入ってい るはずである。 見えない場合、作成したファイル名がおかしいことがある。前に述べたように、拡張子を表示しないモー ドになっていると気づかないのだが、自分で index.html というファイルを作ったつもりで実は index.html.txt というファイルを 作ってしまっていることが起こることがある。拡張子を表示するモードにしてから、ファイル名を確認して欲しい。または、フ ァイルのリストを表示している中で、そのファイルを右クリックし、最下段の「プロパティ」をクリックすると、そのファイルの 属性情報が表示されるが、その中にファイル名が表示されているはずであるので、それで確認することも出来る。 注意) Windows のファイルのリストの中で、index.html ファイルをダブルクリックすると、その内容がホームページのよ うに表示される。これは、我々が今意図している見え方(Web サーバーから端末へ送られて見える)ではないので、注 意して欲しい。これは、手元にあるファイルをブラウザで見ているだけで、Web サーバーによる転送を経ていない。< 同じに見えるのだからいいじゃないか>と思うが、あとで PHP による動的ページを表示したときに、大きく差が出てく る。この節で扱っている静的なページは、どちらで見ても同じになるだろう。後のことを考えて、ちゃんとブラウザの URL 欄に pegasus の名前を入れてアクセスすること。 ≪少し複雑なタグ≫ <body> ... </body>の中身を、自由に変えてみましょう。 (1) ヘッダー 「ヘッダー」は、章・節・パラグラフのタイトルであり、レベルが1から6まである。最も大きい単位はレベル1で、 <h1>この章のタイトル</h1> のように書く。<h1>が開始タグ、</h1>が終了タグである。 <h1>章タイトル</h1> <h2>節タイトル</h2> <h3>パラグラフタイトル</h3> <p>パラグラフの本文を書く。 <h3>パラグラフタイトル2</h3> <p>パラグラフの本文を書く CGIプロジェクト2 4 <h2>節タイトル</h2> <h3>パラグラフタイトル</h3> のように使える。 なお、パラグラフ本文は<p>で始める。 (2) 箇条書き 家で飼う動物には3種類ある 家で飼う動物には3種類ある 箇条書きは、数をつける 1. 犬 ・ 犬 Ordered List (左側)と、数をつ 2. 猫 ・ 猫 けない Unordered List (右側)が 3. ・ うさぎ うさぎ ある。Ordered List は<ol></ol>で 囲 み 、 Unordered List は <ul> </ul>で囲む。内容項目はそれぞ れ<li>で始める。 このほか、<dl>も使われる。 <ol> <li>犬 <li>猫 <li>うさぎ </ol> <ul> <li>犬 <li>猫 <li>うさぎ </ul> (3) 絵(イメージ) 絵(イメージ)をホームページに載せるには、 <img src=”http://pegasus.is.sci.toho-u.ac.jp/~自分の ID/(イメージファイル名)”> のように、<img>タグを使う。src=の後にイメージファイル(画像ファイル)の URL を指定する。 HTML 文書と同じサーバー内にイメージファイルを置く場合は、URL の代わりにファイル名だけを書くことも出来る。特に HTML 文書と同じディレクトリにおく場合には、ファイル名で書くと簡単になる(相対パス指定)。 <img src="henohenomoheji.PNG" width="212" height="200" border="0" align="right"> この例では、イメージファイルのファイル名は henohenomoheji.PNG である。その他に絵の表示寸法: width(幅)が 212 ピ クセル(画素)、height(高さ)が 200 ピクセルであること、border(周りの線)の太さが 0 つまり枠を描かないこと、最後に align(位置合わせ)が right(右そろえ=画面の右側のふちに合わせる)であることを指定している。指定しているそれぞれ の「値」の部分(212 とか 200 とか 0 とか right)を二重引用符「”」で囲んでいることに注意。 なお、イメージファイル本体は予め適当な形式(GIF、JPEG、PNP、TIFF など)で作成して、サーバーに載せておかなけれ ばならない。 Img タグを簡単に試してみる目的で、手書きの絵をイメージファイルとして作成して、ホームページに表示してみるのも面 白いかもしれない。具体的には、 ・ Windows のアクセサリの中にあるペイントプログラム(「スタート」⇒「すべてのプ ログラム」⇒「アクセサリ」⇒「ペイント」) を使って、手書きの絵を描く。 描き終わった後で保存する時に GIF、JPEG、 PNG、TIFF などの形式で保存する (「ファイル」⇒「名前を付けて保存」で、「ファイルの種類」欄で JPEG や PNG を選ぶ)。保存場所(フォルダ)は HTML ファイルと同じフォルダにする。 ・ 前に作った HTML ファイルの中に<img>タグを追加する。src=のところは、今描 いた絵の保存したファイル名を使う。 (4) 表(テーブル) 表を書きたい時がある。罫線の入った表だけでなく、単に縦の位置をそろえたい時に罫線を入れない表を使うこともでき る。 CGIプロジェクト2 5 表は右のように書く。 1行の単位を<tr>...</tr>で囲み、その中に1項目(1カラム)ずつ <td>...</td>で囲んで書く。このサンプルは右端の図のようになる。 罫線(枠)をつけるには、<table border=”1”>のように指定する。”1”は線 幅で、数字が大きくなると太くなる。左側のサンプルは枠なし、右図は枠 幅「1」の例である。 また、項目のところにイメージを入れることも可能である。 <TABLE> <TBODY> <TR> <TD>1行目の1項目目</TD> <TD>1行目の2項目目</TD> </TR> <TR> <TD>2行目の1項目目</TD> <TD>2行目の2項目目</TD> </TR> </TBODY> </TABLE> 枠なしの場合 枠=1の場合 (4) ハイパーリンク Web ページは、文字列や絵をクリックすると別のページにジャンプで きる「ハイパーリンク」を使うことができる。これは <a href=”…(URL)…”>標的文字列</a> <p>それでは<a href”nextpage.html”>ここ </a>をクリックしてください のように書く。但し、”…(URL)…”の部分はジャンプ先のページの URL を書いておく。標的文字列(もしくはイメージ)はこのページに表示される文字列(もしくは絵)であり、ここをクリックす るとジャンプするようになる。 ⇒ 上記のサンプルを表示 クリックした後のジャンプ先 [課題2-A] HTML を使って自分のオリジナルページを作れ。 但し時間がないので、余り凝らないこと。 第1回目の時間内にとどめ、それ以上のことは後半のプロジェクトに入ってか ら別途行うこと。 このサーバーは世界中からアクセスできるので、家からでも見られる。つまり、誰が見るか分からないので、 (1) 自分が公開したくない情報・しないほうがよい情報は載せてはいけない。実名・電話や住所などは載せないこと。 公開は自分の責任で行うこと。公開することによる危険を十分理解すること。 自ら公開した情報によって被害を受けた場合、大学は補償できない。 (2) 内容は、法と公序良俗に従うこと。他人の著作権を侵害しないこと。法を遵守すること。いずれも各自の責任とする CGIプロジェクト2 6 第3章 フォームによる入力 [1] フォームとは 「フォーム(form)」とは、本来の意味は(記入の出来る)書類のことで、XXX(申請)用紙 (Application Form) といったイメ ージで使われる。 ホームページの世界では、ユーザが端末で入力した情報を、サーバーが読み取るための仕掛けとして使われる。たとえ ば、会員登録をする画面、インターネッ トショッピングをする画面(商品を注文したり、配送先を指定したり、支払いのた めのクレジットカード番号を入力したりする画面)などとしてよく見かける。 また、検索のための入力画面もこの形で実現 される。 その他にも、Web によるテスト(WBT=Web-Based Testing)、つまりサーバーが問題を出してユーザが解答し、 サーバーが採点する、といった使い方もある。 フォームを使って入力をするためには、 1)フォームタグを使って、入力が出来るように記入場所を用意した画面をサーバーが準備して、端末に送り表示させる、 2)そのフォームに対して、ユーザが端末で情報を入力し、送信ボタンでサーバーに送り返し、サーバーはその情報を受 け取って、あらかじめ決めた処理を行う、 という2ステップの動作が必要になる。その仕組を簡単に説明する。 《入力画面の表示》 まず、入力用の穴の開いた画面を表示させ る。具体的には Web サーバーが、普通のペ ージ(普通の静的なページ)と同様に、HTML で書かれたページを送出し、端末はそれを受 け取って解釈して表示する。 ただし、送られるページデータに、入力用の 欄 を 表 示 す る た め の HTML コ マ ン ド <FORM> タグとその関連タグが書かれてい る点が異なる。端末は、この <FORM>タグと その関連タグが書かれていると、 1) 入力欄を作って表示すると同時に、 2) その欄に対する識別名を与える。 前者の入力欄には、単純なテキス ト欄だけでなく、選択肢を選べる 欄や(プルダウン)メニュー型の欄などを作れるタグが用意されてい る。後で具体的な例を通じてもう少し詳しく見ることにする。 後者の識別名は、入力をサーバーに伝える時に、たくさんの入力欄 があるとそれぞれを区別する必要があるので、区別するために識 別名を与える。たとえば入力画面にユーザIDとパスワードの2つの 欄があるとき、サーバー側へ渡された入力のデータの上で、それら を区別する必要があることは、容易に想像できるだろう。 また、入力タグの中に、「送信ボタン」タイプを指定することができ、 この場合は画面上に送信ボタンが作られる。ユーザは、端末画面 上に表示された入力画面で、必要な欄にデータを入力し、最後に CGIプロジェクト3 1 「送信ボタン」をクリックする。このクリックした時点で初めて、入力データはサーバーに送信される。それ以前では、端末 上で入力データを扱っているだけであり、サーバーは関知していない。 「送信ボタン」の形や文字はある程度自由に作ることができる。たとえば「送信」とか「了解」とか「終了」といったラベルを 貼っておく。 複数の入力欄がある場合にそれらを区別しなければならないので、各々の入力欄につけた名前(識別名)とキーインされ た入力データをペア(対)にして、サーバーに送る。 サーバーは、端末から送られてきたデータを読み取る。送られてき Web たデータはプログラムで処理することになる。たとえばユーザ登録 ブラウザ の画面なら登録データをデータベースに書き込んで登録するとか、 ショッピング画面ならそのデータを元にして在庫から荷物の発送へ 回すと同時にクレジットカードから代金の引き落とし処理をする、な Web 入力 どが考えられる。そのためには、送られてきたデータをプログラムで 読める形にして渡す仕組が準備されている。これを CGI (Common Gateway Interface)と呼んでいる。 サーバ CGI アプリ ケーション プログラム サーバー側でこのデータの処理プログラム(図中で「アプリケーショ ンプログラム」と書いたもの)を準備する人は、CGI を介して入力を受け取るプログラムを作ることになる。このときのプロ グラミング言語は本来なんであってもよいはずのもので、現にいくつかのプログラミング言語が使われている。よく使われ ているのは Perl や Ruby、PHP、Java などの言語で、いずれもインタプリタ式で実行される言語である(注: CGI アプリケ ーションを書くためには必ずインタープリタ式でなければならないということではない。たとえばコンパイラ式の C 言語など でも作ることが出来るのだが、あまり使われているのを見たことがない)。またいずれも C 言語と似た構文(文の書き方の 規則)をもっていること(注: 最近の言語はまあ大体似たような構文を持っている)、文字列の処理などが得意(C言語で は苦手、CGI アプリケーションでは文字列処理が必要なので、文字列処理が簡単だとプログラムが楽になる)なものであ る。今回使うのは PHP と呼ばれる言語である。要するに端末から送られてきた入力データが決められた形式でプログラ ムの入力に渡されるので、それを解読して必要な処理ができるプログラムが作れればよいのである。 CGI を使うアプリケーションプログラムは、もちろんカスタムメードで作ることが出来るが、一方で既に出来ているプログラ ムが提供されることもある。ショッピングやユーザ登録の仕組は、たいていカスタムメードで作られているだろう。また典型 的な(つまり、そのままの形で導入したいユーザが多い)CGI アプリケーションプログラムは、(有料の)製品として提供さ れているものもあるし、またフリーソフトとしてネットに公開されているものもある。典型的な例としては、掲示板システム (BBS=Bulletin Board System)やそれを日記として扱う WebLog(ブログ)、メールを Web 上で読んだり書いたりする Web メール(キャンパスで提供されている Active Mail や Deep Mail などは有料のパッケージだが)などのソフトが出回っている。 たとえば Vector のサイト http://www.vector.co.jp や窓の杜 http://www.forest.impress.co.jp などを覗くとこの種のソフ トを見つけることが出来る。 このプロジェクトの前半で扱うのは、掲示板や Web メールのうちで、画面とやり取りする基礎部分に限定しよう。細かい画 面デザインや入力情報の選択と、掲示板なりメールなりがどう動作するかのアプリケーション機能とを組み合わせれば、 完結したシステムになるはずである。前半では入力画面の出し方と、アプリケーションでの入力データの受け取り方に限 定する。なお、アプリケーション部分は、その機能に関する固有の知識が必要になるので、それは各自で勉強して欲しい。 (個別に質問してくれれば、ある程度は答えられるだろう。) ここまでで分かったことを整理すると、 1. 入力の仕組は 1) <FORM>を使った(入力欄を含む)ページを準備して、それを普通のページと同様に表示する、 CGIプロジェクト3 2 2) 端末で入力欄にキーインした情報は 送信ボタンを押すと、まとめてサーバーに送られる、 3) サーバーでは送られてきた入力データを CGI インターフェースを経由してアプリケーションプログラムに 渡す、アプリケーションプログラムは、所定の手続きで入力の情報を受け取る といった手順で行われる。 2. 入力データは、サーバー上に用意した CGI アプリケーションプログラムで受け取ることができるので、それを使っ て、たとえばデータベースへのユーザの登録なり、クレジットカードからの引き落としなりという、アプリケーション 処理をすることが出来る。 CGI アプリケーションプログラムは Perl, Ruby, Java, PHP やそのほかの言語で書くことができ、端末からの入力 データを受け取って、それを処理する。 プロジェクト前半でやることは、このような CGI アプリケーションプログラ ムの簡単なものを書いてみて、プロジェクト後半で本格的な仕組を作るための前提知識を得ることである。 [2] フォームの書き方の例 まずはサンプルから見てみることにしよう。 <FORM action="inputaction.php" method="post"> <P>学生番号 <INPUT type="text" name="student_id"></P> <P>氏名 <INPUT type="text" name="name"></P> <P><INPUT type="submit" name="exec" value="送信"></P> </FORM> これを、ページの一部として作る。つまり、この前に<HTML><BODY>があって、この後に</BODY></HTML>を置く ( <HEAD>…</HEAD>部分は必要なものを自分で書くこと )。 この中で、<P>タグ (パラグラフタグ、パラグラフの先頭を示す) は既に知っているとする。その他の<FORM>タグ, <INPUT>タグは初めてなので、説明を要するだろう。 表示 <FORM action="inputaction.php" method="post"> <P>学生番号 <INPUT type="text" name="student_id"></P> <P>氏名 <INPUT type="text" name="name"></P> <P><INPUT type="submit" name="exec" value="送信"></P> </FORM> inputaction.php クリック 学生番号と氏名を受け取って それを処理するアプリケーション プログラム <FORM>タグは、ここからフォーム(記入用紙)が始まるという意味で、</FORM>で閉じられる。<FORM>タグの中に、引数 として、action=と method=が書かれている。 action はこのフォームを端末からサーバーへ送信した時(それはユーザが 送信ボタンをクリックして送るのだが)、サーバー側の後ろでフォームから入力データを受け取って動作するプログラム(こ れをアクションスクリプトと呼ぶことがある)の名前(そのプログラムが置かれているファイル名または URL)を書く。ここで は inputaction.php という名前のファイルに書かれたプログラムが実行される、と指定している。 (注) action には本来は URL つまり http://foo.bar.toho-u.ac.jp/xyz/abc.php のような形を書くように規定さ れているが、相対パス表現も許されるので、同じディレクトリにあるプログラムファイルを指定する場合はそのファイ ル名だけを書いてよい。また相対パスを用いて、たとえば../cgi/abc.php のように「自分の1つ上(..)の下の cgi の下の abc.php」を指定することもある。規定に従えば、フルの URL を書いていいのだが、他のサーバーのプログ ラムを呼び出せるのだろうか?試したことがない。 実行するプログラムのファイルは、大抵の場合は Perl、PHP、Java などのプログラムだろう。ここでは、拡張子が php なの CGIプロジェクト3 3 で、PHP のプログラムが実行されることになる。 (注)Web サーバーの指定で、拡張子 php のファイルは PHP のインター プリタが起動されるようにしてある。 method 引数は、FORM のデータを端末からサーバーへ送る時の「送り方」の指定で、選択肢は POST と GET の2種類が あるが、このプロジェクトの目的では POST しか使わない。 GET を使う場合については、下記に公式な解説があるので 参考にして欲しい。ここでは一切サボることにする。 http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.2 次に<INPUT>タグが3回使われている。<INPUT>タグにはいろいろなタイプがあって、type パラメータで指定する。たとえ ば、最初の<INPUT>タグは、type="text"と指定しているが、これはテキスト型の入力欄を作る(表示する)ということであ る。type には • text • textarea 複数行にまたがるテキスト入力欄を表示 • password テキスト入力だが画面には入力文字を表示せず*などで隠すような入力欄を表示 • checkbox チェックボックスを表示(チェックボックスは1つだけ選択) • radio ラジオボタンを表示(ラジオボタンはいくつ選択してもよい) • (プッシュ)ボタン類 テキスト入力欄(1行のみ)を表示 submit ボタン(送信ボタン)、reset ボタン(入力リセットボタン)、image ボタン(イメージボタ ン)など などがある。ここの例では text という指定なので、1行のみのテキスト入力欄を作る。複数行必要なら textarea にしなけれ ばならない。 次のパラメタ name="student_id" は、この入力欄を(他の入力欄と)区別するためにつける名前である。CGI プログラム からアクセスする時は、複数の欄の入力が一度に入力として入ってくる。それを区別するために、識別名 student_id という のをつけたのである。この名前はプログラマの好きなものを選んで構わない。 たとえば、次の行の <input>タグは、タイ プは同じ text であるが、識別名は name="name" となっている。CGI プログラムから見ると、識別名 name として入ってく るデータが、画面上の「氏名」と書いたところの入力欄の値になる。 最後に、同じ<INPUT>タグですが type="submit" としたタグが書かれている。これは「送信ボタン」を表示する。submit 型 は、これを含む<FORM>…< /FORM>に含まれるすべての入力データを、端末から送出する。このタグのパラメタ name は、 もし submit のタグが複数あれば(つまり2つ以上の送信ボタンがあれば)、どちらを押されたかを区別するために使うこと が出来る(あまり必要ないかもしれないが)。次のパラメタ value は、画面上に表示されるボタンの上に貼り付けられる文 字列を指定する。この場合は「送信」と書かれたボタンが表示される。 なお、value パラメタは、他の INPUT タグ、たとえば TEXT などでは、value で指定した文字列が、枠内に初期値の形で表 示される。そのまま送信ボタンを押せば初期値が送出されるし、端末上で値を書き換えれば書き換えた値が送出される。 [3] いろいろなフォーム これをまねすれば、いろいろなフォームを書くことが出来る。次の例を見て欲しい。 <FORM action="inputaction.php" method="post"> <TABLE> <TR> <TD>学生番号</TD> <TD><input type="text" name="student_id"></TD> </TR> <TR> <TD>氏名</TD> CGIプロジェクト3 4 <TD><input type="text" name="name"></TD> </TR> </TABLE> <P> <input type="submit" name="exec" value="送信"> </P> </FORM> 前の例と殆ど同じだが、フォームの中に<TABLE>タグを使っており、フォームの内容を「表」にしたため、1行目と2行目の 入力欄の位置が揃っている。一般に、フォームの内容はどのような形でもよく、<P>を使ってパラグラフにしようと、<UL>や <OL>を使って箇条書きにしようと、この例の様に表を使おうと、構わない。 なお、参考資料として、HTML 言語の公式の定義をしている http://www.w3.org/TR/html4/ がもっともオフィシャルなペ ージなので参考にするとよい。英語をいとわずに読む努力をすること。FORM などを含めて難しめの内容に関する解説ペ ージとして面白いと思っているものとして、http://www.cs.tut.fi/~jkorpela/forms/ を挙げておく。 Google などでたとえば「HTML フォーム タグ」ぐらいをキーワードに検索してみると、日本語のお手軽な解説ページがた くさん出てくるだろう。これらは上記の w3.org 公式ページと異なり、正確さは下がるだろう。 [例題演習 3-1] 簡単なフォームを含むホームページを作り、アップして、どのように見えるか試してみよう。 上記の例を参考にして、簡単なフォームを含むホームページを作り、アップして、どのように見えるか試してみよ。試すの は、 (a)テキスト、(b)テキストエリア、(c)パスワード、(d)チェックボックス、(e)ラジオボタン、及び (f)送信ボタン をやってみ ること。アップする場所は、たとえば(自ホーム)/public_html/の下に適当なファイル名(たとえば testform.html など)を付 けて保存し、ブラウザで URL http://pegasus.is.sci.toho-u.ac.jp/~自ユーザID/testform.html をアクセスして試せ。 書き方は以下の例を参照。 <P>氏名<INPUT size="20" type="text" name="yourname" value="山田太郎" maxlength="30"></P> <P><TEXTAREA rows="3" cols="20" name="freecomment">自由にコメントを書き込んでください</TEXTAREA></P> <P>パスワード<INPUT size="20" type="password" name="yourpassword" maxlength="15"></P> <P>好きな果物 <INPUT type="checkbox" name="fruit1" value="apple">りんご <INPUT type="checkbox" name="fruit2" value="orange">オレンジ <INPUT type="checkbox" name="fruit3" value="banana">バナナ </P> <P>動物がすき? <INPUT type="radio" name="animal" value="yes">はい <INPUT type="radio" name="animal" value="no">いいえ <INPUT type="radio" name="animal" value="neither">どちらでもない </P> <P><INPUT type="submit" name="send" value="送信"></P> 1行目はテキストの例。size は欄の大きさ、name は入力欄を識別するための名前、value は初期値(どう現れるか確かめ てみよ)、maxlength はここに書き込むことの出来る最大の文字数で、欄の大きさ size より大きく出来る。 (注) 一般に、maxlength は指定しておくのがよい。理由は、受け取る CGI アプリケーションプログラムの側で、入力 用に用意するバッファが足りなくてあふれてしまうことを防ぐためである。このバッファがあふれると、(場合によって) あふれた部分が悪さをして、CGI アプリケーションを壊したり、最悪時には悪いプログラムを意図的に書き込まれたり CGIプロジェクト3 5 する可能性がある。これは攻撃に対する脆弱性(この場合はバッファオーバーフローの脆弱性)を提供する可能性が あるということで、実際に何かのトラブルが起こらない場合でも、なるべくあらかじめ避けておくのが望ましい。という わけで、実際に使う程度の文字数を maxlength として指定しておくのがよいだろう。 2行目はテキストエリアの例で、rows は欄の行数、cols は欄の長さを指定する。INPUT タグではないので注意。name は 入力欄の識別。初期値は value ではなくて、この例のように書くので注意。 3行目はパスワードの例。テキストと同じ形だが、ユーザが書き込んだ時に文字を隠してくれる。試してみよ。 4~6行目はラジオボタンの例である。ラジオボタンはクリックして選択できるタイプの入力で、同時に複数のものを選ぶこ とができる(選択肢で複数選択可)。 name は入力欄を識別する名前だが、4行目だけでなく5,6行目も同じ識別名を使 っていることに注意。これによって、4・5・6行目は同じ選択群であることがわかる。 value はそのボタンにチェックを入れ たときに入力として戻ってくる値。この例では、ユーザがりんごにチェックを入れると、apple という値が戻ってくるようにして ある。 もう1つ、「好きな果物」というテキストは INPUT のタグの外側に置かれている。つまり選択群の範囲外である。 FORM の要素はこのように普通のテキストやイメージと混ざって使うことが出来る。 7~11行目はチェックボックスの例である。チェックボックスは、選択肢だが、ラジオボタンと違って唯一選択を強制される。 つまりどれか1つをクリックすると、もし他のものにチェックをしていてもそれが消されて、新たにチェックしたものだけが残 る。8~10行目にチェックボックスを書くための INPUT タグがある。name は入力欄の識別で、 8~10行目に共通の名前 にしているのは、ラジオボタンと同じである。value はこのボックスにチェックをしたときに入力として戻ってくる値で、yes か no か neither の3つの値のうちの1つが戻ってくるようにしてある。 12行目は送信ボタンの例で、引数は前に説明した。 この送信ボタンをクリックすると、このフォームのすべての入力の値が(まとめて)端末からサーバーに送られる。その結 果、サーバーのプログラムから見ると、yourname には名前が、yourpassword にはパスワードが、fruits には好きな果物の 選択値が、同時に戻ってくるはずである。 戻ってくる値を取り扱うためには、「CGI プログラム」を作らなければならないが、それは次の節で説明する。ここは、とに かく HTML 上でフォームを 書いてみて、どのように見えるかだけを試してみよ。 ⇒ つまり「送信」ボタンを押しても、(フ ォームページだけでは)何も起こらない。 CGIプロジェクト3 6 第4章 言語 PHP [1] PHP とは 言語 PHP (正式には PHP HyperText Processor)は、CGI を実装する言語としては比較的単純で、かつCや Java 言語を 学んだものにとってあまり違和感なく使える言語である。 もちろん、CGI には他の言語、たとえば Perl や Java が使われ ているケースも多いだろう。これらの言語との使われ方の違いを理 解すれば、容易に別の言語も使えるだろう。 PHP の特徴は 1. HTML 文書のテキストと、CGI プログラムとが、同じファイルに書 かれる。 Perl などの他の言語では、CGI プログラムは HTML テキストとは 別ファイルに置かれる。<FORM>タグの action 引数によって、起 動したい CGI プログラムのファイルを指定する。しかも通常は HTML 文書の置かれる場所とは異なるディレクトリにおく。 PHP は、同じ場所に、つまり HTML と同じファイルの中に置く。PHP でも<FORM>タグに書かれた action 引数で起動す ることには変わりないが、その起動される PHP ファイルの中に、HTML のテキスト部分を含んで構わない。PHP のイ ンタープリタ(解釈実行するソフト)は、PHP の部分は実行プログラムとみなして実行し、HTML タグの部分は HTML と して表示する。 2. (特に Apache サーバーでは)サーバープログラム内で実行されるので起動が早い。 Perl の CGI プログラムでは、格段の仕込みをしない限りは、CGI プログラムは Web サーバーとは別のプロセスとして 立ち上がる。そのときにプロセスの生成と初期化に関わるオーバーヘッドが生じ、アクセス負荷の高いサーバーでは このオーバーヘッドが性能低下をもたらす。それに比べて PHP は、Apache サーバープロセスの一部として実行され るため、このオーバーヘッドがない。 と言われている。上記は利点として述べているが、その裏には欠点もあるわけで、1については、①HTML 文書と PHP の プログラムが混在して区別しづらい点や、②PHP のプログラムをページの一部として置いてあるためにセキュリティをか いくぐってソースを見ることが出来る、見られてしまう可能性がある、という問題がある。2については、Apache サーバー ではあらかじめ CGI アプリケーションプログラムを走らせるためのプロセスをいくつか立ち上げておき、プログラムが起動 されるときにそれを使うことによって回避しています。また Java の場合には、Apache ではなく、たとえば TomCat など全体 を Java で書いたコンテナ型のサーバーを使い、CGI プログラムはその中へ取り込んで実行するものもある。 とにかく、一般には PHP は CGI プログラムを作成するのに簡便な言語であると評価されている。 PHP のオリジナルホームページは、 http://www.php.net にある。ダウンロードキットやマニュアルなどが整備されている。 マニュアルは日本語版も用意されている。また、参考書の類もかなりの数が出版されてきており、書店でもよく見かける。 PHP にはバージョン4と5があり、オブジェクト指向化の動きが強くなっているが、このプロジェクトでは、それほど大きなサ ーバープログラムを構築することは考えていないので、オブジェクト指向にはこだわらないことにする。流通しているいくつ かのパッケージはオブジェクト指向を使っているものもある。 [2] PHP プログラムの基本 最初に、サンプルプログラムを動かしてみよう。まずは「フォーム」とは関係の無い、単純な例を試す。 [例題演習4-1] PHP プログラムの実行を試してみる 次の PHP のプログラムを、ファイル(自ホーム)/public_html/mysample1.php として作り、ブラウザからアクセスしてみよ。 このとき、必ず http://pegasus.is.sci.toho-u.ac.jp/~(自分の ID)/mysample1.php のように、pegasus のファイルと してアクセスすること。 CGIプロジェクト4 1 <html> <head> <title>PHP Test</title> </head> <body> <?php echo "<p>Hello World</p>"; ?> </body> </html> 右図のような画面が得られるはずである。 (注意) Windows 上で秀丸エディタなどを使って上記のファイルを作って、mysample1.php と名づけてセーブ したとする。そのファイルを《ブラウザを使ってどう見えるか見てください》と言ったとき、Windows 上で(ファイ ル一覧から) mysample1.php ファイルをダブルクリック すると、ブラウザが起動してファイルが見える。しか し、これは上の課題とは違います。 そのときのブラウザ内の「アドレス」の欄にどう表示されているだろうか? ファイルをダブルクリックして表示 すると、 Z:\....\mysample1.html と表示されているだろう。 上記の課題で要求しているのは、ブラウザ内の「アドレス」欄に http: //pegasusis.sci.toho-u.ac.jp/..../mysample1.php と表示された状態である。 Z:\...\mysample.html と表示されている時は、Windows 上のファイルを 直 接 そ の ま ま ブ ラ ウ ザ で 見 て い る の に 対 し 、 http: //pegasus . . . /mysample1.html と 表 示 さ れ て い る 時 は ホ ー ム ペ ー ジ サ ー バ ー pegasus.is.sci.toho-u.ac.jp から送られてきている(つまり pegasus の apache サーバーを介している)情報をブラウザで見ている。実は、PHP のプログラムは、pegasus ホームページサーバー上で解釈実行されるの で、pegasus を介さないと PHP は実行されないままの状態になる。表示 も、PHP のプログラムがそのまま(文字の列として) 表示されているは ずである(右図)。それに比べて、pegasus を経由した場合(つまり http://pegasus.../mysample.php の場 合)は、 上の図にあるように Hello World だけが表示される。これは下記の説明にある echo "Hello World" 文が実行された結果だからである。 この PHP プログラム(PHP ファイル)を読んで解釈してみよう。先頭から5行目までは、ごく普通の HTML のファイルである。 まず<html>タグがあって、次に<head>のセクションがあって、その中に<title>として「PHP Test」と書いてある。その次に <body>が始まっている。 その次からが新しい構文になる。「<?php」から始まって「?>」で終わる部分が、PHP のプログラムとなっている。言ってしま えば<?php … >という形なので、<?php ?>タグの引数が長いプログラムになっている、という形である。 この例では、PHP プログラムは「echo "....";」という1行だけである。「echo」は画面にそれ以下セミコロン(;)までの文 字列を表示するという構文である。ここでは「<p>Hello World</p>」という文字列を表示せよと言っていることになる。端末 は受け取った文字列を HTML だと思って解釈表示するので、<P>と</P>(パラグラフの開始と終了を示すタグ)は画面上 には表示されない。 PHP のブロックが終わったあとは、いつもどおりの HTML のタグで、</body></html>でボディと HTML 環境を閉じている。 CGIプロジェクト4 2 このように、PHP のファイルは、HTML の(タグを含む)文の中に、 <?php から ?> までの PHP の分を埋め込んだような 形になっている。このファイルは上から順序に解釈され、PHP 部分は PHP プログラムとして実行される。 PHP の開始のタグは、正式には<?php であるが、(サーバーの環境設定をすることによって)省略形として <? を使うこと が出来る。 [3] いろいろな PHP 構文とプログラム 最低限のプログラム例と、PHP プログラムの実行の仕方を理解できたので、次にもう少し複雑な構文を見てみることにし よう。 構文の公式な解説は PHP 言語のマニュアル http://www.php.net/manual/ja/ を見て欲しい(日本語である)。 《変数と代入》 次の例を解釈してみよ。 $xyz = 3; /* 変数$xyz に値 3 を代入する */ $enshuuritu = 3.1416; /* 変数$enshuuritu に値 3.1416 を代入する */ $toiawase = "What is this?"; /* 変数$toiawase に値"What is this?"を代入する */ いずれも、変数に値を代入する代入文である。左辺は変数の名前ですが、ルールとして$から始まる名前を使う。右辺は 代入される値(定数)で、整数だったり小数だったり文字列だったりしている。 大事なこと: 変数は宣言しない。さらに型 も気にしない。(注: 型がないわけではない。正確に言えば、PHP が実行中に自動的に型を決めて処理してくれる。詳し くはマニュアルの「型」の項を参照すること。) それぞれの行の右半分の /* ... */ はコメントです。PHP では C/C++言語と同じ形(/* ... */で囲まれたコメントと、//で始 まる1行コメント)のコメントと、UNIX シェルと同じ形のコメント(#で始まる1行コメント)を書ける。 《制御構造》 Java や C 言語と似ていて、if 文、while 文、for 文、switch 文などが使える。詳しくは PHP マニュアルの「制御構造」の項を 参照のこと。 if ($x < 0) { $abs = -$x; } else { $abs = $x; } $sum = 0; for ($i = 1; $i <= 100; $i++) { $sum = $sum + $i; } $i = 1; $sum = 0; while ($i <= 100) { $sum = $sum + $i; $i++; } 各々の文の終りにセミコロン「;」を置くのも、Java や C 言語と同じ。 CGIプロジェクト4 3 [例題演習4-2] PHP プログラムでループを試してみる 次の PHP のプログラムを、ファイル(自ホーム)/public_html/mysample2.php として作り、ブラウザからアクセスしてみよ。 このとき、必ず http://pegasus.is.sci.toho-u.ac.jp/~(自分の ID)/mysample2.php のように、pegasus のファイルと してアクセスすること。 <html> <head> <title>PHP Loop Test</title> </head> <body> <?php $sum = 0; for ($i = 1; $i <= 100; $i++) { $sum = $sum + $i; } print "<p>Sum is " . $sum . "</p>"; ?> </body> </html> (注) 出力文として、echo ではなく print を使ってみた。正確に言うと微妙に違うのだが、まあほとんど同じに使える。 ≪関数呼出しと関数宣言、return 文≫ PHP の関数の呼び出し方は、Java や C 言語同様に、関数名の後に引数を書く。たとえば関数 sin に引数 π/8 を与えて 呼び出す時は、sin(3.14/8) などとすればよい。 PHP では、関数という形でさまざまな機能を提供しており、かなり多くの関数があらかじめ用意されている。あとで使う SQL データベース の呼び出し機能も、関数の形で提供されている。このあたりも Java や C 言語の感覚と似ているかもし れない。 あらかじめ組み込まれている個々の関数の機能と呼び出し方は、マニュアルの「関数リファレンス」の項を参照すること。 たとえば、正弦関数 sin の詳細はマニュアルの「数学関数(Math)」の項に書かれている。 非常に多岐にわたる関数が提供されているので、一目では理解しづらいかもしれない。サンプルプログラムを見ながら、 便利そうな関数から試してみると良いだろう。また「こういうことができないかな」と思ったら、まず組み込み関数をチェック してみるというのもよい。 プログラム中で、自分で関数を定義したい場合(ユーザ定義関数と呼ぶ)にどうするか、について触れておく。たとえば、1 からNまでの和を求めるユーザ定義関数 sum(N) は次のような形になる。 function sum ($upperlimit) { $retval = 0; for ($i = 1; $i <= $upperlimit; $i++) { $retval = $retval + $i; } return $retval; } キーワード function の次に、定義したい関数名 sum と引数のリストを書く。関数の本体の書き方は Java や C 言語とよく 似ている。関数の戻り値は、上記の例ではプログラム中で変数$retval に既に計算されているので、それを return $retval によって戻している。 この関数を呼び出す側のプログラムは、たとえば CGIプロジェクト4 4 print "<p>Sum of 1..100 will be " . sum(100) . "</p>"; などとすればよい。print 文の引数の中で sum を呼び出した形である。 [例題演習4-3] PHP プログラムで関数を試してみる 次の PHP のプログラムを、ファイル(自ホーム)/public_html/mysample3.php として作り、ブラウザからアクセスしてみよ。 このとき、必ず http://pegasus.is.sci.toho-u.ac.jp/~(自分の ID)/mysample3.php のように、pegasus のファイルと してアクセスすること。 <html> <head> <title>PHP Loop Test</title> </head> <body> <?php function sum ($upperlimit) { $retval = 0; for ($i = 1; $i <= $upperlimit; $i++) { $retval = $retval + $i; } return $retval; } print "<p>Sum is " . sum(100) . "</p>"; ?> </body> </html> ≪演算子≫ マニュアルの「演算子」の項を見て欲しい。代数演算、論理演算、比較演算は、Java や C 言語と似たようなものである。 演算子の優先順位は、気にしておいた方がよい。 文字列に対しては、代入のほか、結合演算子「.」(ピリオド)が使える。2つの文字列を結合した結果を返す。 $mojiretu1 = "hallo"; $mojiretu2 = "world"; $mojiretu3 = $mojiretu1 . $mojiretu2 とすると、結合結果の $mojiretu3 は、「halloworld」となる。この時あいだに空白などが入らないことに注意。 なお、演算子「.=」は、C 言語でも見られた「+=」と同様に、 $s .= "ABC"; $s = $s . "ABC"; は と同じ という規則である。 ≪配列≫ PHP の配列は C 言語の配列とは考え方が違い、Perl 等でも用いられている「連想配列」の考え方に基づく。 配列は、(同じ型の)要素が並んでいるものだが、どの要素かを識別する方法が、Java や C 言語(や従来の Algol 系と言 われる言語全般)では(0 から始まる)番号が付いていた(添字配列)のに対して、PHP では名前をつけて識別する(連想 配列)。 図で分かるように、配列の各要素には名前 (例では apple, lemon, peach) が付けられ、配列のアクセスは Array[apple]のようにして要素を指定する。アクセスの結果は、Array[apple]の値は 25 だということになる。 CGIプロジェクト4 5 (注: 名前として先頭から 0 から始まる連番をふれば、C 言語の配列と同様に Array[0]が 25 という使い方もできるので、 その意味からは連想配列のほうが広い概念といえるかも知れない。) PHP の配列は連想配列なので、宣言の仕方もアクセスの仕方も、Java やC言語のそれとは異なっている。まず宣言は、C 言語では静的に「宣 言」し実行開始前に作られるし、Java では型の宣言部分と実体の(個数 を含めた)生成の2つのステップが必要だが、PHP の場合は実行時に (array 関数を呼び出すことによって)生成する。(型宣言は必要ない。な ぜなら、PHP では型は自動的に決められるからである。) 図のような配列を作るためには $Array = array(“apple” => 25, “lemon”=>12, “peach”=>89); とすることになる。また、 $arr = array("foo" => "bar", 12 => true); echo $arr["foo"]; // bar echo $arr[12]; // 1 この例では、配列$arr は foo という名前の要素と 12 という名前の要素の2つを持ち、foo 要素には初期値 bar を、12 要素 には初期値 true をもつものとして作られる。従って、echo 文で$arr["foo"]を読み出せば値 bar が、$arr[12]を読み出せば 値 true (=1)が読み出せることになる。 なお、配列の要素は任意の型であって構わない。従って、配列の配列を作ることが出来る。 初期値の書き方として次のようなものを許される。 $arr = array(3 => 15, 17, 19, 21) これは、 $arr = array(3 => 15, 4 => 17, 5 => 19, 6 => 21) と同じと見なす。更に開始添字(3=>)をも省略すると 0 からを仮定される。つまり $arr = array(15, 17, 19, 21) は、 $arr = array(0 => 15, 1 => 17, 2 => 19, 3 => 21) と同じである。 配列要素へのアクセス(読み出し、書込み)は、例にあるように、角括弧を用いた表記で書く。 配列を扱える関数がある。マニュアルの「配列関数」の項を参照せよ。 [例題演習4-4] 下記のプログラムが何をするものか、解析せよ。 <html> <title>Sample Array</title> <body> <?php $N = 20; $arr = array(); for ($i=2; $i<=$N; $i++) { $arr[$i] = 1; // すべて 1 にする } for ($i=2; $i<=$N; $i++) { for ($j=2; $j<$i; $j++) { CGIプロジェクト4 6 if (($i % $j) == 0) { $arr[$i] = 0; // %演算子は、$i を$j で割った余り // 割った余りが 0 なら(割切れたなら)配列に 0 をマーク } } } for ($i=2; $i<=$N; $i++) { if ($arr[$i] == 1) { print($i); print("<br>"); // 配列で 1 が残っている所だけ$i の値を表示 } } ?> </body> </html> [例題演習4-5] 上記プログラムを試してみる 例題4-4として読み解いた PHP のプログラムを、ファイル(自ホーム)/public_html/mysample4.php として作り、ブラウザ からアクセスしてみよ。このとき、必ず http://pegasus.is.sci.toho-u.ac.jp/~(自分の ID)/mysample4.php のように、 pegasus のファイルとしてアクセスすること。 CGIプロジェクト4 7 第5章 [1] フォームと PHP プログラム PHP プログラムのデバッグ プログラムがうまく動作しない場合、原因を見つけて修正するデバッグが必要となる。PHP に限らず、一般に CGI のプロ グラムのデバッグは結構面倒になる。と いうのは、単独のプログラム(つまり CGI ではなくて普通の Java や C のプログラ ムと同じようにして)として動作させても、CGI 環境で実行される時の環境(入力を含めた環境)に依存するため、それを正 しく(=実際に CGI として実行される時と同じに)設定しなければならないわけだが、これが非常に面倒になる。 そこで、私は大抵の場合は、大きなプログラムでない限り、ホームページの環境で実行しながらデバッグしてしまう。 私流のデバッグの場合、 (A)実行している場所 プログラム上のどの文を実行しているのか、正確には「今」の状態は取り出せないので「どの文を経由して実行し て異常終了したのか」もしくは正常終了した場合でも「どの文を経由して実行したのか」を指す、 (B)変数や入力の値 プログラム上のある文を実行する前の変数の値と実行後の変数の値を表示する の2つの情報を元にしてデバッグする。 前者については、プログラムはどの言語であっても、変数や入力の値によって実行の経路が変わる。ここでいう実行の経 路とは、if による分岐がどちらを選ぶか、while などのループの終了条件がいつ成り立つか、などのことを想定している。 ループ構造もつきつめれば、if と同じような分岐によってループを脱出する仕組なので、要するに分岐点でどちらの経路 が選ばれるかに注意すればよいことになる。 しかも、分岐の経路選択は変数の値によって決まる。たとえ if 文が関数値によって分岐していたにしても、その関数の値 は結局、変数値から計算される。その変数値は、プログラム内で他の変数から計算されるか、入力値から計算されるか、 どちらかのはずである。だから、変数値と入力値を見張っていれば、if やループの分岐の経路も予想できる。 プログラムの、≪期待される動き≫と、≪上記で得た実行の経路+変数の値≫とを比較し、問題箇所の範囲を狭めて原 因を特定する、というプロセスでデバッグを進めることになる。 この(A)と(B)を実現する方法はいろいろ考えられるが、Java や C 言語で print 文を各所に挿入するのと同様、PHP でも print 文を各所に挿入して追跡することが出来る。PHP の print 文は、それが置かれた場所を実行すれば、変数値を画面 に表示することができる。つまり、表示されればその場所が実行されたことと変数の値が分かることになる。 ただし、CGI プログラムの場合は、print 文で書かれる画面とは、端末側から見るホームページの画面になる。また、print 文で書き出した文字列は、端末のブラウザで HTML として解釈されるので、HTML の文として成り立つ形にして出力しなけ ればならない。たとえば、次のようになる。 <html> <head> <title>PHP Debug Sample</title> </head> <body> <?php $now = gettimeofday(); $time = $now[sec]; $datestring = date("r", $time); print("<P>Debug Test. time: $time, datestring: $datestring. </P>\n"); ?> </body> </html> この例では、$time と$datestring の値を、print 文によって表示させている。前後に<P></P>を書いているが、これによっ て HTML の形式に合うようににしている。(実際は、<P>を省略してもうまく表示される。) CGIプロジェクト5 1 この例で使った関数 gettimeofday、関数 date については、PHP のマニュアル(http://www.php.net/manual/jp/)か ら「日付/時刻」の項を参照せよ。更に、2番目の代入文の$now[sec]は、変数$now が配列で、その[sec]要素を取り出 す構文である。配列は連想配列になっていることは、前章で説明した。 [例題演習5-1] 実行途中の変数の値を print してみる。 上記のプログラムを実際に実行してみよ。ここにあるだけでなく、実効途中の変数の値をいろいろと表示してみよ。 [2] フォーム入力を使う PHP プログラム ここまでである程度 PHP が使えるようになったはずなので、次に、フォーム(入力画面)を受けるプログラムを作ってみよう。 前に説明したとおり、CGI による動的なページは、フォーム(<FORM>)による入力画面と、そこに action として指定された プログラムが、対になっていなければならない。フォームの HTML の書き方は3章で説明したので、ここでは入力を受けて 処理をするプログラムの書き方を見てみよう。 例題で解説する。 [例題演習5-2] フォーム入力を使う CGI プログラムを PHP 言語で書いてみる。 [前半] まず、フォームの入力画面を表示する HTML ファイルを作っておく。第3章の例題3-1で作った HTML ファイルを使うこと にする。 <HTML><BODY> <FORM action="myaction.php" method="post"> <P>氏名<INPUT size="20" type="text" name="yourname" value="山田太郎" maxlength="30"></P> <P><TEXTAREA rows="3" cols="20" name="freecomment">自由にコメントを書き込んでください </TEXTAREA></P> <P>パスワード<INPUT size="20" type="password" name="yourpassword" maxlength="15"></P> <P>好きな果物 <INPUT type="checkbox" name="fruit1" value="apple">りんご <INPUT type="checkbox" name="fruit2" value="orange">オレンジ <INPUT type="checkbox" name="fruit3" value="banana">バナナ</P> <P>動物がすき? <INPUT type="radio" name="animal" value="yes">はい <INPUT type="radio" name="animal" value="no">いいえ <INPUT type="radio" name="animal" value="neither">どちらでもない </P> <P><INPUT type="submit" name="send" value="送信"></P> </FORM> </BODY></HTML> このファイルを、(自ホーム)/public_html/ testform.html に置くこと にしよう。 [後半] 次に、このフォームで「送信」ボタンをクリックした時に起動されるプロ グラムファイル myaction.php を作る。<FORM>タグの中に action= で指定されたプログラムである。 フォームの入力を読み取るには、ここでは<FORM>タグ内の method に post を指定しているので、POST メソッドで取り込まれる。 CGIプロジェクト5 2 POST メソッドで取り込んだ入力は、(連想)配列 $_POST[入力欄の名前] に入って来る。それを PHP プログラムで読み 出すことが出来る。上記の例だと、入力欄「氏名」では、欄の名前を yourname としている(INPUT 文で name="yourname")ので、入力の取り出しは $inname = $_POST["yourname"]; のようにする。つまり、$_POST["yourname"]の中に、入力した文字列が入ってくるので、それを変数$inname に代入して いるのである。 同じ様にして、入力欄 freecomment, fruit1, fruit2, fruit3, animal を読み出す。 チェックボックスは、HTML ファイルでは <P>好きな果物 <INPUT type="checkbox" name="fruit1" value="apple">りんご <INPUT type="checkbox" name="fruit2" value="orange">オレンジ <INPUT type="checkbox" name="fruit3" value="banana">バナナ</P> のように設定してあり、各チェックボックスに異なる名前 fruit1・2・3 をつけているので、 $fruit1result = $_POST["fruit1"]; $fruit2result = $_POST["fruit2"]; $fruit3result = $_POST["fruit3"]; のように読み出す。チェックマークをつけると value で指定した値(apple, orange, banana)が戻ってくる。上記の入力例の画 面ではりんごとオレンジにチェックをしているので、fruit1 には apple が、fruit2 には orange が入ってくる。 次の行のラジオボタンは、HTML ファイルでは <P>動物がすき? <INPUT type="radio" name="animal" value="yes">はい <INPUT type="radio" name="animal" value="no">いいえ <INPUT type="radio" name="animal" value="neither">どちらでもない</P> としてあるので、名前 animal で読み出してみるとこの3種の選択のいずれか(ラジオボタンは択一)の value の値が入って きます。 $animal = $_POST["animal"]; 上記の入力例画面では「いいえ」にチェックしているので、animal の値は no が入ってくるはずである。 これらを併せた全体のプログラムは、たとえば次のようになる。このプログラムは FORM 入力から読み取ったデータを、後 ろの5行の print 文で画面に書き出すようになっている。パスワードは入力していないので、値がない(空)。 <?php $name = $_POST["yourname"]; $comment = $_POST["freecomment"]; $pass = $_POST["yourpassword"]; $fruit1result = $_POST["fruit1"]; $fruit2result = $_POST["fruit2"]; $fruit3result = $_POST["fruit3"]; $animal = $_POST["animal"]; print("<p>名前 :" . $name . "</p>\n"); print("<p>コメント:" . $comment . "</p>\n"); print("<p>パスワード:" . $pass . "</p>\n"); print("<p>どの果物:" . $fruit1result . ", " . $fruit2result . ", " . $fruit3result . "</p>\n"); print("<p>動物好き:" . $animal . "</p>\n"); ?> CGIプロジェクト5 3 この PHP プログラムを、ファイル myaction.php として、フォームを作る testform.html ファイルと同じディレクトリにおく。 そうしておいて、testform.html をブラウザから(http://pegasus.../testform.html という名前で)開くと、まず入力の画面が現 れる。入力した後に「実行」ボタンをクリックすると、myaction.php が実行されて、右上のような結果が表示されるだろう。 これを試してみて欲しい。 [3] もう1つ簡単な CGI プログラムのサンプル もう1つ、簡単なサンプルを作って試してみよう。 [例題演習5-3] 入力画面から数値Nを受け取って、1からNまでの和を求めて表示するプログラムを作る。 前の例題5-2と同じように、①最初にフォームによる入力ページを表示してその入力枠に数値 N を入力して、送信ボタ ンを押す、②それによって action で指定される PHP プログラムが実行され、その中で入力値 N を受け取って、1からNま での和を求めて、最後に表示する、という手順である。 ファイルは、フォームによる入力ページを表示する HTML ファイル(samplesum.html) と、送信ボタンを受けて action で起 動される PHP プログラムのファイル(samplesum.php)の2つのファイルからなる。 まずは自分で、それらを作ってみよ。 以下に作成した例を示す。 フォームを表示する HTML ファイルは、 <HTML> <BODY> <FORM action="samplesum.php" method="post"> <P>1から<INPUT size="10" type="text" name="max">までの総和を求めます。</P> <P><INPUT type="submit" name="send" value="計算開始"></P> </FORM> </BODY> </HTML> のように書くことが出来るだろう。その結果表示される画面は、右のように なるだろう。 また、このとき、action で呼び出される PHP プログラムの形は、 <html> <head> <title>FORM action program 2</title> </head> <body> <?php $maxval = $_POST["max"]; $sum = 0; for ($i = 1; $i<=$maxval; $i++) { $sum = $sum + $i; } print("<p>1から" . $maxval . "までの和は" . $sum . "です</p>\n"); ?> </body> </html> CGIプロジェクト5 4 のように作ればよい。 この処理の結果は、右側の画面コピーのようになる。 [5-B] 次のようなフォーム入力を使った PHP プログラムを書け。 入力画面は、タイトル(1行テキス ト)、名前(1行テキスト)、本文 (テ キストエリア)、送信ボタンとする。 action で起動される PHP プログラ ムは、タイトル、名前、作成日時、 本文を表示する。将来は (データ ベースが使えるようになったら)、こ のメッセージをデータベースに格納 すると同時に、データベース内に ある複数のメッセージを表示したい のだが、今は入力画面から読み取 った情報を表示するだけの形で作 る。 入力画面のイメージは右図のようにする。 また、(今回の)出力画面のイメージ は、右下図のようにする このようになるように、HTML と PHP でプログラムを自分で作って、実際に試してみよ。ここではサンプルは示さないので 自分で考えて作ってみよ。 作ったものを提出せよ。 CGIプロジェクト5 5 第6章 データベースの基礎知識 さて、ここからはデータベースを使ったホームページ処理を学ぶ。 まず最初に、データベースが何であるか、データベー スをどう使うのか、考えて見ることにする。 [1] データベースとは? データベースとは、同じ形(イメージとして Java 言語でのクラ ス、C言語の構造体)のデータ(Java でのインスタンス)がた くさんあるときに、それを効率よく格納し、検索する仕組(組 込みのソフトウェア)である。 例としては、学生1人のデータとして名前、生年月日、学籍 番号、住所、入学年度があるとしよう。形は、たとえば名前 は最大16文字の文字列、生年月日は年・月・日の3つの整 数、学籍番号は6文字の文字列、住所は50文字の文字列、 入学年度は整数、を含むクラス(または構造体)として考えることが出来る。このような形を持ったデータが 5000 人分ある としよう。Java やC言語のプログラミングで出てくるようなクラスや構造体の配列を定義するのは1つの方法だが、格納も 検索も効率が悪いことが多い。データの個数が非常に大きくなると(例えば1万件とか10万件とか)、検索するのに効率 の悪いやり方をしていては、とても実用に耐えなくなるだろう。かと言って、効率のよい優れたプログラムを毎回作成する のも大変である。そこで、大量の(同じ形の)データを効率よく扱える仕組として、データベースが用いられている。データ ベースは、大量のデータを扱うことを目的にして専用に設計された、共通で使える仕組(ミドルウェア)といってもよいだろ う。プログラマは、このような仕組を使うことによって、アプリケーション毎に効率向上の工夫をしなくても、効率よいアクセ スが出来るようになる。 正確には、「データベース」と「データベース管理システム(DBMS)」は区別して扱わなければならない。「データベース」 はデータの集まりそのものを指す。 「データベース管理システム」(DBMS)はデータベースを入れる入れ物(上に説明し た効率よいアクセスを実現するためのソフトウェア)を指す。つまりデータベースはDBMS上にデータを集めたものです。 たとえば、過去の気象のデータベース、農作物の生産量のデータベース、人口のデータベースなどと呼ぶことが出来る。 これらのデータ集合を、DBMSで管理すると効率がよい、ということになる。 データベースでデータ間の関連を表す必要がある。そのための表し方にはいくつかのモデル(データモデル)がある。有 名なのは「関係モデル」で、データ同士の関連を「関係」(relation)として表す。具体的には表の形式で表現される。別の モデルとしては「階層モデル」や「ネットワークモデル」が有名である。この詳細はデータベース論の講義に譲ることにし、 ここでは深く追求しないことにする。 ここでは、広く使われている「関係モ 名前 生年月日 学籍番号 住所 入学年度 デル」によるデータベースを使うこと 田中太郎 1982/9/9 00R950 船橋市三山... 2000 にする。 関係モデルでは、データを 山田一郎 1982/5/5 00R951 習志野市藤崎.. 2000 表の形式で記述する。 右図は、上 東邦花子 1983/3/3 00R952 千葉市美浜区.. 2000 記の学生のデータベースを表形式で 佐倉純一 1981/7/7 00R953 柏市... 2000 表した例で、学生1人が1行のデータ になっており、その中に名前や生年月日などの情報が横に並んでいる。 CGIプロジェクト6 1 [2] データベースをどう使うのか? データベースに対する操作は、データの挿入・削除や検索などが中心になる。関係モデルのデータベース(関係データベ ース)では、データ操作のための SQL と呼ばれる言語が標準化されており、広く使われている。SQL に従ったデータベー スを SQL データベースと呼ぶことがある。この実験では、広く使われている SQL データベースを使って、ホームページか ら登録されたデータを格納したり、ホームページから与えた条件で検索したりする。 SQL データベースにはいくつも製品がある。商用で有料のソフトでは Oracle 社のデータベース管理システムが有名なほ か、 Microsoft 社の Windows サーバー上で動く製品もある。 またフリーのソフトもいくつか出回っており、PostgreSQL や MySQL などはかなり広く使われている。いずれも、標準化された SQL 言語を介してデータにアクセスするので、どの製品 でも同じようなものですが、それぞれに拡張が成されていたり、運用管理上の手段がいろいろと提供されていたり(これは SQL 標準には含まれない)、性能や安定性にも差がある(これは同じソフトでもバージョンによって異なる)。今回の実験 では、データへのごく簡単なアクセスを、標準的な SQL の文で実現するので、おそらくほとんどの SQL データベースで利 用できるはずだと思う。その製品固有の拡張を使うと、他の製品では使えないということも起こりえる。 実際に SQL データベース(データベース管理システム DBMS)を使うには、(1) 表を作る(定義する)、(2) 表にデータを挿 入する、(3) 表を検索し欲しいデータを抽出する、(4) 必要なら表の中のデータを更新する(書き換える)、といったことを しなければならない。例で考えて見よう。上に示した学生データを管理したい場合、まず最初に表を作らなければならな い。表を定義するためには、各々の「列」(正式にはフィールドと呼ぶ)のデータの形の定義を DBMS に伝える必要がある。 たとえば、名前を書く欄は name という名前で呼ばれ、最大 16 文字の文字列データが入る、といったことである。すべての 列について定義する必要がある。この表を作るための SQL の構文として、CREATE TABLE がある。これによって1つ表 を作ることが出来ます。表には名前をつけておく。また引数として、表の列(フィールド)の名前や型を指定する。なお、表 の操作にはこの他に列(フィールド)の変更(ALTER)や表自体の削除(DROP TABLE)などがある。 次に、今作成した表にデータを挿入する。ここで言うデータの挿入は、表の上では行を1つ追加することに当たる。 表の 行のこと(たとえば学生データベースにおける山田太郎のデータ)を「レコード」と呼ぶ。 データ(行、レコード)の挿入は INSERT INTO 構文で行う。引数に、対象とする表の名前と挿入する値を与えます。1行追加する時に、すべての列の値を 与える必要はない。値を与えていない列は、値が決まっていない状態のままとなる。 表にたくさんのデータ(行、レコード)が入ると、その表を検索して特定の行(レコード)を取り出すことが必要になる。(注 意: データベースでは、行(レコード)がどういう順番で入っているか、つまり何行目に入っているかは問題にしない。そ の代わり、特定の条件に合う行(レコード)を検索して取り出そうとする。) 学生データの例で言えば、「名前が山田一郎 の学生のレコードを取り出せ」とか「学籍番号が 00R952 の学生のレコードを取り出せ」とか「生年月日が XX から YY まで の学生のレコードを取り出せ」などのように条件を指定して取り出す。 この操作を、SQL では SELECT という構文を使っ て行う。たとえば、SELECT * FROM students WHERE name='山田一郎' とすると、表 students の中から、列名(フィールド 名)name が'山田太郎'である行(レコード)を検索・抽出し、そのすべての列(フィールド)を表示せよ、という意味になる。 表の中のデータを更新したい場合は、UPDATE 構文を使う。引数で、どの表の中の、どの列(フィールド)の値を書き換え たいかを指定した後、対象となる行(レコード)を WHERE 節で指定する。 WHERE 節の書き方は検索と同じで、条件を満 たす行(レコード)を検索し、その検索で当てはまった行に対して、指定された列(フィールド)を指定された値に書き換える、 という操作をします。たとえば、山田太郎の生年月日を修正するときには、SQL の上では name が山田太郎である行を探 して、その行に対して生年月日をZZに置き換える、というような操作の仕方をする。 この他に重要な操作として、表の結合がある。例として、上記の学生の表 students の他に、もう1つ点数の表 score があ るとしよう。点数の表 score は、学生番号の列(フィールド)id と、点数の列(フィールド)ten を持っているとする。そこで、表 CGIプロジェクト6 2 students と表 score を同時に見ることを考える。たとえば「'山田一郎の点数は?」という問い(つまり名前が山田一朗であ る学生の点数は?という問い)に対して、まず表 students を引いて山田一郎の学生番号が 00R951 であることを求め、更 に表 score を引いて学生番号が 00R951 である学生の点数を求めることになる。これを1回で自動的にやってしまおうとい うのが結合である。この例では、 SELECT score.ten FROM students, score WHERE students.name='山田一郎' AND students.id=score.id のようにする。SELECT の後ろの score.ten はこの検索の出力を「表 score 内の列 ten」にせよ、と指示している。表の名前. 列の名前で書かれている。また最後の students.id=score.id は結合の条件で、表 students の id と表 score の id は同じも のとみなせということを指示している。 SQL データベースを使えるようになるためには、SQL の文と機能をひととおり学ぶ必要がある。ここではすべての機能を 詳細に説明する余裕がないので、簡単な例を試すだけにし、細かい点は自習に譲ることにする。特に、値に関わる機能 (この列の値は正でなければならない、とか、この列の値は指定していなければデフォルト値として Z をとるとか)や、行 (レコード)をユニークに識別できる「キー」としてどの列を使う(たとえば、学生番号は重複が無いのでキーに出来る)とか の機能は、細かくなるので省略するが、重要である。自分で勉強して欲しい。 さて、このような SQL の「文」が使えるとして、実際にどのように使うのだろうか? データベースのアクセスは、(1)プログラ ムからのアクセス、と(2)端末から手でコマンドを打って(インタラクティブに)アクセスする、の2つが提供されている。前者 はこれからこのプロジェクトの中で実際に使ってゆく。後者はいろいろと試してみるのに便利であるので、実際に使ってみ ることにしよう。 [3] SQL を使ってみる SQL データベースへのインタラクティブなアクセスのやり方(どうやって起動するか)は、DBMS の製品毎に異なる(標準化 の対象外)。このプロジェクトで用いる無償の製品 MySQL (ホームページ http://www.mysql.com 参照)では、DBMS が実 行されるコンピュータ(本プロジェクトでは pegasus)の文字端末の上で操作する。 (注) コンピュータ pegasus の文字端末を、手元のPC上に開くことが出来る。ネットワーク上の「遠隔端末」の機能を 用いる。Pegasus の場合、ssh と呼ぶ遠隔端末の機能が使える(telnet はセキュリティ上使ってはならない)。この ssh の機能を使える端末側のプログラムはいくつか存在し、部屋によってインストールの具合が違う。具体的には、① putty、②TeraTerm (TTSSH)、③Cygwin でコマンド ssh が使える場合、の3つがあり、いずれも同じように使える。 Putty や TeraTerm の場合、起動するとウィンドウが開き、接続先を指定する画面が出るので、 pegasus.is.sci.toho-u.ac.jp を指定し、接続モードに SSH を指定する。Cygwin の場合は、cygwin を起動した後、プロンプト(入力促進)に対して ssh pegasus.is.sci.toho-u.ac.jp のようにタイプインして Enter を打つと、SSH が起動する。但し cygwin のインストール状況によっては「ssh が無い」と 言われる場合がある。 いずれの端末プログラムでも、一番最初に pegasus に接続したときに、接続してよいかどうか尋ねられるので yes と 答える必要がある。その後は、pegasus のログインIDとパスワード(Linux のログイン ID とパスワードと同じ)を入れて、 ログインする。 話を戻して、この pegasus の文字端末の上で、ユーザコマンド mysql を次のように実行することによって起動する。 mysql -u d550???? -p (ENTER キーを押す) パラメタ -u d550???? は、mysql 上でのユーザ ID を指定する。 -p は、次の行でパスワードを入力することを指示してい る。 ここで、mysql の ID とパスワードは UNIX の ID とは別の物で、SQL DBMS の中で定義されたものである。 pegasus 上の mysql サーバーでのユーザ ID とパスワードは、独自につけたものを配布する。-p の後に Enter キーを押すと、 Enter password: CGIプロジェクト6 3 と出るので、ここでパスワードを打ち込む。このやり方をすればパスワードが画面上に表示されない。パスワードがOKで あれば、 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 3.23.54 Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> という画面が(文字端末上に)現れる。これ以降、mysql> という入力促進記号の後に、mysql のコマンドをタイプすること が出来る。 mysql のコマンドは、またいろいろとあるが、よく使うのは (1) SQL 文そのものの後ろに「;」(セミコロン)を置いたもの、 (2) use コマンド、これは「ここから use コマンドで指定したデータベースを使う」というコマンド、 (3) mysql とのやり取りを終了する quit コマンド、 の3つであろう。その他のコマンドは help;と入力するとヘルプメッセージが表示される。use コマンドをタイプインすると、 mysql> use test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed となるし、quit コマンドをタイプインすると mysql> quit Bye のような表示が出て mysql とのやり取りは終り、UNIX の入力促進記号(ここでは%記号)が表示され、UNIX コマンドを受け 付けるようになる。 use コマンドについて説明しておこう。mysql では、同じユーザ ID の下で、複数の異なるデータベースを持つことができる。 「1つのデータベース」とは、意味のある表の集まりのことで、たとえば私一人が、気温の記録のデータベースと、学生の データベースと、人口統計のデータベース、というように複数の(この場合3つの)異なるデータベースを、同じ mysql の DBMS の下に持つことができる。use コマンドは、「これから私が定義した学生のデータベースを使いますよ」という宣言に なる。学生データベースの中に複数の表、たとえば学生番号と名前と住所の表と、学生番号と成績の表と、学生番号と 出身高校の表を持つことができるが、それは1つのデータベースの中の複数の表であり、SQL の項で述べたように複数 の表を合成して利用することもある。 use コマンドで利用するデータベースを宣言したら、あとは SQL 文でデータベースをアクセスできる。次の章で実際に使っ てみる。 CGIプロジェクト6 4 第7章 MySQL を使ってみる 早速、mySQL のインタラクティブセッション(端末からコマンドを入力してデータベースを操作するやり方。 これに対して、 あとから PHP を介して使うが、この時は端末から使うのではなくて、PHP プログラムがデータベースを操作する)を使って、 DBMS を使ってみることにしよう。 [例題演習7-1] pegasus 上の UNIX にログインし、前章で説明したようにコマンド mysql を起動する。ここで使う MySQL 用のユーザ ID と パスワードは、配布したものを受け取ること。 % pegasus[yamanouc]%mysql -u yamanouc -p (ENTER キーを押す) Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 3.23.54 Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> 次の手順に沿って、mySQL データベースを使ってみる演習をせよ。ここから先の SQL 文(SQL コマンド)の意味について は、マニュアル(http://dev.mysql.com/doc/refman/4.1/ja/)を見て確かめよ。一応翻訳されている。但し一部の章は翻訳 されておらず英文のままになっている。できれば全部を英文 http://dev.mysql.com/doc/refman/4.1/en/index.html で 読めるようになって欲しい。 [1] 使うデータベースを宣言する まず、このインタラクティブなやり取りで利用するデータベースを、use コマンドで宣言する。データベースはあらかじめ DBMS 内に存在しなければならない。システム管理者が、皆さんのユーザ ID を名前とするデータベースを、あらかじめ作 ってあるとする。(場合によっては自分でデータベースを作らなければならないこともあるだろう。マニュアルで CREATE DATABASE を見よ。 pegasus 上では、学生ユーザはデータベースを作る権限を与えられていないユーザとして登録して あるので、作ることは出来ない。 use d5505999 (データベース名 d5505999 は例) use 文によって、これから使うデータベースの名前が d5505999(d5505999 は例)であると宣言する。実行結果は mysql> use d5505999 Database changed のようなメッセージが表示される。 ところで、このシステム(DBMS 全体)にどんなデータベースが登録されているか見てみたくなったら、SHOW DATABASES と いう SQL コマンドが使える。 show databases; 最後にセミコロン「;」を打ってから、Enter キーを押す。セミコロン「;」は mysql でインタラクティブにコマンドを入力する時に、 SQL 文の最後を示すために付ける区切り文字です。セミコロンを忘れると、更に次の行を入れて欲しい、というモードにな る。(下記参照) mysql> show databases -> このときは、最後の行にセミコロン「;」だけを書いて Enter を押せば、それでその行の入力が終りになる。 CGIプロジェクト7 1 気がついたかもしれないが、文中で SQL コマンドを示すのには大文字で SHOW DATABASES と書いているのに、例では小文 字で show databases と書いている。実は、これは「どちらでもよい」。マニュアルでは大文字で書いてあるが、少なくとも mySQL では、SQL コマンドに関しては区別しないことになっている。但し、その他の文字の部分、つまり表の名前やフィー ルドの名前などはきっちり区別するので、注意が必要である。 実行結果は、 mysql> show databases; +----------+ | Database | +----------+ | d5505999 | | mysql | +----------+ 2 rows in set (0.00 sec) といったメッセージが出力される。 [2] 表(テーブル)を作る 次に、自分のデータベース(d5505999)の中に、表を作って見よう。 表を作る SQL 文は、CREATE TABLE を使う。 ここでは試しに、mytest という名前の表を作ってみよう。 create table mytest ... ちょっと待って欲しい。CREATE TABLE では、その表を構成する列(フィールド)の名前と型(属性)を教えてやらなければな らない。 では例として、学生の名前と学生番号と年齢を含む表を作ってみることにしよう。 学生の名前のフィールドは「name」という名前で20字の文字列 CHAR(20)型とする。 学生番号のフィールドは「id」という名前で6文字の文字列 CHAR(7)型とする(整数型にしてもよいところだが、ここで は文字型にしておく)。 年齢のフィールドは「age」という名前の整数 INT 型とする。 型の種類は、Java やC言語などと違う点がある。どのような型があるのかは、MySQL マニュアルの6.2節を見て欲しい。 では、CREATE TABLE を実行してみよう。name は CHAR(20), id は CHAR(7), age は INT とした。 mysql> create table mytest (name CHAR(20), id CHAR(7), age INT); Query OK, 0 rows affected (0.05 sec) 次の SHOW TABLES 文は、このデータベース中にどんな表があるかの一覧を表示してくれる。今はまだ表が mytest の1つ だけである。 mysql> show tables; +------------------+ | Tables_in_5506999| +------------------+ | mytest | +------------------+ 1 row in set (0.00 sec) 次に、表 mytest がどのようなフィールドから構成されているのか、忘れてしまった時に、確認する方法を紹介しておこう。 DESCRIBE 文である。以下のように「DESCRIBE 表の名前」とすると、その表のフィールドの名前と属性(型)を表示してく CGIプロジェクト7 2 れる。Null, Key, Default, Extra の部分は、ここではあまり説明しないので、マニュアルや SQL の参考書を読んで欲しい。 mysql> describe mytest; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | name | char(20) | YES | | NULL | | | id | char(7) | YES | | NULL | | | age | int(11) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ 3 rows in set (0.01 sec) [3] 表を検索する 表 mytest が出来たので、さっそく使ってみよう。まず第1にできそうなことは、表の検索である。前にも見たが、SELECT 文 を使うと検索できる。 例えば、「表 mytest に含まれるすべてのフィールドを検索表示せよ、ただし検索条件は無しなので、 すべての行を表示せよ」という文は mysql> select * from mytest; Empty set (0.00 sec) のように書く。SELECT の*は「すべてのフィールドを選べ」という意味である。もし特定のフィールドだけを書き出したけれ ばここにフィールド名を指定する。FROM のあとの mytest は検索の対象となる表の名前である。いずれにせよ、この表は まだ何も行(レコード)を挿入していないので、どう検索しても「空」(empty)という返事が返ってきている。 [4] データ(行・レコード)を挿入する いつまでも空では仕方ないので、表 mytest にデータを挿入しよう。挿入は行(レコード)を単位にして行う。追加には INSERT 文を使う。 mysql> insert into mytest values ('tanaka ichiro','5505950','19'); Query OK, 1 row affected (0.00 sec) mysql> select * from mytest; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 19 | +---------------+--------+------+ 1 row in set (0.00 sec) INSERT INTO の後に表の名前 mytest を書き、その後に VALUES と書いたあと、括弧にくくられた1行分のデータを書く。 1行分のデータは、コンマで区切られた、順に並んだフィールド(この場合3つのフィールド、name, id, age)の値である。 個々の値は、データであることを示すために1重の引用符「'」で囲んである。 (注意: 名前のフィールドの値を漢字にし たい時は、正しい漢字のデータを正しい形で与えてやれば、mySQL 自体は漢字データでも格納できる。残念ながら、イン タラクティブモードの場合、UNIX 端末の漢字に対する特性があるので、そのままではうまく入らない。後で試すように、 PHP などのプログラムからデータを挿入する場合は、漢字でもそのままうまく入る。) 挿入した直後の表の内容を、SELECT * FROM MYTEST として表示してみているが、上のように正しく挿入されているの が分かる。 これによって、次々とデータ(レコード)を挿入してゆけば、データベースが完成する。例としてもう2つデータを挿入してみ る。そのために INSERT 文をさらに2回繰り返す。最後に表を表示してみると、レコードが3つになっていることが分かる。 mysql> insert into mytest values ('yamada taro','5505951','20'); CGIプロジェクト7 3 Query OK, 1 row affected (0.00 sec) mysql> insert into mytest values ('toho hanako','5505952','19'); Query OK, 1 row affected (0.00 sec) mysql> select * from mytest; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 19 | | yamada taro | 5505951| 20 | | toho hanako | 5505952| 19 | +---------------+--------+------+ 3 rows in set (0.00 sec) [5] 表の検索 その2 このように3つのデータが入っている表を対象にして、いろいろな条件を付けて検索をしてみよう。まず、フィールドの値が ある条件に一致するデータ(レコード=行)を選択・表示するには、SELECT 文で WHERE 節を書く。その書き方は、 mysql> select * from mytest where name='tanaka ichiro'; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 19 | +---------------+--------+------+ 1 row in set (0.01 sec) ほとんど自明と思われる。 name='tanaka ichiro'であるようなデータ(レコード)を探している。等号の右辺はデータなので、 1重引用符「'」で括ってある。条件にマッチする結果(この場合1行だけ)が表示されている。 条件を AND や OR で組み合わせることも出来る。 mysql> select * from mytest where name='tanaka ichiro' or age='20'; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 19 | | yamada taro 20 | | 5505951| +---------------+--------+------+ 2 rows in set (0.00 sec) また、値に対する条件を不等号で書くこともできる。年齢 age が 20 より大きいレコード(行)だけを表示するには mysql> select * from mytest where age>='20'; +-------------+--------+------+ | name | id | age | +-------------+--------+------+ | yamada taro | 5505951| 20 | +-------------+--------+------+ CGIプロジェクト7 4 1 row in set (0.00 sec) 次は、検索結果の表示をソートすることを試す。表示をソートするには、ORDER BY 構文を使う。name をキーにしてソート したい場合、 mysql> select * from mytest order by name; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 19 | | toho hanako | 5505952| 19 | | yamada taro | 5505951| 20 | +---------------+--------+------+ 3 rows in set (0.00 sec) 名前は文字列なので、文字列としてのソートをしている。アルファベット順になる。2行目と3行目の順番がひっくり返った のがわかると思う。(注: 漢字データのソートは厄介な問題で、ここでは触れないでおく) 最後に、一部のフィールドだけを選んで表示する例を示す。ここの例で名前 name と年齢 age のフィールドだけを表示した い場合は、SELECT のあとに対象フィールドの名前を列挙すればよい。 mysql> select name, age from mytest; +---------------+------+ | name | age | +---------------+------+ | tanaka ichiro | 19 | | yamada taro | 20 | | toho hanako | 19 | +---------------+------+ 3 rows in set (0.00 sec) [6] データの更新 既に存在する行(レコード)の、特定のフィールドの値を書き換える処理である。新しいデータが入手できた時や、以前レ コードを作った時に空白のままにしておいたフィールドに値を書き込むなどの用途があるだろう。 書込みは UPDATE 文を使う。UPDATE 文は、指定したフィールドを指定した値に書き換える。 UPDATE 表の名前 SET フィールドの名前=新しい値 のようにする。更新する行(レコード)を指定するのは、SELECT と同じ WHERE 節を使う。たとえば、tanaka ichiro の年齢を 18 に書き換えるためには、WHERE name='tanaka ichiro'として対象となるレコードを選択する。具体的には、 mysql> update mytest set age='18' where name='tanaka ichiro'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from mytest; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 5505950| 18 | | yamada taro 20 | | 5505951| CGIプロジェクト7 5 | toho hanako | 5505952| 19 | +---------------+--------+------+ 3 rows in set (0.00 sec) でできる。最後に SELECT 文で表を書き出しているが、確かに値が書き換わっていることが分かる。 UPDATE は、WHERE 節の条件が合致すれば 複数の行でも同時に書き換えられる。上記の状態から、age が 20 未満の 行(レコード)のすべてについて、ID を無理やり'8888***'に書き換えてみる。 mysql> update mytest set id='8888***' where age<'20'; Query OK, 2 rows affected (0.00 sec) Rows matched: 2 Changed: 2 Warnings: 2 mysql> select * from mytest; +---------------+--------+------+ | name | id | age | +---------------+--------+------+ | tanaka ichiro | 8888***| 18 | | yamada taro | 5505951| 20 | | toho hanako | 8888***| 19 | +---------------+--------+------+ 3 rows in set (0.01 sec) この例では age が 20 未満のレコードが2つあり、そのことが「2 rows affected」「Changed: 2」というコメントにも現れている。 念のため SELECT 文で表全体を書き出してみているが、1行目と3行目の id 部分が書き換わっていることがわかる。 [課題7-C MySQL を使ってみよう] このページで見た手順を、自分で試して見よ。少し条件を変えてあるので、それに併せてコマンドなどを書き換えよ。 東邦大学理学部の学科、学生数、就職希望者数、内定者数、未内定者数の5つを保持する表 shushoku を作れ。14年度 のデータは以下の通り(http://www.sci.toho-u.ac.jp/shoku/3jyokyo/3-1gk_zyky.html ⇒ このページは無くなった。最新 の情報は http://www.toho-u.ac.jp/way/narashino/data/scidata.html にあるが、まあ実験のためにはこの下の表にある データをそのまま使って欲しい)。 具体的には CREATE TABLE で表を作り、そこにデータを挿入せよ。 次に、この表のデータを検索せよ。 (1)biomol 学科の就職状況(レコード=行全体) を表示せよ。 (2)学生数が 100 人未満の学科の就職状況を 表示せよ。 (3)未内定者が皆無の学科の名前(学科名だ 学科 学生数 就職希望者数 内定者数 未内定者数 chem 107 62 62 0 bio 90 54 52 2 biomol 116 63 62 1 phy 90 48 47 1 info 101 75 73 2 け)を表示せよ。 (4)info 学科の学生数が間違っていたので、102 に変更せよ。 (5)WHERE 節に式を書いてしまおう。 (就職希望者数/学生数)が 0.65 より大きい学科を選んで、その就職状況を表 示せよ。 (6)未内定者数の多い順(多いほうが上)にソートして、表全体を表示せよ。(同数の場合の順序にはこだわらないこと にする) 降順にソートするには ORDER BY …DESC のように DESC (descending order)を付ける。 CGIプロジェクト7 6 第8章 PHP から MySQL を呼び出す 前章で、SQL のコマンド(正しくは「キュエリー(=問合せ)」と呼ぶ)の使い方を、端末から手で打ち込むことによって試し た。ここでは最後の問題として、手で打ち込むのではなく、PHP のプログラムから SQL キュエリーを生成してデータベース にアクセスし、その結果を受け取る方法を学ぶ。 PHP プログラムと MySQL データベースの間のインターフェースは、 ①接続 ① PHP プログラムと SQL データベースを接続する、 ② PHP プログラムから SQL データベースへ向かって SQL 文を 放る(SQL コマンドを投げる)、 PHP ③ SQL データベースから PHP プログラムへ検索結果を送り返す プログラム (PHP から見ると結果を拾い上げる)、 ④ PHP プログラムと SQL の間の接続を切断する、 ②SQL コマンド MySQL ③結果 データベース ④切断 という4つからなる。 [例題演習8-1] 次の4つの手順を含む PHP のプログラムを書き、実行してみる。 [1] SQL データベースを接続する mysql_connect PHP のプログラムが mySQL データベースを使うために、初めに接続するという作業がある。これには、mysql_connect 関数を使う。引数は、mySQL データベースのサーバーが置かれているホスト(普通は自ホストだが、リモートホストに置い た mySQL サー バーをアクセスするような設定も出来る)、mySQL 上のユーザ名、パスワードを与える。たとえば $MySQLHost = 'localhost'; $MySQLUserName = '5505999'; $MySQLPassword = 'mypassword'; $MyLink = mysql_connect($MySQLHost, $MySQLUserName, $MySQLPassword); のようにすることができる。但し、5505999 は自分の MySQL 用の ID、mypassword はそのパスワードである。 このプログラム例で分かるように、mySQL のユーザ ID とパスワードを PHP のプログラム中に書いておかなければならな い。これはもし PHP プログラムのソースコードが見られてしまうとセキュリティ上具合が悪いので、普通はここでちょっとし た一ひねりをする。上の3行(ユーザ ID などを変数に代入するところ)は別ファイル.ht_mytest に置き、それを PHP プロ グラムで取り込むようにする。つまり、表に見える PHP プログラムファイルには書かないでおく。更に Web サーバー (apache)の設定で「.ht」から始まるファイルは外へ見せない、としておくと、パスワードの値を書いたファイル.ht_mytest は外へ見えない、ということができる。PHP のメインのプログラムでは include 文を使ってファイル.ht_mytest を取り込む。 include(".ht_mytest"); $MyLink = mysql_connect($MySQLHost, $MySQLUserName, $MySQLPassword); このトリックはややこしいので、後からゆっくり考えるのでもよかろう。ただ、セキュリティ上のリスクがあることは認識して 欲しい。 (注) ファイル.ht_mytest は独立した PHP プログラムファイルなので、最初と最後に<?php と?>が必要である。 <?php $MySQLHost = 'localhost'; $MySQLUserName = '5505999'; $MySQLPassword = 'mypassword'; ?> CGIプロジェクト8 1 接続が出来たら、次にデータベースを選択する。端末から SQL コマンドをタイプインした時の use コマンドに相当する機能 に当たる。関数 mysql_select_db で選択する。第1引数はデータベースの名前、第2引数は上の mysql_connect 呼出し の戻り値を入れる。この 戻り値 $MyLink は後で SQL 呼出しをするときに常に必要になる(引数で指定する)。 $MySQLDatabase = 'd5505999'; mysql_select_db($MySQLDatabase, $MyLink); これら mysql_connect や mysql_select_db 関数についての詳細は、PHP のマニュアルの MY SQL サーバー関数の章 http://www.php.net/manual/ja/ref.mysql.php を参照して欲しい。 [2] PHP から SQL へコマンドを投げる mysql_query PHP プログラムから SQL データベースをアクセスするには、PHP のプログラムの中で、SQL のコマンド(キュエリー)をそ の通りの形で生成して、mySQL に放る。 mySQL を端末からインタラクティブモードで使った時とまったく同じ SQL 文を、 PHP プログラムで文字列として作っておき(最後のセミコロン「;」は除く)、それを関数 mysql_query の引数に与えて呼び出 す。 (注: インタラクティブモード時の行末のセミコロン「;」は、インタラクティブ時に入力の最後を示すためのもの) $Query = "SELECT * FROM mytest WHERE age='19'"; //SQL コマンドをそのとおり文字列として準備 $Result = mysql_query($Query, $MyLink); //$Query を送出し、結果を$Result に受取る これによって、mySQL データベースに SELECT 文が送られる。もしどんな SQL 文が送られているかを見たければ、print 文で表示してみるとよい。 $Query = "SELECT * FROM mytest WHERE age='19'"; print("<p>Query: " . $Query . "</p>\n"); //$Query の内容を画面に表示 $Result = mysql_query($Query, $MyLink); 関数 mysql_query についても、マニュアルの MY SQL サーバー関数の章 http://www.php.net/manual/ja/ref.mssql.php を 見て欲しい。 [3] SQL から検索結果を受け取る mysql_fetch_array など SQL コマンドには、 *データベース側に作用を及ぼすが戻り値は利用しない操作(たとえば表を作るとか、データの更新をするとか)と、 *結果を戻す操作(たとえば検索のような操作) がある。 戻り値を利用しない操作の場合は、mysql_query 文で操作のための SQL 文を放ったままでよく、特に結果を取り 出す必要はない。(つまり戻り値$Result を使う必要がない。) もちろん、操作がうまく完 了したかどうかをチェックするべきである(引数に与えた値がおかしいために操作がうまく 行かないということがありえる)が、今はサボっておく。 他方、戻り値を利用する場合、たとえば検索結果を利用したい場合は、検索の結果の量 が検索によって変わるため、取り出す関数に工夫がされている。次の例を見て欲しい。 $Query = "SELECT * FROM mytest WHERE age='19'"; $Result = mysql_query($Query, $MyLink); $count = 0; while ($Row = mysql_fetch_array($Result, MYSQL_ASSOC)) { $count = $count+1; print("<p>$count " . $Row["id"] . " " . $Row["name"] . " " . $Row["age"] . "</p>\n"); } CGIプロジェクト8 2 この例では、mysql_fetch_array という関数を、while 文を使って繰り返し呼び出しており、もしこの関数が「空」を戻せば while ループを脱出するというプログラムになっている。よく見かける、ファイルからの入力が空になるまで while で繰り返 して呼び出す、というプログラムと同じ考え方の構造である。ここでは(複数行ある)SQL 検索結果$Result を、 mysql_fetch_array 関数を用いて、1回につき1行ずつ読み出している。 読み出した1行分の結果は、$Row という変数に代入しているが、$Row 自身は実は配列で、行内の各フィールドの値を持 っている。つまり、検索結果のある1行 の、$Row["id"]は学生番号のフィールドの値を、$Row["name"]は名前のフィール ドの値を、$Row["age"]は年齢のフィールド の値を、保持している。print 文でこれらのフィールドの値を画面に表示してい る。 print 文は書きたい文字列を指定するが、ここでは文字列 . 文字列 . 文字列といった形をしている。ピリオドは文 字列同士を繋ぐ操作であることを思い出して欲しい。 は HTML で空白を表す定数である。裸の空白「 」を書いて も、HTML では空白1つにしか解釈されない。 なお、データベースは下記のように1行(1レコード)分を増やしてある。 mysql> select * from mytest; +----------------+--------+------+ | name | id | age | +----------------+--------+------+ | tanaka ichiro | 5505950| 18 | | yamada taro | 5505951| 20 | | toho hanako | 5505952| 19 | | yoshida takuro | 5505953| 19 | +----------------+--------+------+ 4 rows in set (0.00 sec) 実行結果は2行表示される(前頁の図)。 age='19'に合致する行は2つあって、それが表示 される。もし、WHERE 節を取り除いて、すべての行を表示するようにすれば、右図のように4 行表示される。 ここまでの手続きを[例題演習8-1]として自分で試してみること。 [課題8-D PHP から MySQL をアクセスしてみよう] 課題7-Cのデータに対して、PHP からのアクセスを試してみる。 課題7-Cの表 shushoku を作成する。7-Cで使った後の状態は info の学生数が 102 になっているので、元の 101 に戻 しておくこと。 次に、この表のデータを、PHP プログラムから検索してみよう。 (1)biomol 学科の就職状況(レコード=行全体)を表示せよ。 (2)学生数が 100 人未満の学科の就職状況を表示せよ。 (3)未内定者が皆無の学科の名前(学科名だけ)を表示せよ。 (4)値(就職希望者数/学生数)が 0.65 より大きい学科を選んで、その就職状況を表示せよ。 CGIプロジェクト8 3 [参考自由課題] 簡単な掲示板を作ってみよう 5章の[課題5-B]で作ったフォーム入力の掲示板 PHP プログラムと、この章で学んだデータベースアクセスとを使って、 とても簡単な掲示板を作ってみよう。最初はなるべく凝らずに、簡単な最低限のシステムから始めるのがよかろう。 まず書込みは、最初に HTML ファイルで課題5-Bのようなフォーム入力の投稿画面を用意し、表示させる。投稿画面で 「送信」をクリックすると、 action で指定された PHP ファイルが起動され、その中で$_POST[...]を使って、入力情報を取 り出します。ここまで課題5-Bと同じである。 次に、得られた投稿タイトル、投稿者氏名、投稿本文と、更にシステムの時間を取り出して投稿時間とし、これらの情報を データベースの1行(レコード)として書き込む。データベースには、あらかじめ(この掲示板システムをインストールした時 点で)これらの項目をフィールドとして持つような表を作っておくものとする。書込みの action として呼び出された PHP プロ グラムは、この表に1行(レコード)分のデータを書き込む。次々に書き込んでいくと、次々に行が増えてゆく。 データベースの表の列(フィールド)は、始めはあまり凝らないことにする。タイトルはたとえば最大40文字ぐらいの文字 列としてしまおう。名前は最大20字ぐらいの文字列でよかろう。本文は TEXT 型というのを使います。文字列型(CHAR や VARCHAR)では255文字までしか格納できないので、もう少し長くてもよい TEXT 型(65535 文字まで格納できる)にす る。TEXT 型のバリエーションもいろいろありますが、MySQL マニュアルの「各フィールド型の所要容量」の節を参照して欲 しい。 投稿時刻は、SQL にもいろいろな型があるのだが、単純な UNIX システム時刻(1970 年 1 月 1 日からの秒数)を格納する ことにしよう。これだと整数として比較して、時間の順に表示することが出来る。しかし、そのまま表示すると意味がわから ないので、表示する時に UNIX 時刻を普通の日時の表記に変換する関数 date を呼び出すことにする。5章に示した手順 $now = gettimeofday(); $time = $now[sec]; $datestring = date("r", $time); は、関数 gettimeofday()によって現在の UNIX 時刻を取り出して配列$now へ代入し、$now の秒単位の表記要素である $now [sec]を使って(UNIX 時刻の秒表記を)変数$time に格納し、最後に date 関数によって時刻$time を通常の文字表記 に変換している。変換の仕方は"r"つまり普通に使われている日時の表記を指定している。今回はユーザが時刻を指定 する機能はサボることにするので、逆向きに文字表記の日時から UNIX 秒時刻への変換は使わずに済むだろう。 これらの方法で準備したフィールドの情報を使って、SQL の INSERT INTO 文を作り、mySQL へ送りつけて格納する。 行 の挿入の操作では、mySQL からの戻り値は気にしなくてよいだろう。(失敗することもないではないが。) 次に読出しであるが、いろいろと凝ることが出来るだろうが、今回は簡単に、データベース上の投稿者が入力された名前 と一致するデータ(行=レコード)を抽出し、それを投稿時刻の順に並べて表示する、というだけにしてみよう。 これをするためには、検索に使う投稿者名を入力するための フォーム画面を表示する HTML ファイルと、そのフォームの action で起動される PHP プログラムが必要となる。 PHP プログラムの中では、「データベース内の名前のフィールドのデ ータが、フォームから$_POST[...]で得られた名前と一致するレコードを取り出せ」という SQL 文を作って、データベースに 投げる。 一致するレコードは複数ある可能性があるので、この章の前半で見たような while 文を使った方法で、複数の 検索結果レコードを1つずつ読み出して、print 文で表示させる。 検索結果を日時の順に並べて(つまりソートして)古いものから表示するには、データベース上 の投稿日時のフィールド が UNIX 時刻(=1970 年を起点とする秒数)で書かれているので、これを整数とみなして大きさの順にソートすれば、投稿 日付の順に並べられる。 SQL では ORDER BY という構文を使うと、指定したキーの昇順(もしくは降順)にソートして結果 を返してくれるので、それを while で1つずつ読み出してゆくとソートされた順に読み出せる。 なお、ソートの向きは何も指 定しないと昇順なので、降順にするためには ORDER BY "date" DESC のように DESC を指定すればよい。 動作確認には、インタラクティブ端末を使ってデータベースを読み出したり書き込んだりしながら、変化を追跡するとよい。 CGIプロジェクト8 4