PHP の覚え書き

初版作成  2011.11
最終更新  2018.02.01


◆◆ 動作環境 ◆◆

php は /usr/bin あるいは /usr/local/bin に
インストールされる。

  % php file.php

で実行可能。

通常は apache から呼び出して使う。
環境変数などを参照する必要があるので、
実際に apache から動かしてみてデバッグする
ケースが多い。

<注意!!!>

apache から呼び出されるとき www-data などの
権限で呼び出される。ファイルのパーミッションは

  $ chmod 666 file.php

のように、他人に対して読み込み許可を出す必要が
ある。これを忘れてハマるケースがある。


◆◆ 設定ファイル ◆◆

php.ini の中を以下のように変更する

default_charset = "UTF-8"
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = auto
mbstring.http_output = pass
mbstring.encoding_translation = Off
mbstring.detect_order = SJIS,EUC-JP,JIS,UTF-8,ASCII
mbstring.substitute_character = none;

display_errors = On

php.ini の場所は

<?php
  phpinfo()
?>

で得られる。

◆◆ コードの記述方法 ◆◆

普通は <body> の中に

<?php
   プログラム
?>

ただし、クッキーを送るときは <head> の手前に置く

複数の場所に分けて書いたプログラムは一つと解釈される。

◆◆ コメント ◆◆

C++ と同じ
// コメント
/* コメント */

◆◆ 定数 ◆◆

真偽値は  TRUE or FALSE
小文字でもよい


◆◆ 行 ◆◆

C++ と同じ
; で区切る

◆◆ 変数 ◆◆

$ で始まる。

宣言不要。

関数外で使うとグローバル
関数内で使うとローカル

関数内でグローバル変数を使いたいとき

    global $data;

のように宣言する。


◆◆ 文字列 ◆◆

$moji = 'aa'.'bb';        連結

$head = substr($line,0,2);          先頭から 2 文字取り出す
$head = mb_substr($line,0,2);       同上  マルチバイト文字対応

$len = strlen($str);
$len = mb_strlen($str);

$euc = mb_convert_encoding($str,'UTF-8','EUC-JP';   euc --> utf-8

$str = trim($str)              左右の空白, tab, \n の切り落とし
$str = implode('+',$array)     perl の join
$array = explode(' ',$str)     perl の split

mb_ereg("[あ-ん]",$cha)        ひらがなかどうか調べる


◆◆ 出力(表示) ◆◆

print, echo はどちらも perl の print と同じ
printf は C と同じ " のエスケープは \"

echo $moji;
echo "moji = {$moji}\n";   \n は 改行,  { } がなくても動く場合がある。
echo "$a[1]  $a[abc]\n";   連想配列の添字を '' で囲むとエラーになる

printf("<li><a href=\"%s\">%s</a></li>",$value,$key);

print_r($array)     () の内容を詳細に表示する

◆◆ 配列 ◆◆

配列と連想配列は区別されない。
添字は整数または文字列。

普通の配列

$a = array(1,2);              $a[0] = 1     $a[1] = 2

$b = array(  2 => 'aa',       $b[2] = 'aa'
             4 => 'bb');      $b[4] = 'bb'  このとき count($b) は 2

' の代わりに " でもよい。

連想配列

$a['aa'] = 'AA';
$a['bb'] = 'BB';

$a = array( 'aa' => 'AA',
            'bb' => 'BB');

削除

unset($a[0]);  要素を削除
unset($a);     配列全体を削除


◆◆ foreach ◆◆

$array は配列

foreach($array as $value){
    echo "$value <br>";
}

foreach($array as $key => $value){
    echo "$key = $value <br>";
}

◆◆ 2 次元配列 ◆◆

$a[0][0] = 1;
$a[1][1] = 1;
$a[1][2] = 1;
$a[2][1] = 1;

のように書ける。このとき

count($a)      : 3
count($a[0])   : 1
count($a[1])   : 2
count($a[2])   : 1

となる。

$c[0] = array(1,2);
$c[1] = array(-1,-2,-3);
$c[2] = array(10,11,12,13,14);

のようにも書ける。全ての要素を書き出すには

for( $i = 0; $i < count($c); $i++){
    for( $j = 0; $j < count($c[$i]); $j++){
        echo "$i $j : ".$c[$i][$j]."\n";
    }
}

foreach( $c as $value ){
    foreach( $value as $key2 => $value2 ){
        echo "key2 = $key2   value2 = $value2 \n";
    }
}

◆◆ ループからの脱出 ◆◆

C と同じ。ただし switch もループ構造とみなされる

break;
continue;

break 2;        2 レベル抜ける
continue 2;     2 レベル抜ける

◆◆ if ◆◆

if ( $a > $b ) {

} elseif ( $a == $b ) {

} else {

}

◆◆ 情報取得 ◆◆

スーパーグローバル変数   global 宣言不要

$_POST['key']
$_GET['key']
$_COOKIE['key']

環境変数

getenv('REMOTE_ADDR')
getenv('HTTP_REFERER')


◆◆ 関数 ◆◆

isset($a['abc'])    定義されているか否か
ctype_digit($a)     数値か否か


◆◆ 配列操作関数 ◆◆

array_push($array,$data)
$a = array_merge($a,$b)

is_array($a)        配列か普通の変数か
count($a)           配列の要素数

$array_count_values($array)    配列の要素数の種類をカウントして
                               連想配列として返す。


◆◆ ファイル操作 ◆◆

file() はファイルを全て読み込み、改行で区切って配列にする。
@ はエラーが発生してもスクリプトの実行を継続する命令。
or 以降を実行するための記号。

$lines = @file($fname) or exit('cannot open file.');
for( $i = 0; $i < count($lines); $i++){
    echo $lines[$i];
}

   -----------

fopen, fgets, fputs, fclose は C とほぼ同じ
fgets で取得した文字列の最後は 0d 0a の 2 byte が付いている。
「みるみる PHP がわかる本」によると、テキストの読み書きも b が
推奨されるらしい。

$f = @fopen($fname,"rb") or exit('cannot open file.');
while( feof($f) == false ){    // feof($f) は eof を確認したら true になる
    $str = fgets($f);          // 行末まで読み込み
    echo $str."\r\n";
}
fclose($f);

先頭まで巻き戻すとき

rewind($f);

書き出すとき

fputs($f,$str);

   -----------

readfile() はファイルを開いて内容を全て標準出力に出す。

@readfile($fname) or exit('cannot open file.');


◆◆ CSV ファイルの操作 ◆◆

読み込み

$f = @fopen($fname,"rb") or exit("cannot open file.");
while( !feof($f) ){
    $array = fgetcsv($f);
    $str = implode(",",$array);
    echo $str."\n";
}
fclose($f);

書き出し

$array = array($a,$b,$c);

$f = @fopen($fname,"ab") or exit("cannot open file.");
fputscsv($f,$array);
fclose($f);


◆◆ ディレクトリ操作 ◆◆

@opendir($path) or exit("cannot open dir");
while( $f = readdir($dir) ){
    echo $f."\n";
}
closedir($path);


◆◆ 関数 ◆◆

func($a);    // 値渡し
func(&$a);   // 参照渡し

関数側は値渡し、参照渡しのどちらでも同じ構文

function func($a){
    return($b);
}


◆◆ ファイルのアップロード ◆◆

アップロード用 html

<form method="post" action="upload_manage.php" enctype="multipart/form-data">
<input type="hidden" name="max_file_size" value="2000000">
アップロードファイル:
<input type="file" name="f1" size="50">
<!-- name="fname" はダメ  原因不明 -->
<p>
<input type="submit" value="アップロード実行">
</form>

関係する php.ini のパラメータ

file_uploads         ファイルアップロードの可否
upload_tmp_dir
upload_max_filesize
post_max_size

「input の max_file_size」は「php.ini の upload_max_filesize」
より小さくする。

アップロード処理用 upload_manage.php

<?php
/*
    アップロードしたファイルをセーブするディレクトリは 777 にしておく。
    www の権限で書き込めなくてはならない。
*/
if ( is_uploaded_file($_FILES['f1']['tmp_name']) ){
    $fname      = $_FILES['f1']['name'];
    $tmp_fname  = $_FILES['f1']['tmp_name'];
    $save_fname = "savefiles/".time()."-".$fname;

    $ret = move_uploaded_file($tmp_fname, $save_fname);
    if ( $ret == true ){
        echo "ファイルのアップロードに成功しました。";
    } else {
        echo "ファイルのアップロードに失敗しました。";
    }
} else {
    echo "ファイルが選択されていません。";
}
?>

◆◆ ヘッダを送る ◆◆

header('location: index.php');   移動先を指定する

◆◆ クッキー ◆◆

クッキーを送る

setcookie($key, $value, time()+3600, '/');

第3引数は○秒。省略時はブラウザを終了するまで。
第4引数は適用されるディレクトリ。'/' はそのドメイン全て。省略時はカレントディレクトリ

クッキーを読み取る

if ( isset($_COOKIE['key']) ){
   $value = htmlspecialchars($_COOKIE['key'], ENT_QUOTES);
   // html のエスケープ処理
}

◆◆ ファイルの最終更新時刻を読み取る ◆◆

date('Y / n / j H : i : s', filemtime($fname));

filetime はファイルの日付を整数で返す関数。
date はその値をフォーマット文字列に従って整形する関数。

Y   年 4 桁
n   月 先頭に 0 をつけない
j   日 先頭に 0 をつけない
H   時 24 時間単位
i   分 先頭に 0 をつける
s   秒  先頭に 0 をつける