PHP メニュー

オブジェクトとクラス

C++のようにPHPにも「クラス」と「オブジェクト」と言う概念があります。クラスは、変数及びこれらの変数で動作する関数を1つに集めたもののことです。とりあえず例を見てみましょう。

<?php 
class sample_class { 
    var $name = "Apple"; 
    function print_fruits ( ) { 
        print "テスト出力:" . $this -> name . "<br>\n"; 
    } 
} 
  
$obj1 = new sample_class ( ); 
$obj2 = new sample_class ( ); 
  
$obj1 -> name = "Banana"; 
  
$obj1 -> print_fruits ( ); 
$obj2 -> print_fruits ( ); 
?>
テスト出力:Apple
テスト出力:Banana

ここではまず、sample_classと言う名のクラスが定義されています。その中身というのは見ての通り$nameに"Apple"を代入し、それを出力しているだけのものです。しかし、クラスというものはこのままプログラム中で使用することができませんのでインスタンス化してやる必要があります。そこで登場するのが、newという演算子です。上の例ではnew演算子を使用しsample_classをインスタンス化したものに$obj1$obj2という名前をつけていることになります。逆に言えば、この$obj1$obj2sample_classをインスタンス化したオブジェクトということになるのです。オブジェクトはいくらでも作ることができ、それぞれに独立しています。上の例で説明すると、

$obj1 -> name = "Banana";

と言う命令で$obj1name変数を"Banana"に変更していますが、$obj2nameは"Apple"のままです。つまり、$obj1$obj2はそれぞれにprint_fruit関数とname変数を持っており、それぞれ独立していることとなります。$obj1 -> nameが一つの変数と思えば、$obj1 -> $nameで無いことも納得がいくと思います。ここで例をあげたnameのように、クラス内で定義された変数のことをプロパティと呼びます。また、クラス内で作られた関数のことをメソッドと呼びます。メソッドは上の例では、

$obj1 -> print_fruits ( );

のようにして呼び出されます。もう一つ特筆すべきは$thisでしょう。クラス定義の内部では、プログラムでアクセス可能なオブジェクト名を知ることはできません。sample_classクラスが書かれている時点では、そのオブジェクトが後で$obj1という名前となるか$obj2となるかはわからないからです。つまり、クラスの中では$obj1 -> nameのような記述は出来ないことになります。その代わりとして、クラスの中からそのクラス内の関数や変数にアクセスするために、疑似変数$thisが用意されているのです。

クラス内でクラス名と同じ名前のメソッドをコンストラクタと呼びます。コンストラクタはオブジェクトのインスタンスを作成する際に自動的に呼び出される性質を持っています。

<?php 
class sample_class { 
    var $name;
    function sample_class ( $in = "Apple" ) {
        $this -> name = $in;
    }
    function print_fruits ( ) { 
        print "テスト出力:" . $this -> name . "<br>\n"; 
    } 
} 
  
$obj1 = new sample_class ("Banana"); 
$obj2 = new sample_class ( ); 
  
$obj1 -> print_fruits ( ); 
$obj2 -> print_fruits ( ); 
?>

変数のスコープ

変数の有効範囲のことをスコープと言いますが、PHPのスコープは、最初にどこで使ったかで決まります。とは言いましても、Perlのように柔軟に解釈してくれるわけではないので注意が必要です。例えば、以下の例では、$sampはグローバル変数となり、include されたdummy.php内でも有効的に使用することができます。

<?php
    $samp = 'str';
    include "dummy.php";
?>

しかし、次の例を見てください。

<?php
    $samp = 'str';

    function print_test ( ) { 
        print $samp; 
    }

     print_test( );
?>

この場合、何も出力されません。関数内で初めて使われた $samp は関数内でのみ使えるローカル変数となっているのです。では、変数をグローバルに使いたい場合はどうするのかと言いますと、関数内で変数をグローバルとして宣言してやる必要があります。方法としては二通りありまして、関数内で使いたい変数をgrobalで宣言してやる方法と、PHPが定義する$GLOBALS配列を使用する方法です。$GLOBALSは連想配列になっていまして、キーが外部変数名、その要素が外部変数の値となっています。

<?php
    $samp = 'test';
    function print_test ( ) {
        global $samp;
        print $samp;
    }
?>


<?php
    $samp = 'test';
    function print_test ( ) {
        print $GLOBALS["samp"];
    }
?>

また、PHPには静的(static)変数と呼ばれるものもあります。これは関数やブロック内で宣言された変数で、そのブロックが終了しても値を保持しているもののことを言います。他の関数から使用できない点が、グローバル変数との大きな違いとなっています。静的変数は、自分自身を関数内で呼び出す再帰関数を作る際によく利用されます。

<?php
    function print_test ( ) {
        static $samp = 0;
        print "$samp<br>\n";
        $samp++;
    }
    print_test ( );
    print_test ( );
    print_test ( );
    print_test ( );
?>

上の例では0,1,2,3と表示されます。

GET/POST

ブラウザからの要求である「GET」と「POST」。Perlでは受け取った文字列を「&」で分割し、「=」の右と左でキーと値に代入して、しかも受け取る文字列に日本語が含まれるのであればさらに手がかかる作業が必要でした。まぁ、実際は決まり文句のような関数を使用するのでさほど手間はかからなかったのですが、PHPではこんなことに気を使う必要も無いのです。では、実際に「GET」から例を見ていきましょう。ご存知とは思いますが、ブラウザにURIを直接入力した場合「GET」要求となります。また、明示的にメソッドを指定しない場合も「GET」要求となります。PHPの世界での例を挙げますと、

<?php print "$get" ?>

という内容を、PHPが有効なサーバの適当なディレクトリに、samp.phpという名前で保存します。次に、ブラウザのアドレス欄に、http://○○/samp.php?get=Testと入力します。そうすることにより、samp.phpはブラウザ上にTestという文字列を出力するのです。ただし、「GET」で直接サーバに送信できる文字は半角英数字だけとなっています。日本語等マルチバイト文字を「GET」で送信したい場合は、HTTPエンコードをする必要があります。具体的には「urlencode()」関数や「rawurlencode()」関数を使うことによって、簡単にHTTPエンコードする事ができます。また、「POST」では日本語フィールドも自動的にHTTPエンコードされて送信されます。受け取り側はフォーム内で指定した「name」の値を変数名として受け取ります。

ただし、PHP4.2.0以降のバージョンでは、デフォルトのままで「$変数名」と言う形での外部データ取得が不可能となっています。セキュリティ強化措置ではあるらしいですが、この設定を変えてやりたい場合にはPHP設定ファイルである「php.ini」の設定を下記のように変更します。

register_globals = On

また、ISPのサーバ等でこの辺りの設定を書き換えてやることが出来ない場合には、下記のように変数名をキーとした連想配列で変数を受け取ることができます。

$_POST['変数名']
$_GET['変数名']

日付と時間

PHPでは、日数の算出に必要な「暦」を以下のものだけ用意しています。

世界協定時【UTC】
全世界で時刻を記録する際に使われる公式な時刻です。天体観測を元に定めるグリニッジ標準時とほぼ同じですが、SI単位系の1秒(セシウム133が91億9263万1770回振動する時間)を原子時計で計測して決定しています。GMTにおける1958年1月1日0時0分0秒からの経過時間を原子時計でカウントして定めた時刻である「国際原子時」に、GMTとのずれを調整するための「閏秒」を追加したものがUTCとなっています。なお、日本時間はこの世界協定時から9時間加えることで参照できます。
グリニッジ標準時【GMT】
イギリスのグリニッジ天文台での天体観測を元に決められる時刻です。昔は世界標準時刻として普及していましたが、現在では原子時計によって決定される協定世界時が主に使われています。両者はほとんど同じですが、天文を主体としたグリニッジ時は海の潮汐運動がネックとなり、地球の自転周期は年々長くなっているため、時間の経過と共にずれが生じる矛盾が指摘されています。 Windowsマシンではこのグリニッジ標準時に、ローカル時間との差分を計算して時刻を示しています。日本時間はグリニッジ標準時から、9時間加えることによって求めることができます。
UNIX 時
サーバ・コンピュータの標準的な OS である UNIXでは、1970年1月1日午前0時00分00秒からの経過秒数を基準とした時間で、UNIXでは 31536000 ( =365× 24× 60× 60 ) と表現されます。UNIX時は、プログラムとの相性がよいという長所がありますが、桁数が多く見た目に日時が全く理解できないという欠点もあります。
グレオリオ暦
ローマ教皇グレゴリオ13世が、1582年に作成した暦です。グレゴリオ暦は現在世界各国で使われている暦法で、それ以前に使用されていたユリウス暦に修正を加えた太陽暦の一種であるといわれています。 これは、ユリウス暦に 400の倍数の年は閏年を設けないという規則を追加し、400年に3日減らすことで平均年を 365.2425日としてより正確な暦が作成されました。
フランス革命暦
フランス革命の後に始まった暦で、1ヶ月を30日、1週間を10日、1日を10時間、1時間を100分として、年末に5日間の閏日を持っています。フランス革命後、ナポレオンによって廃止される 1806年まで使われた暦です。
ユダヤ暦
創生紀元年 (西暦紀元前3761年) から始まり、19で割った余りが 0、3、6、8、11、14、17 になる年を閏年とした、月の満ち欠けで計算される暦です。
ユリウス暦
ジュリアス・シーザー(ユリウス・カエサル)が紀元前46年に制定した暦で、1年を原則として 365.25日とし、4年に1度の閏年に、2月に1日を加えて 366日とすることでより正確な暦となりました。ただし、正確な太陽年は、4年に約44分の誤差があるため、後のグレゴリオ暦に取って代わることとなりました。
ユリウス日
ユリウス日とは、JJ.Scaligerが考案した月のない日付です。紀元前4713年1月1日12時から数えた日付を表わします。PHPでは、それぞれの暦を相互運用するとき、このユリウス日を必ず使うことになっています。ユリウス日の日付を参照するために関数が幾つか用意され、それに基づいて目的の日付を取得するというわけです。

また、世界各国のそれぞれの地域の時間を表すローカル時間を参照するには、getdate()関数を使いますが、この関数には 連想配列として、以下のようなインデックスが定義されています。

  • second:現在の秒
  • mimutes:現在の分
  • hours:現在の時
  • mday:現在の月次の日付
  • wday:現在の曜日番号
  • mon:現在の月
  • year:現在の年
  • yday:その年の通算日
  • weekday:現在の曜日
  • month:現在の月の文字列

これらを組み合わせ、下記の例のように使用します。

<?php
    $today = getdate();
    print("$today[year]年$today[mon]月$today[mday]日<br>\n");
?>

また、更に自由なフォーマットで日時を表現したい場合には、date()関数を使用します。date()関数では日付を参照するだけでなく、ローカル時間の時刻も合わせて参照することができます。フォーマットを定義する引数は、以下の通りです。

  • a:am または pm を定義する
  • A:AM または PM を定義する
  • d:2桁の日付を定義する
  • D:3文字の曜日 (Sun 〜 Sat) を定義する
  • F:フルスペルの英字で月を定義する
  • h:12時間単位 (00 〜 12) の時間を定義する
  • H:24時間単位 (00 〜 23) の時間を定義する
  • g:先頭に 0 をつけない12時間単位 (0 〜 12) の時間を定義する
  • G:先頭に 0 をつけない24時間単位 (0 〜 23) の時間を定義する
  • i:2桁の分 (00 〜 59) を定義する
  • j:先頭に 0 をつけない (0 〜 31)の日を定義する
  • l:フルスペルの英字で曜日を定義する
  • L:閏年では 1 を、それ以外は 0 を返す
  • n:先頭に 0 をつけない (0 〜 12) の月を定義する
  • m:2桁のの月 (01 〜 12) を定義する
  • M:3文字の月 (Jan 〜 Dec) を定義する
  • s:2桁の秒 (00 〜 59) を定義する
  • S:英文の序数を表わす接尾語 (th 〜 nd) を定義する
  • t:指定した月の日数 (28 〜 31) を定義する
  • U:UNIX時間 (1970年1月1日からの秒数) を定義する
  • w:数値で示す曜日 (0 〜 6) を定義する
  • y:西暦の下2桁を示す年を定義する
  • Y:西暦を4桁で示す年を定義する
  • z:その年の1月1日からの通算日を定義する
  • Z:タイムゾーンのオフセット秒 ( -43200 〜 43200まで)

<?php echo date("Y/m/d H:i:s") ?>

こんな感じで記述します。

セッション管理

PHP4から標準でサポートされていますセッション管理機能がどのようなものかをまずは説明します。Webページを開いた際に、データのやり取りはクライアントとサーバとで行われます。このやり取りには、HTTPプロトコルが使われるわけですが、HTTPは、1回のリクエストとレスポンスの間に、接続して通信を行い、そして切断するのです。ところが、切断されるとサーバからはクライアントの見分けがつかなくなってしまいます。クライアント1人1人を見分けるための便利な機能としてこのセッション管理機能が用意されているのです。簡単に説明しますと、各ユーザ固有のIDをクッキーや URLへの埋め込みで保存し、それを各ページでセッションIDにて共有することにより同じユーザからのアクセスかどうかということを判断する機能となっています。

セッションIDには、ランダムに生成された文字列が割り当てられます。例えば「1a564b842156ec15648916a1354678a1」のようなセッションIDが引き継がれていく訳ですが、引き継ぐためにはクッキーを利用するか、URLに埋め込むかのどちらかの方法を取ります。クッキーの場合は、「sess_1a564b842156ec15648916a1354678a1」のようなファイル名で、標準ではサーバ上の「tmp」ディレクトリに保存されます。