18. パッケージの使用方法
そろそろデータベースのレッスンに入ろうと思いますが、その前に、パッケージの
使用方法の補足を行います。
Perlでデータベースに接続するには、どうしてもデータベース接続のための
パッケージを使用しなくてはなりませんので、今回は、そういったパッケージの
中身の概要と使用方法をご紹介します。
■クラスの概念
データベース接続用のパッケージを知るためには、クラスというものの概念が
分かっていなければならないので簡単にご説明したいと思います。
クラスについての説明は、オブジェクト指向なども説明しなければならないの
ですが、これにについては、ちゃんと説明すると本1冊以上にもなるので、
ここでは簡単にご説明します。
クラスとは、一言で言うと、変数や関数を一まとまりにしたものです。
さらに、作成したクラスを継承して、新たにクラスを作り、拡張していく
ことができます。
クラスは、変数や関数を自由に持たせることができるので、例えば、出力する
関数をまとめてクラス化したり、データベースに接続するための変数や関数を
まとめてクラス化することができます。
基本的に、クラスは再利用をするために作成するもので、再利用が難しい場合は
クラス化する意味はないと言えます。クラスを作成する際には、どのような
クラスを作成すれば効率が良いかを、きちんと設計する必要があります。
クラスの作成は難しいので、このレッスンでは、簡単なクラスの作成方法と
使用方法までをご紹介します。
ただし、Perlの場合は、厳密的なクラスというのはないので、擬似的に作成する
クラスになります。
■クラスの作成
説明はこの辺にしておいて、クラスのサンプルを以下に記述します。
-----------------------------------------------------------------
package Common;
#--------------------------------------------------------
# 関数 : new
# 概要 : メンバ変数の初期値を設定
# 引数 : member_aの値
# 戻値 : インスタンス
#--------------------------------------------------------
sub new
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless($self, $class);
# メンバ変数の設定
$self->{member_a} = $_[0];
$self->{member_b} = "This is a test.";
return $self;
}
#------------------------------------------------------------------
# 関数 : print_test
# 概要 : メンバ変数の出力
# 引数 : なし
# 戻値 : なし
#------------------------------------------------------------------
sub print_test
{
my $self = shift;
if ($self->{member_a})
{
print $self->{member_b};
}
}
1;
-----------------------------------------------------------------
Perlのクラスは、少々分かりづらいのですが、細かい部分は気にせず、こういう
ものだと思ってください。
まず、コンストラクタという、クラスを初期化するための関数を書きます。
この中で、クラス内の変数を定義、初期化します。(クラスの持つ変数を
メンバ変数といいます。)
コンストラクタ名は、newでなくても構いませんが、newが一般的に使用されます。
コンストラクタ内で、クラスを使用するための準備をします。簡単に説明すると、
最初に、第1引数でクラス名が渡ってくるので、それを受け取り、次に無名の
ハッシュリファレンスを作成し、bless関数でオブジェクトとクラス名を渡します。
メンバ変数がある場合は、サンプルのようにメンバ変数を書いて初期化します。
サンプルでは、member_aという変数と、member_bという変数を作成し、member_aには
new()の第一引数を設定しています。
クラス内に関数(クラスの持つ関数をメンバ関数といいます。)を書く場合は、
サンプルのように、普通の関数を書く要領で記述できます。
print_test関数では、メンバ変数の判定、出力を行っていますが、メンバ変数や
メンバ関数を使用するには、まず、shiftと記述して第1引数のクラス名を受け取る
必要があります。
また、クラスが破棄された時に呼ばれるデストラクタというものもありますが、
省略可能ですので、ここでは省略します。
■クラスの呼び出し
さて、次に呼び出し側ですが、まずは呼び出し側のサンプルを以下に記述します。
-----------------------------------------------------------------
#! /usr/local/bin/perl
use strict;
# クラス使用の宣言
use Common;
# クラスのオブジェクト化
my $test = Common->new(1);
print "Content-type:text/html\n\n";
print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML
# member_aの出力
print $test->{member_a} . "<br>";
# print_testを呼ぶ
$test->print_test();
print << "END_OF_HTML";
</BODY>
</HTML>
END_OF_HTML
exit;
-----------------------------------------------------------------
"use パッケージ名"で呼び出しますが、クラス化したファイルは、同じディレクトリ
に置くか、Perlライブラリのディレクトリに置く必要があります。別の場所に置き
たい場合は、ライブラリをインクルードする設定する配列に、ディレクトリを追加
すればOKです。
まず、newのコンストラクタを呼び、Commonのオブジェクトを作成します。
一度オブジェクト化したら、メンバ変数やメンバ関数を呼び出すことができます。
"->"という矢印のような形式で呼び出します。
オブジェクトは、いくつも作成することができます。
また、今回ご紹介した方法以外にも、違った記述方法で表現する方法もあるよう
です。興味がある方は、いろいろとサイトなどを調べてみてください。
★今日のまとめサンプルプログラム
common.pm
-----------------------------------------------------------------
package Common;
#--------------------------------------------------------
# 関数 : new
# 概要 : メンバ変数の初期値を設定
# 引数 : member_a、member_bの値
# 戻値 : インスタンス
#--------------------------------------------------------
sub new
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless($self, $class);
# メンバ変数の設定
$self->{member_a} = $_[0];
$self->{member_b} = $_[1];
return $self;
}
#------------------------------------------------------------------
# 関数 : print_a
# 概要 : member_aの出力
# 引数 : なし
# 戻値 : なし
#------------------------------------------------------------------
sub print_a
{
my $self = shift;
print $self->{member_a};
}
#------------------------------------------------------------------
# 関数 : get_b
# 概要 : member_bの取得
# 引数 : なし
# 戻値 : member_b
#------------------------------------------------------------------
sub get_b
{
my $self = shift;
return $self->{member_b};
}
#------------------------------------------------------------------
# 関数 : set_a
# 概要 : member_aのセット
# 引数 : 設定するmember_aの値
# 戻値 : なし
#------------------------------------------------------------------
sub set_a
{
my $self = shift;
$self->{member_a} = $_[0];
}
1;
-----------------------------------------------------------------
test.cgi
-----------------------------------------------------------------
#! /usr/local/bin/perl
use strict;
use Common;
print "Content-type:text/html\n\n";
print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML
# オブジェクトの生成
my $test = Common->new("Test ", "Sample");
# メンバ変数の出力
print $test->{member_a} . $test->{member_b} . "<br>";
# member_aに新しい値を設定
$test->set_a("This is a ");
# member_aを出力
$test->print_a();
# member_bを直接変更
$test->{member_b} = "test";
# member_bを取得して出力
print $test->get_b();
print << "END_OF_HTML";
</BODY>
</HTML>
END_OF_HTML
exit;
-----------------------------------------------------------------
■解説
クラス化したパッケージファイルは、別ファイルとして保存してください。
このサンプルでは、コンストラクタのnew()でメンバ変数に値を設定し、
さらにset_aでメンバ変数の値を変更、print_aでメンバ変数member_aを出力、
get_bでメンバ変数member_bを取得しています。
それぞれのメンバ関数を確認しておいてください。
また、$test->{member_a}と書くと、直接メンバ変数に書き込んだり、取得
したりできます。
★課題
1. まとめサンプルを、以下の条件で改変してください。
(1) member_bを出力するprint_bというメンバ関数を追加してください。
(2) member_aを取得するget_aというメンバ関数を追加してください。
(3) member_cというメンバ変数を追加し、初期値に現在日時(yyyy/mm/dd hh:mm:ss)を
格納してください。
(4) member_cに値を設定するset_cというメンバ関数を追加してください。
★前回の課題の解答
1. サンプルプログラムを改良し、ファイルサイズが100キロバイトを超えたら、
エラーメッセージを表示するプログラムを作成してください。
→下のサンプルを参照してください。
2. サンプルプログラムを改良し、アップロードファイルのMIMEタイプが、
JPEG以外の形式だった場合に、エラーメッセージを表示するプログラムを作成して
ください。
→下のサンプルを参照してください。
-----------------------------------------------------------------
#! /usr/local/bin/perl
print "Content-type:text/html\n\n";
print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML
use CGI;
$query = new CGI;
# ファイル名の取得
$filename = $query->param('upload_file');
# MIMEタイプの取得
$type = $query->uploadInfo($filename)->{'Content-Type'};
# 課題2
if (index($type, 'jpeg') < 0) {
print("ファイルはJPEGファイルを指定して下さい。");
exit;
}
# ファイルの受け取り
while($bytesread = read($filename, $buffer, 2048)) {
$file .= $buffer;
# 課題1
$file_size++;
if($file_size > 50){
print("ファイルサイズが大きすぎます。100KB 以下にして下さい。");
exit;
}
}
# ファイルの保存
open(OUT, "> ./tmp.dat") or die("ファイルの保存に失敗しました。");
binmode(OUT);
print(OUT $file);
close(OUT);
print << "END_OF_HTML";
<img src="./tmp.dat"><br>
ファイル名 : $filename<br>
MIMEタイプ : $type<br>
</BODY>
</HTML>
END_OF_HTML
exit;
-----------------------------------------------------------------
■解説
ファイルサイズは、レッスン12でやったstat()関数でも取れますが、ファイル
取得時に、バイト指定でループしてますので、これを利用した方が楽です。
2048バイト = 2キロバイトですので、50回ループが回ると、100キロバイトに
なり、これ以上でエラーとすればOKです。
課題2の方は、MIMEタイプがJPEGの場合、image/jpegなどという文字列になります
ので、index()関数でjpegという文字列があるかどうかをチェックすれば良いです。
|