「見るだけ」のWebから、「対話する」Webへ。
こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回は、PerlとApacheを使って「Hello World!」を表示させるところまで進みました。
しかし、今のままではサーバーが一方的にメッセージを表示しているだけです。
Webアプリケーションの醍醐味は、「ユーザーが入力した情報を受け取り、それに応じて違う結果を返す」という双方向のやり取り(インタラクティブ性)にあります。
先生、前回作ったCGI、友達に見せたら「ただのHTMLと何が違うの?」って言われちゃいました…。
やっぱり、検索フォームみたいに「文字を入れてボタンを押したら結果が出る」みたいなことがしたいです!
どうやったらブラウザに入力された文字をPerlで拾えるんですか?
痛いところを突かれたわね。
でも、それこそがCGIの本質よ。
今回は、HTMLの「フォーム」から送信されたデータを、Perlの「変数」に入れて処理する方法を学ぶわ。
ここを理解すれば、アンケートフォームも掲示板も作れるようになるわよ!
本記事では、プログラミング言語Perlの基礎である「3つの変数」をマスターし、HTMLフォームから送られてくるデータをサーバー側で受け取って処理するテクニックを完全解説します。
🐪 Perlサーバサイドプログラミング講座(バックナンバー)
現在地:【第2回】入力フォームを攻略せよ!GET/POSTデータの受け取りと変数入門
- 【第1回】Linuxの「最強の武器」を手にせよ!環境構築とCGIでのHello World
- 【第2回】入力フォームを攻略せよ!GET/POSTデータの受け取りと変数入門
- 【第3回】掲示板を作ろう(前編)!制御構文とファイル操作(読み書き)の基礎
- 【第4回】車輪の再発明を防ぐ!CPANモジュールの導入とCGI.pmの活用
- 【第5回】データはデータベースへ!MariaDB(MySQL)連携とDBI/DBDモジュール
- 【第6回】モダンPerlの世界へ!Webフレームワーク「Mojolicious」入門
- 【第7回】セキュリティと見た目の分離!テンプレートエンジンの利用とXSS対策
- 【第8回】実践アプリ開発!簡易ブログシステムの構築とPSGIデプロイ
第1章:Perlの「3つの変数」を完全マスター
データを受け取る前に、そのデータを入れる「箱」について知る必要があります。
Perlには、データの種類によって使い分ける3種類の変数があります。
他の言語(PHPやPython)とは異なり、Perlは変数の先頭につく記号(シジル)で種類を区別します。
これこそがPerlの最大の特徴であり、初心者が最初に混乱するポイントでもあります。
1. スカラ変数($): 1つのデータを入れる箱
数字も文字も、1つだけなら全部これに入れます。
「Scalar(単一の)」の頭文字ではなく、ドルの $ と覚えましょう。
# 宣言と代入(my を付けるのが作法) my $name = "コウ君"; my $age = 25; # 使うとき print "名前は $name です。\n";
2. 配列変数(@): 順番のあるデータの列
複数のデータを順序をつけて管理します。
「Array(配列)」の頭文字、@(アットマーク)を使います。
# 宣言と代入(カッコで囲む)
my @colors = ("red", "blue", "green");
# 全体を表示
print "@colors"; # -> red blue green
# 1つだけ取り出す(ココが重要!)
# 「配列の中の1つの要素」は「スカラ」なので、記号が $ に変わります。
print $colors[0]; # -> red
3. ハッシュ変数(%): キーと値のペア
いわゆる「連想配列」です。キー(名前)を使って値を取り出します。
キーと値がペアになっている様子を表す %(パーセント)を使います。
Web開発では、このハッシュが最も重要です。(フォームの項目名と入力値のペアを扱うため)
# 宣言と代入(カッコ内で => を使うと見やすい)
my %user = (
"name" => "田中",
"city" => "東京"
);
# 全体を表示(順番はバラバラになる)
# print %user;
# 1つだけ取り出す
# 「ハッシュの中の1つの要素」も「スカラ」なので $ になり、添字は {} を使う。
print $user{"name"}; # -> 田中
💡 覚え方:取り出すときの記号変化
Perlの変数は「全体を扱うときはその記号、中身を1つ取り出すときは $ になる」というルールがあります。
・@array 全体 → $array[0] 1個
・%hash 全体 → $hash{'key'} 1個
第2章:HTMLフォームの作成(送信側の準備)
データを受け取るには、送る側のページが必要です。
まずは簡単なHTMLファイルを作成し、/var/www/html/form.html として保存しましょう。
form.html の作成
sudo nano /var/www/html/form.html
コード内容:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Perl CGI Test</title>
</head>
<body>
<h1>アンケート</h1>
<!-- action: データを送る先のCGIファイル -->
<!-- method: 送り方(POST または GET) -->
<form action="/cgi-bin/receive.cgi" method="POST">
<p>
お名前:<br>
<input type="text" name="username">
</p>
<p>
性別:<br>
<input type="radio" name="gender" value="male"> 男性
<input type="radio" name="gender" value="female"> 女性
</p>
<p>
<input type="submit" value="送信する">
</p>
</form>
</body>
</html>
第3章:Webの基礎「GET」と「POST」の違い
フォームを作成する際、method 属性に GET か POST を指定しました。
この2つは、データの送り方が根本的に異なります。
1. GETメソッド
- 送り方: URLの後ろにデータをくっつけて送る。
例:http://example.com/search.cgi?keyword=perl&page=2 - 特徴: URLを見ればデータが分かる。ブックマークできる。
- 制限: 送れるデータ量に制限がある(約2000文字程度)。パスワードなどの機密情報は送ってはいけない(履歴に残るため)。
- Perlでの受け取り: 環境変数
$ENV{'QUERY_STRING'}に入る。
2. POSTメソッド
- 送り方: リクエストの「本文(ボディ)」に入れて送る。URLには表示されない。
- 特徴: 大量のデータ(画像など)も送れる。ブックマークしてもデータは保存されない。
- Perlでの受け取り: 標準入力(STDIN) から読み込む。データサイズは環境変数
$ENV{'CONTENT_LENGTH'}に入る。
第4章:Perlモジュールの導入 (CGI.pm)
GETとPOSTで受け取り方が違うなんて、面倒くさいですよね?
さらに、送られてくるデータは「URLエンコード(例: %E3%81%82)」されているため、これを元の文字に戻す(デコード)処理も必要です。
昔のPerlプログラマはこれを自力で書いていましたが、現代では「モジュール(便利な部品セット)」を使うのが常識です。
今回は、Web開発のデファクトスタンダードである CGI.pm モジュールを使います。
1. モジュールのインストール
AlmaLinux 9 (RHEL 9) では、Perlのコアパッケージから一部のモジュールが分離されています。CGI.pm を使うために、追加パッケージをインストールします。
sudo dnf install perl-CGI -y
これで準備完了です。
このモジュールを使えば、GETだろうがPOSTだろうが、たった1行でデータを受け取れます。
第5章:【実践】データを受け取るCGIの作成
それでは、先ほどのフォームからデータを受け取って表示する receive.cgi を作りましょう。
1. ファイル作成と権限設定
sudo nano /var/www/cgi-bin/receive.cgi
2. コードの記述
#!/usr/bin/perl
# エラーを厳しくチェックするおまじない
use strict;
use warnings;
# CGIモジュールを使う宣言
use CGI;
# CGIオブジェクトを作成(これで便利な機能が使えるようになる)
my $q = CGI->new;
# ヘッダー出力(おまじないの \n\n も自動でやってくれる)
print $q->header(-charset => 'UTF-8');
# パラメータの受け取り(name属性を指定して値を取り出す)
my $user = $q->param('username');
my $sex = $q->param('gender');
# HTMLの出力
print "<html><body>";
print "<h2>送信結果</h2>";
# 入力チェック(変数が空かどうか)
if ($user eq "") {
print "<p>名前が入力されていません!</p>";
} else {
print "<p>ようこそ、<strong>$user</strong> さん!</p>";
print "<p>性別コード: $sex</p>";
}
print "<a href='/form.html'>戻る</a>";
print "</body></html>";
3. 権限設定と動作確認
保存したら、実行権限を与えます。
sudo chmod 755 /var/www/cgi-bin/receive.cgi # SELinuxが有効な場合、以下のコマンドも必要かも(前回参照) # sudo restorecon -v /var/www/cgi-bin/receive.cgi
ブラウザで http://サーバーIP/form.html にアクセスし、入力して送信ボタンを押してみてください。
画面に入力した名前が表示されれば成功です!
第6章:制御構文「if文」と文字列比較の罠
先ほどのコードに登場した if 文について解説します。
Perlの条件分岐は、他の言語と少し違う「独特のルール」があります。
数値と比較と文字列比較の違い
Perlでは、比較するデータが「数字」なのか「文字」なのかによって、使う演算子が異なります。
これを間違えると、バグの原因になります。
| 比較内容 | 数値用 | 文字列用 | 例 |
|---|---|---|---|
| 等しい | == | eq | if ($num == 10) / if ($str eq "hoge") |
| 等しくない | != | ne | if ($num != 0) / if ($str ne "") |
| より大きい | > | gt | if ($age > 20) |
| より小さい | < | lt | if ($age < 20) |
例えば、名前(文字列)が空かどうか調べるのに if ($user == "") と書くと、Perlは文字列を無理やり数値の「0」として解釈してしまい、意図しない動きをすることがあります。
文字列には必ず eq や ne を使いましょう。
第7章:日本語文字化けとの戦い(Encodeモジュール)
「英語だと動くけど、日本語を入れると文字化けする!」
これはPerl初心者が必ず通る道です。
Perl内部では、文字列を扱う際に「UTF-8フラグ」という特殊な属性を持たせて管理するのが理想です。
外部(フォーム)から入ってきたデータは単なる「バイト列」なので、これをPerl内部形式に変換(デコード)し、出力するときにまたUTF-8バイト列に戻す(エンコード)必要があります。
文字化け対策版コード
先ほどのコードを、日本語対応させましょう。
標準モジュールの Encode を使います。
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use Encode; # 文字コード変換モジュール
# 標準出力をUTF-8で出す設定(print時に自動エンコード)
binmode STDOUT, ":utf8";
my $q = CGI->new;
# ヘッダー出力(charset指定を忘れずに)
print $q->header(-charset => 'UTF-8');
# パラメータを受け取り、Perl内部形式(utf8)にデコードする
my $user = decode('UTF-8', $q->param('username'));
my $sex = $q->param('gender');
print "<html><body>";
# 変数を表示する(binmodeしているので、自動的にUTF-8バイト列になる)
if ($user eq "") {
print "<p>名前を入力してください。</p>";
} else {
print "<p>ようこそ、$user さん!</p>";
}
print "</body></html>";
💡 ポイント:入り口でDecode、出口でEncode
Perlの文字化け対策の鉄則は「入力されたらすぐデコード(decode)、出力する直前にエンコード(encode)」です。
上記のコードでは binmode STDOUT, ":utf8"; が「出力時の自動エンコード」を担当しています。
まとめ:これで「対話」ができるようになった!
お疲れ様でした!
これで、ユーザーからの入力を受け取り、条件によって表示を変える「Webアプリケーション」の基礎が完成しました。
今回の重要ポイント:
- 変数はシジル($, @, %)で区別する。
- フォームデータの受け取りには
CGI.pmモジュールを使うと簡単。 - 文字列の比較には
eqやneを使う。 - 日本語を扱うときは
Encodeモジュールでデコードする。
しかし、今のままでは入力したデータは「表示して終わり」です。
ブラウザを閉じれば消えてしまいます。
Web掲示板のように、データをサーバーに残しておくにはどうすればいいでしょうか?
次回、第3回は「掲示板を作ろう(前編)!制御構文とファイル操作(読み書き)の基礎」です。
受け取ったデータをテキストファイルに保存(書き込み)し、それを読み込んで表示する技術を学びます。
いよいよ本格的なアプリ開発に入りますよ。お楽しみに!
▼ エンジニアとしてのキャリアを加速させる ▼
Perl環境を作るなら
「VPS」で自分専用環境
インフラ知識を年収に
「ITエンジニア転職」

コメント