PHP
動的にWebページを生成することができるサーバーサイドのスクリプト言語です。
文法が簡単で習得しやすく、データベースとの連携も容易なため Webアプリケーション の開発によく使われる。
●参考Webページ
●基本的な文法
- ファイルの拡張子は「.php」
- htmlファイル内に埋め込む場合、「<?php ?>」または、「<?= ?>」 のタグで囲って記述する。
- コードの最後にセミコロン「;」をつける。
- コメントの記述方法は、行頭に「//」または「#」を書く。複数行コメントは「/* */」
<html>
<head>
<meta http-equiv="Content-Language" content="ja">
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>PHP埋込サンプル</title>
</head>
<body>
あなたはInternet Explorerを
<?php if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) { ?>
使用しています。<br>
<?php } else { ?>
使用していません。<br>
<?php } ?>
フォームから入力しボタンを押すとPHPページがコールされます。
<form action="action.php" method="post">
名前: <input type="text" name="name" />
年齢: <input type="text" name="age" />
<input type="submit" />
</form>
<form method="POST" enctype="multipart/form-data" action="file_send.php">
<p>送信ファイル:<input type="file" name="userfile" size="40">
<input type="submit" value="送信" name="up"></p>
</form>
</body>
</html>
●デバッグ
- 構文の誤り(Parse error)
記述ミスになり、エラーメッセージと問題があるファイルの行番号が出力される。
- 実行時エラー意味が解釈できない(Warning)
ファイルが見つからないなどの警告メッセージになり、ファイルの行番号が出力される。
- 論理エラー
プログラムのロジックに問題があるため、スクリプト内にデバック用の表示を追加するなど工夫が必要になる。
●変数、定数
命名規則について、使用できる文字列は a~z、A~Z、0~9、_(アンダーバー)になります。
変数には先頭に「$」を付け、定数と区別されます。
データ型は代入した際に自動的に決まるため意識する必要はありません。
データ型を指定したい場合(キャスト)は、変数の前に「(int)」のように指定します。
a = 1; // a に定数を代入 define("a", "1");と同じ
$a = 1; //変数 $a に代入
$str = "123";
$num = (int)$str; //文字を数値として代入
$num = "abc"; //数値 $num に文字列を代入して書き換えすることも可能
・
変数関数
isset(); //変数が宣言されていることを検査する
unset(); //指定した変数の割当を解除する
gettype(); //データ型を返す
intval('AB', 16); //指定された基数(デフォルトは 10)とする、整数値を返します。
・
予約変数
$_SERVER — サーバー情報および実行時の環境情報
$argc — スクリプトに渡された引数の数
$argv — スクリプトに渡された引数の配列
●データ型
- bool 論理値 True、False 大文字、小文字の区別はない
- int 整数値
- float 浮動小数点数
- string 文字列 基本的に文字数の制限はないが 2GB 程度
- array 配列
- object オブジェクト
- resource リソース ファイルやデータベースなどを操作する特別な関数で使われる。
- callable
- null ヌル
●文字列
「"」、「'」で囲って記述する。"は変数の内容やエスケープ文字を表す場合に使用する。
文字列を連結する場合は「.」を使用します。
ヒアドキュメント 「<<<ID ID;」で囲って記述する。
Nowdoc 「<<<'ID' 'ID';」で囲って記述する。
文字列は、int や float と解釈できる場合は数値と見なされます。
echo "abc" . "def" // abcdef
$str = <<<ID
今日は、
いい天気です。
ID;
echo 1 + "2a" //出力 3
・文字列を操作する関数
echo $str; //文字列出力 右記も同じ print($str);
strlen(); //文字列の長さ(バイト数)
$ary = split(区切り, 対象); //区切り文字で分割して配列へ 右記も同じ explode(区切り, $str);
$str = substr(対象, 開始, 長さ); //一部を切り出し
str_replace(対象, 置換, $str); //置き換え
str_getcsv(文字列, セパレータ); //CSV形式の文字列を配列にして返す。同様の関数としてexplode();
addslashes(文字列); //エスケープ文字に「\」を付加して処理。SQL文などにて使用
printf(フォーマット, arg…); //フォーマット書式で出力
$str = sprintf(フォーマット, arg…); //フォーマット書式で代入
pack(フォーマット, 値); //フォーマット書式でバイナリデータとしてパックする
mb_strlen(); //マルチバイト文字の長さ
mb_convert_kana(); //かな変換 カタカナ、全角、半角などの日本語変換
ereg(); //正規表現を使った検索
eregi(); //正規表現を使った検索(大文字、小文字を区別しない)
ereg_replace(); //正規表現を使った置き換え
●配列
$ary[] = 1; //$ary[0]に 1 を代入
$ary[] = 2; //$ary[1]に 2 を代入
$array = array("foo", "bar", "hello", "world"); //右記の記述でも可 $array = ["foo", "bar", "hello", "world"];
echo $array[1]; //bar
$ary = array(
key1 => value1,
key2 => value2,
key3 => value3,
...
);
echo $ary["key1"]; //value1の値
$ary = ["a", "b", "c",];
$cnt = count($ary);
for ($i=0; $i < $cnt; $i++) {
echo $ary[$i];
}
$ary = ["key1" => "a", "key2" => "b", "key3" => "c" ]
for (list($key, $str) = each($ary)) {
echo "$key の値は、$str です。";
}
・多次元配列
$ary1 = ['a', 'b', 'c];
$ary2 = [0, '1);
$ary3 = [$ary1, $ary2);
echo $ary3[0][1]; // b
print $pc[1][0]; // 1
$array = [
['田中', 25, '女性'],
['樋口', 32, '男性'],
['山本', 16, '女性']
];
echo $array[1][0].'('.$array[1][1].'歳'.$array[1][2].')'; //樋口(32歳男性)
・配列を操作する関数
count(); //要素数
sort(); //昇順に並び替え
rsort(); //降順に並び替え
array_unique(); //一意の要素を抽出(重複値を除いた配列を返す)
array_diff(配列1, 配列2); //差分を抽出
asort(); //連想配列の要素の昇順に並び替え。降順は arsort();
ksort(); //連想配列のインデックスの昇順に並び替え。降順は krsort();
array_push($ary, 値, 値 ...); //配列に値を追加
array_unshift($ary, 値, 値 ...); //配列の先頭に値を追加
array_merge($array, 配列, 配列 ...); //配列の値を追加
$ary = compact('変数名1', '変数名2' ...); //複数の変数を配列に統合
implode(',', $ary); //配列をカンマ区切りで文字列に変換
list($a,$b,$c)=array(1,2,3); //右辺の配列を左辺に代入する
foreach($array as $key=>$vals){} //連想配列のキーと値を取得
array_keys($ary); //配列のキーすべて、あるいはその一部を返す
●数学関数
abs(); //絶対値
round(); //四捨五入
floor(); //切り捨て値
ceil(); //切り上げ値
max();、min(); //最大値、最小値
number_format(); //フォーマットを指定して形式を整える
echo number_format(123456); // 123,456
echo number_format(123.456, 2); // 123.45
echo number_format(123456.78, 2, "#", ":"); // 12:34:56#78
●演算子
算術演算子 +、-、*、/、%、**、+$a、$a++
代入演算子 =、+=、ー=
ビット演算 &、|、^、<<、>>
比較演算子 ==、!=、<、>、<=、>=、<>、<=>
論理演算子 &&、||、and、or、xor、!
三項演算 条件式 ? 値1 : 値2 //条件が成立すれば値1、以外は値2
エラー制御演算子 @式 式により生成されたエラーメッセージは無視されます。
●制御構文
if (式) 処理;
if (式) {
処理;
} elseif (式) {
処理;
} else {
処理;
}
HTMLに埋め込む場合下記の記述も可能
<?php if ($a == 5): ?>$aは5<?php endif; ?>
while (式) {
処理;
}
while (式):
処理;
endwhile;
do {
処理;
} while (式);
for ($i; $i<9; $i++) {
処理;
}
foreach ($ary as $val) {
処理;
}
foreach ($ary as $key => $val) {
}
foreach ($ary as &$value) {
$value = $value * 2;
}
//$ary は array(2, 4, 6, 8) となります
unset($value); // 参照を解除
switch ($i) {
case 0:
処理;
break;
case 1:
処理;
break;
default:
処理;
}
break;
continue;
return;
goto ラベル;
●日時
・
日付、時刻 関数
getdate(); //現在日時を取得(連想配列)
date(); //指定したフォーマットで日時を取得
time(); //現在のUNIX時間を返す(秒)
mktime(); //日時をUNIX時間に変換
checkdate($month, $day, $year); //日付の妥当性を確認
●ファイル操作
$file = fopen("./test.txt", "r"); //ファイル開く(読取連用)モードは a、a+、r、r+、w、w+、x、x+
fclose($file); //ファイルを閉じる。
fpassthru($file); //ファイルの内容出力。出力後ファイルは自動で閉じられます。
fwrite($file, 書込文字 [, 文字数]); //ファイルへ書き込み。文字数を指定した場合は文字数分書き込み
fread($file, 文字数); //指定した文字数を読み込む
fgetc($file [, 文字数]); // 1行読み込み。文字数を指定した場合は文字数分読み込み
file_exists("./test.txt") //ファイルの存在確認
fpassthru($file); //ファイルの内容を全て表示
fgetcsv(); //CSVファイルから1行読み込み配列へ格納する
fputcsv(); //配列データをCSVファイルへ1行書き込み
file() //ファイル全体を読み込んで1行ずつ配列に格納する
__DIR__ //現在のディレクトリ
__FILE__ //現在のファイルパス
dirname(パス); //親ディレクトリ取得
chdir(ディレクトリ); //カレントディレクトリ移動
●画像操作
$image = ImageCreate(100,100); //画像サイズ指定
$black = ImageColorAllocate($image,0,0,0); //バックグラウンド色 最初のコールで背景色がセットされます。
$white = ImageColorAllocate($image,255,255,255); //描画色
ImageLine($image,0,50,99,50,$white); //直線描画
ImageArc($image,50,50,98,48,0,360,$white); //円弧描画
ImageRectangle($image,10,25,89,74,$white); //四角描画
Header("Content-Type: image/png");
ImagePNG($image); //PNG イメージを出力
ImageDestroy($image); //画像を破棄。リソース解放
<?php
//元画像
$size = GetImageSize("sample.PNG"); //画像サイズ取得
$image_in = ImageCreateFromPNG("sample.PNG"); //画像読み込み
//拡大画像
$image_L = ImageCreate($size[0] * 2,$size[1] * 2); //拡大画像領域作成
ImageCopyResized($image_L,$image_in,0,0,0,0,$size[0] * 2,$size[1] * 2,$size[0],$size[1]); //画像をコピー
ImagePNG($image_L,"large_php.PNG"); //画像をファイル出力
imageDestroy($image_L); //画像を破棄。リソース解放
//縮小画像
$image_S = ImageCreate($size[0] / 2,$size[1] / 2);
ImageCopyResized($image_S,$image_in,0,0,0,0,$size[0] / 2,$size[1] / 2,$size[0],$size[1]);
ImagePNG($image_S,"small_php.PNG");
imageDestroy($image_S);
ImageDestroy($image_in); //画像を破棄。リソース解放
?>
<IMG SRC = "sample_php.PNG" BORDER = "0">
<IMG SRC = "large_php.PNG" BORDER = "0">
<IMG SRC = "small_php.PNG" BORDER = "0">
$size = GetImageSize("sample.PNG"); //画像サイズ取得
$image = ImageCreateFromPNG("sample.PNG"); //画像読み込み
$white = ImageColorAllocate($image,255,255,255); //描画色
$text = "Hello"; //埋込文字
$font = 5 //文字フォント
$start_x = $size[0] / 2 - (strlen($text) * ImageFontWidth($font) / 2); //横中央揃え
$start_y = $size[1] / 2 - ImageFontHeight($font) / 2; //縦中央揃え
ImageString($image, $font, $start_x, $start_y, $text, $white); //画像に埋込
Header("Content-Type: image/png");
ImagePNG($image); //PNG イメージを出力
ImageDestroy($image); //画像を破棄。リソース解放
●関数
function kakezan($num) { //関数の定義
return $num * 100;
}
echo kakezan(3); //関数の呼び出し
//引数の初期値を指定
function kakezan($num = 1) { //関数の定義
return $num * 100; //戻り値
}
echo kakezan(); // 100
//引数を配列で渡す
function kakezan($num) {
return $num[0] * $num[1];
}
echo kakezan(array(3,3));
//引数の参照渡し 呼び出し元の変数を変更できます。
function kisetsu(&$shiki) {
$shiki = '夏';
}
$str = '春';
kisetsu($str);
echo "季節は$str"; //夏
・アクセス修飾子
functionの前に追加することで関数の呼び出しができる範囲を指定できます。
public どこからでもアクセス可能です。アクセス修飾子がない場合は、publicを指定したものと同じになります。
protected そのクラス自身と継承クラスからアクセス可能です。つまり非公開ですが、継承は可能となります。
private 同じクラスの中でのみアクセス可能です。非公開で継承クラスからもアクセス不可能となります。
●HTTP、URL 関数
header('Location: http://www.example.com/'); //別ページへリダイレクト
header('Content-Type: application/pdf'); //PDFを出力します
header('Content-Disposition: attachment; filename="downloaded.pdf"'); //pdf保存
header("Location: リダイレクト先URL", true, 307); //POSTリクエストの内容を引き継ぎながらリダイレクト
header("Location: リダイレクト先URL", true, 302); //POSTからGETリクエストにしてリダイレクト
header_sent(); //HTTPヘッダ送信中は true
setcookie(); //クッキーの設定
parse_url(); //URLの構成要素を連想配列に格納
base64_decode(); //BASE64デコードエンコード
base64_encode(); //BASE64エンコード
urldecode(); //URLエンコード
urlencode(); //URLエンコード 文字列の非英数字を変換(URLにて文字列をGETする場合に有用)
●ファイルのインクルード
require("ファイルパス"); //スクリプトの実行前に読み込まれます。読み込み出来ない場合はエラー。
//name.phpとしてファイル作成
<?php
define ("name","山田 太郎");
require ("name.php"); ///name.phpを読み込む
echo name; //山田 太郎
require_once(); //すでにファイルが読み込まれている場合は読み込みません。
include("ファイルパス"); //実行されるたびに読み込まれます。読み込み出来ない場合はスルー。
for ($i=1; $i<=3; $i++) {
include ("kakezan" . $i . ".php");
}
//kakezan1.php、kakezan2.php、kakezan3.phpが順番に実行されます。
include_once(); //すでにファイルが読み込まれている場合は読み込みません。
class keisan {
var $sum = 0; //合計(デフォルトのプロパティ)
const STR = "hoge"; //クラス内の定数
function __construct() { // コンストラクタ(インスタンスを生成した際に呼び出される)
}
function tasizan($a = 0, $b = 0) { //足し算(メソッド)
$c = $a + $b;
$this->sum += $c;
return $c;
}
function hikizan($a = 0, $b = 0) { //引き算(メソッド)
$c = $a - $b;
$this->sum += $c;
return $c;
}
function print_hoge() { //定数出力(メソッド)
echo self::STR;
}
}
$calc = new keisan;
echo $calc->tasizan(1, 2); // 出力 3(メソッド)
echo $calc->hikizan(3, 2); // 出力 1
echo $calc->sum; // 出力 4(プロパティ)
echo $calc->print_hoge(); // 出力 hoge(メソッド実行)
echo $calc::STR; // 出力 hoge(定数を参照)
・静的メンバ
クラス内で独立したプロパティ、メソッドのことを静的メンバと呼び、変数や関数の先頭にstaticを記述します。
class test {
static $a = 0; //静的プロパティ
function countUp() {
return self::$a++; //静的プロパティに加算。
}
}
$test1 = new test;
echo $test1->countUp(); // 出力 1
echo $test1->countUp(); // 出力 2
$test2 = new test;
echo $test2->countUp(); // 出力 3 静的プロパティの値はクラス内で共有されているため
・クラス情報を取得する関数
echo get_class_vars(クラス名) //クラスのデフォルトのプロパティのを取得する
class_exists(クラス名) //クラスが定義済みか確認
ユーザーを識別するために使われる技術で、Webサイトの訪問回数やショッピングカートなどの情報をクライアント側に保存しておけます。
ただし、ブラウザの設定でクッキーを許可していない場合には使用できないため、配慮する必要があります。
クッキーはブラウザを閉じた際に削除されますが、有効期限を設定することができます。
ブラウザに保持できるクッキーには個数の制限があり、許可されたサーバーにのみ送信されます。
if(!isset($HTTP_COOKIE_VARS["CountCookie"])) { //クッキーの有無確認
$count = 1;
setcookie ("CountCookie", $count); //CountCookieという名前でクッキーをセット
//setcookie ("CountCookie", $count, time() + 30 * 60); //有効期限を設定 30分
//setcookie ("CountCookie", $count, mktime(0,0,0,12,31,2023)); //有効期限を設定 任意の日時(2023/12/31 00:00:00)
echo "このスクリプトへのアクセス回数は1回目です!";
} else {
$count = $HTTP_COOKIE_VARS["CountCookie"] + 1;
setcookie ("CountCookie", $count);
echo "このスクリプトへのアクセス回数は" . $count . "回目です!";
}
setcookie ("CountCookie"); //クッキー名のみ指定するとクッキーを削除
//配列で1つのクッキーに複数の値をセット
setcookie ("ArrayCookie[1]","one");
setcookie ("ArrayCookie[2]","two");
setcookie ("ArrayCookie[3]","three");
if(isset($HTTP_COOKIE_VARS["ArrayCookie"])) {
while (list($name, $value) = each ($HTTP_COOKIE_VARS["ArrayCookie"])) {
echo "$name : $value<br>\n";
}
}
同一ユーザーがアクセスしているのか判断するため、固有のIDを使って管理します。
各ページ毎にIDを確認することで不正なアクセスを防止します。
session_start()関数を呼び出し、セッション変数(連想配列)$_SESSION[]に値を入れます。
スクリプトの最初にこの値を確認するようにします。
セッションIDの情報は、サーバー内のtmpフォルダにファイルとしてセッション毎に保存されています。
セッションファイルはブラウザを閉じるか有効期限(デフォルトでは24分)を過ぎると削除されます。
ただし、有効期限が切れた場合には、次に接続した際に100分の1の確率で削除されます。
php.iniにて変更できます。
;有効期限を24時間に設定
session.gc_maxlifetime = 86400
;有効期限切れで1/1の確率で削除
session.gc_probability = 1
session.gc_divisor = 1
session_start(); //セッションを開始、または既存のセッションを再開
if (!isset($_SESSION["visited"])) {
print('初回の訪問です。セッションを開始します。');
$_SESSION["visited"] = 1;
$_SESSION["date"] = date('c');
} else {
$visited = $_SESSION["visited"];
$visited++;
print('訪問回数は'.$_SESSION["visited"].'です。');
$_SESSION["visited"] = $visited;
if (isset($_SESSION["date"])) {
print('前回の訪問日時は'.$_SESSION["date"].'です。');
}
$_SESSION["date"] = date('c');
}
・セッション削除
session_start();
$_SESSION = array(); //すべてのセッション変数を削除。個別に削除する際は unset($_SESSION("visited"));
if (isset($_COOKIE["PHPSESSID"])) {
setcookie("PHPSESSID", '', time() - 1800, '/'); //クライアント側クッキーを削除
}
session_destroy(); //セッションに登録されたデータを全て破棄
●応用
$file = fopen("c:\\temp\\count.txt","r+");
$count = fread($file,10);
$count = $count + 1;
Header("Content-Type: image/png");
$image = ImageCreate(100,100);
$black = ImageColorAllocate($image,0,0,0);
$white = ImageColorAllocate($image,255,255,255);
$start_x = 50 - (strlen($count) * ImageFontWidth(5) / 2);
$start_y = 50 - ImageFontHeight(5) / 2;
ImageString($image,5,$start_x,$start_y,$count,$white);
ImagePNG($image);
ImageDestroy($image);
fseek($file,0);
fwrite($file,$count);
fclose($file);
PHPを使ったもっともシンプルな認証方法になります。ユーザー名とパスワードを入力してデータの比較をします。
if(!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
echo "ユーザーの認証が必要です。";
exit;
} elseif(isset($_SERVER['PHP_AUTH_USER'])) {
$user = "admin"
$pass = "abc001"
if(($_SERVER['PHP_AUTH_USER'] != $user) || ($_SERVER['PHP_AUTH_PW'] != $pass)) {
header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
echo "ユーザーの認証が必要です。";
exit;
} else {
echo "認証に成功しました!";
}
}
//データベースとの照合を行う場合
if(!isset($_SERVER['PHP_AUTH_USER']) or !isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
echo "ユーザーの認証が必要です。";
exit;
} else {
$id = $_SERVER['PHP_AUTH_USER'];
$psw = $_SERVER['PHP_AUTH_PW'];
//DB設定、SQLコマンド
$con = sqlite_open('../SQLiteManager/sample');
$sql = "select * from user where id = '$id' and psw = '$psw'";
$result = sqlite_query($con,$sql);
$row = sqlite_num_rows($result);
if($row == 0) {
header('WWW-Authenticate: Basic realm="Private"');
header('HTTP/1.0 401 Unauthorized');
echo "該当するユーザーIDとパスワードがありません。";
exit;
} else {
echo "認証に成功しました!";
}
}
〇〇〇 工事中 〇〇〇