【Perl講座 第2回】入力フォームを攻略せよ!GET/POSTデータの受け取りと変数完全マスター

「見るだけ」の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 属性に GETPOST を指定しました。
この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」として解釈してしまい、意図しない動きをすることがあります。
文字列には必ず eqne を使いましょう。


第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 モジュールを使うと簡単。
  • 文字列の比較には eqne を使う。
  • 日本語を扱うときは Encode モジュールでデコードする。

しかし、今のままでは入力したデータは「表示して終わり」です。
ブラウザを閉じれば消えてしまいます。
Web掲示板のように、データをサーバーに残しておくにはどうすればいいでしょうか?

次回、第3回は「掲示板を作ろう(前編)!制御構文とファイル操作(読み書き)の基礎」です。
受け取ったデータをテキストファイルに保存(書き込み)し、それを読み込んで表示する技術を学びます。
いよいよ本格的なアプリ開発に入りますよ。お楽しみに!

▼ エンジニアとしてのキャリアを加速させる ▼

Perl環境を作るなら
「VPS」で自分専用環境

おすすめVPSを見る

インフラ知識を年収に
「ITエンジニア転職」

転職エージェントを見る

コメント