PHP – PDO プリペアードステートメント

基本形

  • $pdo = new PDO()PDOオブジェクトを得る
  • $stmt = $pdo->prepare()でプレースホルダー入りのSQLを準備する
  • $stmt->bindValue()$stmt->bindParam()でプレースホルダーを埋める
  • $stmt->execute()でバインドを有効化する

bindValueによる値の設定

'?'によるプレースホルダー

以下の例では、prepare()のSQL中2つの'?'がプレースホルダーになる。

bindValue()の第1引数は何番目のプレースホルダー'?'かを指定し、第2引数にそのプレースホルダーにセットする値を指定する。第3引数は省略するとPDO::PARAM_STRになる。

この結果、データベースのnum_datastr_dataにそれぞれ10, 'ABC'が追加される。

名前によるプレースホルダー

以下の例では、prepare()のSQL中':num'':str'の2つがプレースホルダーになる。

bindValue()の第1引数でそれぞれのプレースホルダーを指定し、第2引数にそのプレースホルダーにセットする値を指定する。第3引数は省略するとPDO::PARAM_STRになる。

この結果、データベースのnum_datastr_dataにそれぞれ20, 'DEF'が追加される。

bindParamによる変数の設定

bindValue()はプレースホルダーに値を設定したが、bindParam()は変数を設定する。

変数がバインドされた時点ではSQLの内容は決定されていない。変数に値をセットし、execute()を実行した段階でSQLの値が確定する。

この例では2つのプレースホルダーに変数をバインドし、その変数に値を与えてからexecute()を実行している。プレースホルダーに'?'を用いてもよい。

この結果、データベースのnum_datastr_dataにそれぞれ30, 'GHI'が追加される。

 

JS/ES – 雛形・テンプレート

記述場所

bodyセクションの最後かheadセクション内。headセクションに置く場合はDOM生成後に必要な処理は以下の中に記述。

window.onload = function() { ... }

無名関数はアロー関数() => {}でもよい。

DOMの操作

DOMの取得

bodyの取得

document.body

要素名で取得

var element = document.getElementsByTagName('要素名');

'Elements'と複数形であることに注意。結果は配列になる。

idで取得

var element = document.getElementById('ID名');

ID名は#を付けない。結果は単体のDOM。

DOMの内容

要素.innerHTML

innerHTMLプロパティーで直接参照・設定

DOMの作成

var element = document.createElement('要素名');

DOMの追加

body内の指定要素の前に追加

document.body.insertBefore(追加要素, 指定要素);

body内の最後に追加

document.body.appendChild(追加要素);

指定要素の中の最後に追加

指定要素.appendChild(追加要素);

 

PHP – 雛形 – ファイルアップロード

概要

HTML側でアップロードされたファイルをPHP側で受け取り、妥当性のチェック、所定の場所への保存などを行う最低限の手順。

HTML側でのファイル選択

INPUT要素でtype="file"を指定し、サーバー側で参照するためのname属性を設定する。

HTML表示の際、デフォルトで”ファイルを選択”ボタンが表示され、これをクリックするとダイアログによるファイル選択が可能となる。

PHPで受け取る値

HTML側からの結果が受信されたとき、スーパーグローバル変数$_FILESに連想配列としてアップロードされたファイルの情報が格納される。以下、'name値'はINPUT要素で指定されたname属性の値。

$_FILES['name値']['error']
エラーコード。PHPで定義された定数でエラーステータスを確認可能。(PHP-manual)
$_FILES['name値']['name']
アップロードファイル名。
$_FILES['name値']['tmp_name']
アップロードされたファイルのフルパス。
$_FILES['name値']['type']
アップロードファイルのMIMEタイプを取得。たとえばimage/jpeg、image/pngなど。
$_FILES['name値']['size']
アップロードされたファイルのサイズ

PHP側の処理

INPUT要素を受け取ったPHP側での最低限の処理の流れは以下のとおり。

  1. $_FILES['name値']['error'] === UPLOAD_ERR_OKでアップロード時のエラーをチェック
  2. 以下の変数を設定
    • $image_file_name = $_FILES['name値']['name'];
    • $tmp_name = $_FILES['name値']['tmp_name'];
    • $type = $_FILES['name値']['type'];
  3. is_uploaded_file($tmp_name)でアップロードファイルの妥当性をチェック
  4. $type === 'image/jpeg' && $type !== 'image/png'でファイルタイプをチェック
  5. move_uploaded_file($tmp_name, IMAGE_DIR . $image_file_name);でアップロードされたファイルを任意のディレクトリー(この場合IMAGE_DIR)に移動
    • この実行結果のtrue/falseに応じてファイル名のデータベースへの登録などの処理を実行

$_FILES['name値']['type']ユーザーから送信されたものなので、偽装・改竄に対する完璧な防御にはならないが、上記は最低限の流れ。

 

JQuery – 要素指定方法

基本形

要素種類

$('要素名')

全てのp要素の色が緑になる。

id指定

$('#id値')

id=1の要素が赤くなる。

クラス指定

$('.class値')

class='target'が指定された要素が青くなる。

包含関係

$('セレクター1 セレクター2')

スペースで並べる→セレクター1に含まれるセレクター2

$('セレクター1 > セレクター2')

'>'でつなぐ→セレクター1直下のセレクター2

$('セレクター1 + セレクター2')

'+'でつなぐ→セレクター1の次に現れるセレクター2

属性値指定

1つの属性値

HTML中の要素のうち、特定の属性が指定された要素をJQueryで指定したい場合。

$('要素名[属性=値])

value属性が"1"div要素が赤くなる。

2つの属性値のAND

$('要素名[属性1=値1][属性2=値2]')

name属性が"NAME"value属性の値が"VALUE"div要素の色が黄色になる。

 

PHP – GETの流れ

概要

GETメソッドの挙動・手順を確認した。

  • 普通にHTML/PHPファイルが呼ばれると、GETメソッドになる
  • なので初回起動時の処理はGETメソッド前提で、$_GET変数は定義済み、要素数0をチェック
  • $_GETの要素数が0より大きければ初回以降のGETメソッド処理
  • 初回以降の$_GETの要素チェックは''との比較でok

確認コード

以下のHTMLとPHPで動作を確認する。

HTML

  • フォームからGETメソッドで送信する
  • 送信するのはテキストボックスの内容のみ
  • PHP側で処理された$msgを出力する

PHP本体

  • 全体の処理開始以降、節目の経過を$msgに累積記録し、HTMLでの出力に備える

結果

初期起動時

HTMLの表示は以下の通り。

  • 起動時にGETで始まっている
  • そのため$_GET変数も定義済みになっている
  • ここには書いていないがvar_dumpで確認すると'Array  ()'となっている
  • ただし$_GETの要素数は0

このときブラウザーでのURL表示は以下のとおり。

起動後のGET時

テキストボックスに’abc’と入れて送信した結果が以下の通り。

このときブラウザーでのURL表示は以下のとおり。ファイル位置の後ろに?でパラメーターが加えられている。

なお、上記の実行後にはテキストボックスの内容は空になっている。

再度GETの実行時

このときのブラウザーでのURL表示は以下のとおり。

リロード時

ブラウザーのリロードで再読み込みをすると、最後に表示されていたURLのままでリロードされ、同じ結果が表示される。

?以降のパラメーター部分を消してリロードしても、元のパラメーターが付加されたURLに戻ってしまう。

パラメーター部分を消してENTER、つまり直接URLを入力すれば初期状態からスタートする。

改竄に対して

上記コードで、Chromeの検証ツールでinput要素のname属性を改竄した場合、元のisset($_GET['get_input'])が存在しなくなるのでチェックが必要。

まとめ

処理の流れ

初回起動時

  • ファイルを最初に実行する場合はGETメソッド
  • 初期起動時の$_GETは要素数0の配列

フォームからのGETメソッド

  • その後フォームからGETメソッドが実行されると、INPUT要素の内容がURLのパラメーターに付加されてページの最初から実行される

リロード時

  • ブラウザー機能でリロードしただけではURLはリフレッシュされず、直前のパラメーターで再実行される

GETのみの場合

処理全体を通してGETメソッドのみの場合、$_SERVERによるチェックは不要になる。

GET処理とPOST処理を併用する場合は、GET処理を切り分ける必要がある。

action属性

form要素のaction属性をaction="./get.php"と設定しても、リロード時には元のパラメーターが復活する。この属性はGETメソッドを指定したそのフォームからの送信でないと効果がない。

 

MYSQL – インポートできない

文字コード

ローカルにインストールしたMySQL/phpMyAdminからクラウド上の別のphpMyAdminにテーブルをエクスポート、インポートしようとしたところ、’Unknown collation: ‘utf8mb4_unicode_520_ci’でインポートできなかった。元のMySQLがVer8でインポート先がVer5だったためらしい。テキストのSQLの文字コード部分を変更して読み込み。

  • utf8mb4→utf8
  • utf8mb4_unicode_520_ci→utf8_general_ci

 

PHP/MySQL – トランザクション確認(PDO)

概要

PHPのオブジェクト型(PDO)でMySQLのトランザクションを確認。

トランザクション中の動作はデータベースステートメントには設定されるが、トランザクション終了後のコミット/ロールバックによって設定結果がデータベースに反映されるかどうかが決まる。

確認コード

  1. 5行目でトランザクションでコミットフラグをtrueにセット
  2. 通常モードで’one’を書き込み
  3. 14行目でトランザクション開始
  4. ‘two’, ‘three’を書き込み
  5. 25行目でコミット、トランザクション確定
    • 通常モードへは自動的に復帰

確認結果

以下、出力を見ながらトランザクションの動作を確認。

  • 通常モードでは普通に書き込み
  • トランザクション開始後、データベースステートメントの内容は指示通り設定
  • トランザクション終了後、データベース内容の変更が確認できる
  • 通常モード復帰後も普通に書き込み

以下は出力結果で、終了後のデータベースの内容は’one’, ‘two’, ‘three’, ‘four’となる。

次にコミットフラグを$commit=falseにすると、commit()メソッドではなくrollback()メソッドが実行され、実行結果は以下のようになる。

  • 通常モードで普通に’one’が書き込まれる
  • トランザクションに入り、データベースステートメントには’two’, ‘three’が設定される
  • トランザクション終了後にロールバックされると、データベースステートメントがデータベースに反映されてもトランザクション中の’two’, ‘three’は書き込まれない
  • 通常モードに復帰後’four’が書き込まれる

 

PHP/MySQL – トランザクション確認(mysqli)

概要

PHPの手続き型(mysqli)でMySQLのトランザクションを確認。

トランザクション中の動作はデータベースリンクには設定されるが、トランザクション終了後のコミット/ロールバックによって設定結果がデータベースに反映されるかどうかが決まる。

確認コード

  1. 7行目でトランザクションでコミットフラグをtrueにセット
  2. 通常モードで’one’を書き込み
  3. 20行目でトランザクション開始
  4. ‘two’, ‘three’を書き込み
  5. 33行目でコミット、トランザクション確定
  6. 41行目で通常モードに復帰

確認結果

以下、出力を見ながらトランザクションの動作を確認。

  • 通常モードでは普通に書き込み
  • トランザクション開始後、データベースリンクの内容は指示通り設定
  • トランザクション終了後、データベース内容の変更が確認できる
  • 通常モード復帰後も普通に書き込み

以下は出力結果で、終了後のデータベースの内容は’one’, ‘two’, ‘three’, ‘four’となる。

次にコミットフラグを$commit=falseにすると、msqli_commit()ではなくmsqli_rollback()が実行され、実行結果は以下のようになる。

  • 通常モードで普通に’one’が書き込まれる
  • トランザクションに入り、データベースリンクには’two’, ‘three’が設定される
  • トランザクション終了後にロールバックされると、データベースリンクがデータベースに反映されてもトランザクション中の’two’, ‘three’は書き込まれない
  • 通常モードに復帰後’four’が書き込まれる

 

PHP – PDOによるデータベース操作

概要

PDO(PHP Database Object)によるデータベース操作は、手続き型に比べて、異なるDBMS間の際を隠蔽・吸収してくれるほか、セキュリティー対策も組み込まれている。

基本の流れ

PDOの最も基本的な流れは以下の通り。

  1. ユーザー情報やデータベース情報からPDOオブジェクトを生成する
  2. PDO::query()メソッドにSQLクエリーを渡してPDOStatementオブジェクトを得る
  3. PDOStatementオブジェクトからデータをフェッチする

例外処理などを無視した骨格は以下の通り。

メソッド

PDO::__constructor

PDOのコンストラクター

public PDO::__construct ( string $dsn , string $username = ? , string $passwd = ? , array $options = ? )

dsn

データソースネーム(Data Source Name)。DBMS名やホストなどの情報を文字列で指定する。たとえばlocalhostのMySQLを文字セット・データベースまで含めて指定する場合は以下のように記述する。

'mysql:host=localhost;charset=utf8mb4;dbname=databasename'

charsetで文字コードセットをしている点に注意。

$options

PDOクラス定数と用いた連想配列で指定する。たとえばエラーを例外としてthrowさせたい場合は以下のように指定する。

array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)

PDO::query

クエリー文字列を与えて、検索結果をPDOStatementオブジェクトとして受け取る。

PDOStatement::fetch()

検索結果を取り出す。一般的なのは、while文の条件の中でfetch()メソッドの結果を取り出して、全レコードについて処理を行うケース。以下の例では、クエリーによって抽出された都道府県と市町村を連想配列の配列として格納する。

PDO::prepare

PDO::query()による方法は、SQLステートメントがそのまま実行されるためセキュリティー上脆弱。

PDO::prepare()によるプリペアードステートメントとbindValue/bindParamによる値や変数のバインドによれば特定文字のエスケープが行われるため、こちらを使うべき。

PDO::lastInsertId

最後に登録されたレコードのIDを返す。MySQLの場合引数は不要。戻り値はstring。

雛形

PDO::query

レコード数のカウント

SQLのCOUNTの結果1行からデータを読む。以下の例では、id列をカウントした結果が1行で返されるのをfetchColumn()でカラム指定してデータを取得している。

列の全データの取得

検索したい列を抽出し、PDOStatement::fetchAll()で配列として取り出す。以下の例ではprefカラムの全データを取り出し、配列$pref_nameに格納している。

複数列データの連想配列への格納

以下はクエリーの結果を格納する方法の一つ。各レコードをカラム名をキーとした連想配列とし、それを1つの配列に収めている。

例外処理

PDOに例外をthrowさせるには、コンストラクターで以下のようにクラス変数で指定する。

トランザクション

3つのメソッドで簡明に処理できる(PDOによるトランザクションの確認)。

commit()メソッド、rollBack()メソッドはbeginTransaction()が成功していないと例外になるので注意。

beginTransaction()はトランザクションが開始できない場合に例外を投げる。

PDOによるトランザクションの確認はこちらを参照

 

インストール各種

Windows10へのインストール

PHP

20210105

ダウンロード・インストール

  1. php.netのdownlodasページへ
  2. Current Stable PHPのWindows downloadsリンク
  3. VC15 x64 Non Thread SafeのZipファイルをダウンロード
    • 7.4.13
  4. 任意のフォルダーにzipファイルの内容をコピー

設定

  1. コントロールパネル…システム詳細で環境変数PATHにPHPへのパスを追加
  2. php.ini
    1. php.ini-developmentファイルかphp.ini-productionをコピーしてファイル名をphp.iniに変更
    2. extension_dir = "ext"(相対パス or 絶対パス)
    3. 必要な;extensionsのコメントを外す(あるいは確認する)
      • extension=mbstring
    4. ;date.timezoneのコメントを外して日本のタイムゾーンを指定する
      • date.timezone = Asia/Tokyo

PHPサーバーの起動

コンソールで以下を入力

サーバーの収量はCTRL-C

MySQL

202101015

ダウンロード・インストール

  1. MySQLのダウンロードページへ
  2. MySQL Installer for Windowsへ移動
  3. Windows (x86, 32-bit), MSI Installerをダウンロード
    • 8.0.22/405.2Mファイル版
  4. Developper Defaultを選択
  5. 途中、Visual C++ Redistributable for Visual Studio 2019が必要になるのでインストール(一部manualのものは無視)

 初期設定

  1. Type and Networkingダイアログ
    1. Development machineを選択
    2. TCP/IP、PORT:3306のままNext
  2. Accounts and Rolesダイアログ
    1. rootのパスワードを設定してNext
  3. Windows Serviceダイアログ
    1. Configure MySQL as a Window Serviceはチェック
    2. Start the MySQL Server at System Startupのチェックをはずす
    3. 「手動」にはなるがWindows起動後のport listeningでMySQLサーバーも動き出してしまう
    4. Standard System Accountを選択したままでNext
  4. 以降Next/Finish
  5. Connect to Serverダイアログ
    1. ユーザー名rootで設定したパスワードでcheck
    2. 問題なければ以降Nexzt/Finish

PHP設定

  1. php.iniのextension=mysqliのコメントを外す

起動確認

  1. MySQLのCommandl Line Clientを実行
  2. rootパスワードを入力
  3. 終了はexit

phpmyadmin

20200106

ダウンロード・インストール

  1. phpmyadmin.netのサイトへ
  2. 最新版のDownloadをクリックしてファイルをダウンロード
  3. サーバーのドキュメントルートにmyphpadminディレクトリーをつくり、zipファイルの内容をコピー

起動

  1. サーバー起動/実行中確認
  2. ブラウ/\ザーにURL入力してphpmyadminを起動
    • http://localhost:8000/phpmyadmin/ など
    • 最後のバックスラッシュ/は必須らしい
  3. MySQLのユーザー名とパスワードを入力