2014年12月26日金曜日

PHPでDBアクセス

PDO(PHP Data Objects)

データーベース抽象化レイヤ(DBの違いを気にせずに使える)


エラー通知

以下の記述をしておくと、SQLの構文エラーを通知してくれる

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

※$dbはPDOオブジェクト



DBを開く

new PDO(データベース接続文字列, ユーザー名, パスワード)



データベース接続文字列

mysql:host=ホスト名; dbname=データベース名; charset=文字コード



DBを閉じる

PDOオブジェクトを破棄する(NULLにする)
※こうしなくてもスクリプトが終了すれば自動でDB接続が切断される



例)ローカルDBのデータベース名php10を文字コードutf8で開く

//開く
$db = new PDO('mysql:host=localhost;dbname=php10;charset=utf8', 'phpusr', 'phppass');

//閉じる
$db = NULL;




例外処理

try {
  例外が発生する可能性のあるコード
} catch (例外の種類 変数名) {
  例外発生時の処理
}


例)
try {
  $db = new PDO('mysql:host=localhost;dbname=php10;charset=utf8', 'phpusr', 'phppass');
} catch (PDOException $e) {
  die('エラーメッセージ:' . $e->getMessage());
}



SQLの実行

以下の手順が必要

・SQLの準備
・SQLにパラメータをセット
・SQL実行



SQLの準備

PDOオブジェクト->prepare(SQL文);

※PDOStatementオブジェクトが返ってくる




SQLにパラメータをセット

SQL文の中にプレイスホルダ(:名前)を使った場合、そこに値をセットする

※プレイスホルダを使わないとセキュリティ上の問題(SQLインジェクション)がある

PDOStatementオブジェクト->bindValue(パラメータ名, 値);


※セットする値が数値(int)の場合は第三引数に「PDO::PARAM_INT」を付けた方がよい

例)
$stt->bindValue(':age',$arr['age'],PDO::PARAM_INT);




SQL実行

PDOStatementオブジェクト->execute();


例)INSERTを実行

//DB接続
$db = new PDO('mysql:host=localhost;dbname=php10;charset=utf8', 'phpusr', 'phppass');

//SQLの準備
$stt = $db->prepare('INSERT INTO schedule(title) VALUES(:title)');

//SQLにパラメータをセット
$stt->bindValue(':title', $_POST['title']);

//SQL実行
$stt->execute();

//DB切断
$db = NULL;




DBからレコードを取得


SELECT文をexecuteメソッドを実行するとその結果がPDOStatementに保存される




取得したレコードの表示

1行ずつフェッチ(読み込み)をする

PDOStatementオブジェクト->fetch();




フェッチの形式を変更

fetchメソッドは規定で配列または連想配列でアクセスできるように返してくれる

変更したい場合はfetchメソッドに以下の引数を渡す

PDO::FETCH_NUM…配列($row[1])
PDO::FETCH_ASSOC…連想配列($row['title'])
PDO::FETCH_BOTH…配列または連想配列[規定]($row[1] or $row['title'])
PDO::FETCH_OBJ…オブジェクト($row->title)



例)

$db = new PDO('mysql:host=localhost;dbname=php10;charset=utf8', 'phpusr', 'phppass');
$stt = $db->prepare('SELECT title FROM schedule');
$stt->execute();

//全てのレコードをフェッチ
while ($row = $stt->fetch()) {
  //タイトル列を表示
  print($row['title']);
}
$db = NULL;




文字列→日付変換

strtotime(日付時刻文字列);

日付の文字列がUnixタイムスタンプ(1970/1/1 00:00:00から経過した秒数)に変換される

例)
$ts = strtotime('2014/12/26');




日付をフォーマット

フォーマットした日付を文字列で取得

date(フォーマット文字列 [, Unixタイムスタンプ]);

※タイムスタンプは省略可能、その場合は現在日時・時刻となる

例)現在日時をYYYY/MM/DDの形で取得
$str = date('Y/m/d');




タイムスタンプ取得

現在日時・時刻のUnixタイムスタンプを取得

time()

例)
$ts = time;




任意のタイムスタンプ取得

任意の日付・時刻のUnixタイムスタンプを取得

mktime(時, 分, 秒, 月, 日, 年);


例) 2015/1/6 9:18:45秒のタイムスタンプを取得
$ts = mktime(9, 18, 45, 1, 6, 2015);





日付書式

Y4桁の年。例:2014
y2桁の年。例:14
L閏年。1:閏年 0:閏年ではない
mゼロ詰めの月。01~12
nゼロなしの月。1~12
Fフルスペルの月。例:January
M3文字形式の月。例:Jan
t月の日数。28~31
dゼロ詰めの日。01~31
jゼロなしの日。1~31
z年間の通算日。0~365
g12時間単位の時(ゼロなし)。1~12
G24時間単位の時(ゼロなし)。0~23
h12時間単位の時。01~12
H24時間単位の時。00~23
i分。00~59
s秒。00~59
a午前:am 午後:pm
A午前:AM 午後:PM
D3文字形式の曜日。例:Mon
lフルスペルの曜日。例:Monday
NISO-8601形式の曜日。1(月)~7(日)
w曜日。0(日)~6(土)



isset,empty,is_null
if($var)issetemptyis_null
$var=1TRUETRUEFALSEFALSE
$var="";FALSETRUETRUEFALSE
$var="0";FALSETRUETRUEFALSE
$var=0;FALSETRUETRUEFALSE
$var=NULL;FALSEFALSETRUETRUE
$varFALSEFALSETRUETRUE
$var=array()FALSETRUETRUEFALSE
$var=array(1)TRUETRUEFALSEFALSE

リダイレクト

以下のように書けば強制的に別のページに移動する

header('Location: リダイレクト先のURL');

※headerの前に出力(echoなど)をしてはいけない


例) yahooへリダイレクトさせる
header('Location: http://yahoo.co.jp/');




ファイルを開く

fopen(ファイルのパス, オープンモード)

※戻り値としてファイルハンドルを返す


オープンモード

rb…読み取り専用
wb…書き込み専用
w+b…読み書き
ab…追記書き込み
a+b…読み書き(追記)




ファイルを閉じる

fclose(ファイルハンドル);



ファイルに書き込む

fputs(ファイルハンドル, 書き込む文字列);

※fwriteでもOK



ファイルのロック

flock(ファイルハンドル, ロックの種類)

LOCK_SH…共有ロック(書き込み禁止)
LOCK_EX…排他ロック(読み書き禁止)
LOCK_UN…ロックの解除


例)
//ファイルをオープン
$file = fopen('guest.dat', 'ab');

//ファイルをロック
flock($file, LOCK_EX);

//ファイルに書き込み
fputs($file, 'abc');

//ロックを解除
flock($file, LOCK_UN);

//ファイルを閉じる
fclose($file);



@演算子

処理の実行に失敗した場合でも警告を発生させない

※その場合、エラーがあったかどうか分からないので「or die…」を付ける



CSVファイルの読み込み

fgetcsv(ファイルハンドル, 読み込む最大文字列, 区切り文字)

例)タブ区切りファイルの読み込み
$file = @fopen('guest.dat', 'rb') or die('ファイルが開けませんでした');
while ($row = fgetcsv($file, 1024, "\t")) {
  echo $row[0]));
}
fclose($file);


ファイルの読み込み

fgets(ファイルハンドル)



文字を分割

explode(区切り文字, 文字列)




トランザクション処理

DBへの複数回に渡る追加、更新をまとめて処理すること

※大量の件数の処理を行う場合はトランザクションを使ったほうが早い

※InnoDBではないと場合はトランザクションは使えない




トランザクション開始

beginTransaction



トランザクション完了

commit


トランザクションの巻き戻し

rollback


例)CSVファイルの中身を全件DBへ登録
try {
  $db = new PDO('mysql:host=localhost;dbname=php10;charset=utf8', 'phpusr', 'phppass');

  //トランザクション開始
  $db->beginTransaction();

  $file = @fopen('ejdic-hand-utf8.txt', 'rb') or die(' failure!');

  //CSVファイルの中身を全件登録
  while ($row = fgetcsv($file, 5000, ",")) {
    $stmt = $db->prepare('INSERT INTO ejdic (word, mean) VALUES(:word, :mean) ');
    $stmt->bindValue(':word', $row[0]);
    $stmt->bindValue(':mean', $row[1]);
    $stmt->execute();
  }

  //トランザクションを完了
  $db->commit();
} catch (PDOException $e) {

  //例外が発生した場合処理を巻き戻す
  $db->rollBack();
  echo $e->getMessage();
}

0 件のコメント:

コメントを投稿