2025 年度 DB 技術 : PHP + RDBMS 最低限 PHP

はじめに

PHP は Web サーバ側で動作するサーバサイドスクリプトである. 動的な Web ページの作成に良く用いられている. 文法は C 言語に似ている.

PHP のエラーの確認.

ブラウザで PHP ファイルにアクセスした時にエラーが出ることがある. エラーが出た場合はログファイルを確認することが良い.

$ sudo cat /var/log/apache2/error.log

文法

以下はホームディレクトリ以下の public_html フォルダ内で実行することを想定している.

php スクリプトは基本的に以下の構造をしており,開始タグ・終了タグが必要であることに注意されたい.

<?php                      //<-- 開始タグ
  実行する内容;            //<-- 行の末尾は ; (セミコロン)
?>                         //<-- 終了タグ

Hello World

基本というべき Hello World を表示するプログラムは以下のように書ける. ファイルの拡張子は .php とする.

$ vi test1.php

   <?php                      //<-- 開始タグ
     print "Hello World!";    //<-- 行の末尾は ; (セミコロン)
   ?>                         //<-- 終了タグ

このファイルをブラウザで表示させると,"Hello World!" が表示されるであろう.

変数

PHP では変数には接頭詞 $ を付けることになっている. 大文字と小文字は区別される.

PHP は C 言語と違い,変数の型を宣言する必要は無い. 代入される中身から自動的に型を決めてくれる. 以下に代表的なデータ型を挙げる.

整数   → integer
実数   →float, double
文字列 → string
論理値 → boolean
配列   → array

文字列は ' (シングルクォーテーション) もしくは, " (ダブルクォーテーション) で囲む. 以下のような変数に代入する場合には,シングルクォーテーションでもダブルクォーテーションでも, どちらを使っても問題ない.

$ vi test2.php

   <?php
     $a = "ようこそ";  //<-- ダブルクォーテーションで囲む
     print $a;
     $b = '松江へ';    //<--  シングルクォーテーションで囲む
     print $a.$b;      //<-- . (ドット)で文字列連結       
   ?> 

一方で,以下のような例では,シングルクォーテーションで囲むかダブルクォーテーションで 囲むかで出力が変化する. ダブルクォーテーション内の変数や改行コードは展開されるが, シングルクォーテーション内の変数や改行コードは展開されないでそのまま表示される.

$ vi test3.php

   <?php
     $a = "ようこそ";
     print "$a";
     $b = "松江へ";
     print '$b';    // <-- . (ドット)で文字列連結       
   ?> 

関数

PHP には C 言語のように「関数」がある.特に有名な関数は phpinfo だと思われるが, この関数を使うと PHP の環境情報が表示される.

$ vi test4.php

   <?php
     phpinfo();
   ?> 

他にも日付を表す date 関数などあり,以下のように書けば今日の日付が表示される.

$ vi test5.php

   <?php
     print "今日は".date("Y")."年".date("m")."月".date("j")."日 です";
   ?> 

getenv コマンドを使うとアクセスしてきたクライアントの情報を表示することができる.

$ vi test6.php

   <?php
     print getenv("REMOTE_ADDR");         //<-- クライアントの IP
     print getenv("HTTP_USER_AGENT");     //<-- クライアントのブラウザ情報        
   ?> 

繰り返し処理

for 文,while 文,do-while 文が使える

for 文の構造は以下の通りである.

for (初期値; 繰り返しの条件; 変化){
   繰り返し実行する処理;
}

具体的には以下のように書ける

$ vi test7.php

   <?php
      for ($i=1; $i < 15; $i++){
        print "*";
      }
   ?>

while 文の構造は以下の通りである.

while (繰り返しの条件){
   繰り返し実行する処理;
}

具体的には以下のように書ける

$ vi test8.php

   <?php
      $i = 1;
      while ($i < 15){
        print "+";
        $i++;
      }
   ?>

do-while 文の構造は以下の通りである.

do{
  繰り返し実行する処理;
} while (繰り返しの条件)

具体的には以下のように書ける

$ vi test8.php

   <?php
      $i = 1;
      do {
        print "x";
        $i++;
      } while ($i < 15)
   ?> 

条件分岐

条件分岐として,if 文,switch 文が使える.

if 文の構造は以下の通りである.

if (条件1){
   処理1;
} elseif (条件2) {
   処理2;
} else {
   処理3;
}

具体的には以下のように書ける.

$ vi test9.php

   <?php
      // date("G") で時刻が出る
      if (date("G") >= 18) { 
         print "こんばんは";
      } elseif (date("G") >= 9) {
         print "こんにちは";         
      } elseif (date("G") >= 6) {
         print "おはよう";
      } else {
         print "眠くない?";
      }
   ?> 

switch 文の構造は以下の通りである.

switch (変数) {
case 変数1:
  処理1;
  break;
case 変数2:
  処理2;
  break;
default:
  処理X;
}

具体的には以下のように書ける.

$ vi test10.php

   <?php
      // date("G") で時刻が出る
      switch( date("G") ) {
      case 10: 
         print "10 時のおやつです";
         break;
      case 15: 
         print "午後 3 時のおやつです";
         break;            
      default:
         print "おやつの時間ではないです"; 
      }
   ?> 

配列

PHP でも配列を使うことができる.以下のように まとめて定義することも,要素ごとに定義することもできる.

//まとめて定義
$m = array( "ネズミ", "ウシ", "トラ", "ウサギ");

//要素ごとに定義.添え字番号が入れ子になっていても構わない
$m[2] = "トラ";
$m[0] = "ネズミ";
$m[1] = "ウシ";
$m[3] = "ウサギ";

//要素ごとに定義.添え字が順番通りなら以下のように省略できる.
$m[] = "ネズミ";
$m[] = "ウシ";
$m[] = "トラ";
$m[] = "ウサギ";

配列を使うと,上記の test9.php は以下のように書ける.

$ vi test11.php

   <?php
      // date("G") で時刻が出る
      $m = array("こんばんは", "こんにちは", "おはよう", "眠くない?");
      if (date("G") >= 18) { 
         print $m[0];
      } elseif (date("G") >= 9) {
         print $m[1];
      } elseif (date("G") >= 6) {
         print $m[2];
      } else {
         print $m[3];
      }
   ?> 

連想配列 (ハッシュ)

配列の添え字を数字でなくユーザ定義の文字列にすることもできる.

$ vi test12.php

   <?php
      $score["eigo"]    = 73;
      $score["suugaku"] = 84;
      $score["kokugo"]  = 68;
      print "合計点: ";
      print $score["eigo"] + $score["suugaku"] + $score["kokugo"];
   ?> 

HTML 内への埋め込み

PHP は JavaScript と同様に,HTML ファイル内に埋め込むことができる.

HTML のファイル構造は以下のようになっている.

<html>
  <head>
    <link href="xxx.css" rel="stylesheet" type="text/css" media="all">
    <meta charset="UTF-8">
  </head>
  <body>
    本文
  </bory>
</html>

PHP で以下のようなスクリプトを hello.htm として保存して ブラウザ上で表示すると,PHP スクリプトが実行されていることが分かるだろう.

<html>
   <head>
      <meta charset="UTF-8">
   </head>
   <body>
   本文
   <?php
      $text = "HTML内でのPHPスクリプト実行処理";
      echo "<p> $text </p>";
   ?>
   </bory>
</html>

ヒアドキュメントの利用

埋め込み Ruby で用いたようなヒアドキュメントを使うことができる. 書式は埋め込み Ruby と同様であり,

<<<終了を表す文字

    文字列

終了を表す文字;

となっている.以下のような内容を hello2.htm に書いてブラウザ上で 実行してみよ.

<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
  本文
  <?php
    $text =<<<eot
    <h2>HTML内でのPHPスクリプト実行処理2 </h2>
    <br>
    ほげほげ
eot;                            /// 終了を表す文字の前に空白は入れない
    print $text;
  ?>
  </bory>
</html>

データベースとの連携 (1)

PHP とデータベースの連携の例を示す.ここでは db_info.php という 接続情報を書いたファイルを作り,それを読み込ませることにしている.

まず,自分のホームディレクトリにファイル db_info.php を作成する.

$ vi ~/db_info.php   

  <?php
    $SERV="localhost";
    $USER="";           // <-- 自分のユーザ名を入力
    $PASS="";           // <-- Unix Socket を有効にしているので空で良い
    $DBNM="j4db";       // <-- 既存のデータベースを選択
  ?>

次に,データベースから検索するためのスクリプト select.php を作成する. この例では try-catch を使ってエラー処理を書いている.通常の実行時 (try ブロック内で例外が投げられなかった場合) は, catch ブロック内は処理されなず,例外が発生した場合のみ catch ブロック内が実行される. このようにしておくと,データベースへの接続・データベース操作で何か問題が発生した場合には エラー内容を表示させることができるようになる.

$ vi ~/public_html/select.php

  <?php
  try{
    /*************** データベースへ接続、データベース選択 ***************/
    require_once("/home/hogehoge/db_info.php");                     //hogehoge は自分のユーザ名に変更
    $s=new PDO("mysql:host=$SERV;dbname=$DBNM",$USER,$PASS);

    /*************** 検索 ***************/
    $mytable = "商品" ;                                             //テーブル名は自分のものに変更
    $re=$s->query("SELECT * FROM $mytable");

    /*************** クエリの結果を表示 ***************/
    while($kekka=$re->fetch()){
       print $kekka[0].", ";                                        //カラム数は $dbname で選択したテーブルに合わせる
       print $kekka[1].", ";
       print $kekka[2];
       print "<br>";
    }

  }catch(PDOException $e) {
    //エラーメッセージ表示
    print "次がエラーの内容です:".$e->getMessage();  
  }
  ?>

ヒアドキュメントを使って整形する場合は,例えば以下のように書ける.

<?php
  try{
    /*************** データベースへ接続、データベース選択 ***************/
    require_once("/home/sugiyama/db_info.php");                              //hogehoge は自分のユーザ名に変更
    $s=new PDO("mysql:host=$SERV;dbname=$DBNM",$USER,$PASS);

    /*************** 検索 ***************/
    $dbname = "商品" ;                                                       //テーブル名は自分のものに変更
    $re=$s->query("SELECT * FROM $dbname");

    /*************** クエリの結果を表示 ***************/
    print<<<eot
    <html>
      <head>
        <meta charset="UTF-8">
      </head>
      <body>
      <h1> PHP + SQL </h1>
        テーブル: $dbname
        <table border="1">
eot;
    while($kekka=$re->fetch()){
    print<<<eot
         <tr><td>$kekka[0]</td><td>$kekka[1]</td><td>$kekka[2]</td></tr>
eot;
    }
    print<<<eot
        </table>
     </body>
   </html>
eot;
  }catch(PDOException $e) {
    //エラーメッセージ表示
    print "次がエラーの内容です:".$e->getMessage();
  }
?>

データベースとの連携 (2) : 入力フォームの利用

データを送信する Web ページでは HTML の <FORM> タグを使う. <FORM> タグを使う場合の基本構造は以下の通りである.

<FORM METHOD="送信の方法" ACTION="データの送信先"> 
<INPUT TYPE="ボタンの種類" NAME="データを識別する名前"
       SIZE="サイズ" VALUE="表示する文字"or"送信する値">
</FORM>

--------------------------------
METHOD: POST or GET
TYPE: submit (データ送信), button (ボタン), text (テキスト),
      checkbox (チェックボックス), radio (ラジオボタン), hidden (表示なし)

データの入力は HTTP の GET メソッドもしくは POST メソッドを用いるが, PHP スクリプト内ではそれぞれ以下のように参照される.

  • GET メソッドで渡されたデータ → $_GET["名前"]
  • POST メソッドで渡されたデータ→ $_POST["名前"]

商品テーブルの価格に関する検索を行えるようにするスクリプトは 例えば以下のようになる.この例では,isset 関数を用いて, 変数 number に値が入力されているか否かを判断し, 入力されていない場合は入力画面を,入力されている場合は表示画面を出力している. また,fetch(PDO::FETCH_ASSOC)) というように fetch 関数に引数を与えることで カラムの数を自動的に扱えるようにしている.

<?php
  try{
    /*************** データベースへ接続、データベース選択 ***************/
    require_once("/home/sugiyama/db_info.php");      //hogehoge は自分のユーザ名に変更
    $conn=new PDO("mysql:host=$SERV;dbname=$DBNM",$USER,$PASS);

   if (!isset($_POST["number"])) {
       /*************** 検索画面の表示 ***********************/
       echo "<form method='POST'>";
       echo "値:<input type='text' name='number'><br>";
       echo "<input type='submit' value='検索'>";
       echo "</form>";

    } else {
       /*************** 検索 ***************/
       $mytable = "商品" ;              //テーブル名は自分のものに変更
       $number = $_POST["number"];

       $sql = "SELECT * FROM `$mytable` WHERE 価格 = :value";
       $stmt = $conn->prepare($sql);
       $stmt->bindParam(':value', $number);
       $stmt->execute();

       /*************** クエリの結果を表示 ***************/
       $first = true;
       while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
         if ($first) {
           echo "<tr>";
           foreach ($row as $key => $val) {
             echo htmlentities($key) . ", ";   // ドットで文字連結
           }
           echo "<br>";
           $first = false;
        }
        echo "<tr>";
        foreach ($row as $val) {
          echo htmlentities($val) . ", ";
        }
        echo "<br>";
       }
    }

  }catch(PDOException $e) {
    //エラーメッセージ表示
    echo "次がエラーの内容です:".$e->getMessage();
  }
?>

セキュリティ対策:SQL インジェクション

SQL インジェクション対策としてプレースホルダを使うのが良い.prepare と bindParam を挟んだ上で execute する形になる.

(プレースホルダを使っていない例)
     $stmt = $conn->query("SELECT * FROM `$mytable` WHERE 価格 = '$value'");

(プレースホルダを使う例)
     $sql = "SELECT * FROM `$mytable` WHERE 価格 = :value";
     $stmt = $conn->prepare($sql);
     $stmt->bindParam(':value', $number);
     $stmt->execute();

セキュリティ対策:クロスサイトスクリプティング

クロスサイトスクリプティング対策としては, 入力値を制限したり, サニタイジングを行う. サニタイジングとは, HTML タグや JavaScript スクリプトが必要とする &,<,>,”,’ の5文字の特殊文字について, そのまま画面に表示する文字列となるように置換(エスケープ)することを意味する. PHP の場合は htmlentities() 関数を使うと良い.

(htmlentities を使っていない例)
     $a1 = $_POST["a1"];

(htmlentities を使った例)
     $a1 = htmlentities($_POST["a1"]);

課題

検索条件に一致するテーブルの行を表示する Web ページを作成しなさい.

  • 作成済みのテーブル 1 つを選んで利用する.但し,商品テーブル以外とする.
  • 検索に利用するカラムは決め打ちして良い.
  • 検索結果は HTML の TABLE 形式で出力すること.
  • [オプション] ヒアドキュメント(上述)を用いるのが望ましい.echo や print をたくさん書く必要がなく,プログラムがスマートになります.

作成したスクリプトと,ブラウザ上で上記ファイルを表示したときの出力を提出すること. 後者については,アドレスバーを含むようにスクリーンショットを取得すること.