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()でカラム指定してデータを取得している。

あるいはPDO::rowCount()メソッドを使ってもよい。この場合はSELECTで何かのカラムを読み込めばよい。

列の全データの取得

検索したい列を抽出し、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のユーザー名とパスワードを入力

 

PHP – 雛形 – 入力された内容を残す

概要

普通にHTMLのinput要素などを書くと、GETやPOSTのたびにそれらがvalueなしで描きなおされるので、内容が空になる。これに対してsubmit後に元に入力した値が残るようにする手順。

普通に書くと消える

以下のコードでは、送信ボタンを押すと入力した内容が表示されるが、テキストボックスの内容は毎回消えてしまう。

これはinput要素のvalue属性がないため、POSTのたびに再描画されるときに要素が空として描かれるため。

valueを設定すると値を残せる

input要素のvalue属性に前の入力内容を渡せば、その内容で要素が描かれるため値が残る。

  • POSTされた際にPHPコードの変数は初期状態に戻る(undefinedか初期設定値に戻る)
  • ただしHTMLのinput要素が再描画されるまでは、その要素の内容は残っている
  • そこで、正常に入力が取得された場合にはinput要素のvalue属性の値に入力された値を渡せば、描画時にその値が残される

ただし、GETやPOST後の状態によってvalueにセットする変数がundefinedだとエラーになるため、どのような状態でも変数が定義済みとなるようにしておく必要がある。

以下のコードでは、POSTされた場合はisset()がtrueかfalseかそれぞれの場合に、POSTされずに実行された場合(最初に実行された場合など)にvalueにセットする値を定義している。

エラー処理などで値を残す

GET/POSTされた値の内容によってエラーとする場合にも、エラーとなったその値を残しておける。コード実行の最初にinput要素から取得した値を変数に持っておいて、その内容のままvalue属性の値として渡せばよい(もちろん例外対応は必要)。

以下のコードは、数値入力欄が数値以外の場合エラーとしているが、その入力内容はテキストボックスに残る。

 

PHP – 雛形 – MySQLのクォート

概要

SQLでは一般にシングルクォート(')やダブルクォート(")で文字列を囲う。

テキストの内容としてクォートを含む場合、そのまま記述したりテキストボックスの入力内容をそのまま使ってしまうと文字列境界との区別がつかず、エラーが発生してしまう。

そこでSQLデータの書き込み時に、SQLとして適切に解釈可能なようにエスケープする必要がある。

シングルクォートのエスケープ

SQLエスケープ

SQL標準では、シングルクォートを文字として扱う場合にクォートを2つ連続させる('')

PHPからSQLを操作する際にシングルクォートを含む文字列をリテラルとして扱う場合、以下のような方法がある。

  1. query文字列をダブルクォート(")で囲う
  2. テキストリテラルをシングルクォート(')で囲う
  3. テキストリテラル中のシングルクォートはこれを2回続けて('')SQL標準でエスケープする

定義済み関数によるエスケープ

PHPの文字列として扱う場合、シングルクォートをバックスラッシュでエスケープすることができる(\')。この場合、リテラルの解釈後には1文字のシングルクォートとして扱われる。また、テキストボックスに入力された文字列にクォートが入っているケースも考えられる。

ところで、このような文字列をそのままquery構文に渡してしまうとSQLが文字列境界として扱うので不都合が生じる。そこで、PHPに準備されたエスケープ用の関数を使う。この関数の手続き型の構文は以下の通り。

$escaped_string = mysqli_real_escape_string($dblink, $original_string);

第1引数にmysqli_connect()で得られるデータベースリンクが必要な点に注意。

たとえばターゲットの文字列をPHPの変数として扱う場合、以下の手順が考えられる。

  1. クォートを含む可能性がある文字列をmysqli_real_escape_string()関数でエスケープする
    • リテラルとして文字列を準備する場合は、シングルクォートで囲い、文字列中のシングルクォートをバックスラッシュでエスケープする
  2. queryに文字列変数を渡す際に
    1. 文字列変数の内容がシングルクォートで囲われるようにする
    2. そのため、文字列前後の構文をダブルクォートで囲う

ダブルクォートのエスケープ

ダブルクォートもSQLでは文字列境界として扱われるので、queryの構文中にリテラルで書くとエラーとなる。

テキストボックスなどからの入力の場合はそのままmysqli_real_escape_string()でエスケープするといいが、リテラルの場合は全体をシングルクォートで囲ってやるとよい。

読み込み時

エスケープされた文字列がSQLで保存されると、クォートが1つずつの文字列として記録されている。それらを含むテキストをフェッチして変数に代入すると、適正に表示される。

 

PHP – 雛形 – MySQL操作(mysqli)

概要

PHPからデータベースを操作する手続きの大枠は以下の通り。

  1. DBサーバー・DBに接続してDBリンクを取得
    $db_link =mysql_connect()
    if($db_link)で接続成功/失敗処理

  2. 文字コードを設定する
    mysqli_set_charset()
  3. query文字列によりDBから絞り込んだデータを取得
    mysqli_query()
    →処理内容によって戻り値に注意
  4. DBから1レコードずつ取り出す
    mysqli_fetch_array()/mysqli_fetch_assoc()
  5. レコード内のカラムデータをキーを介して利用
    →カラム名をキーとした連想配列など
  6. SELECTなど結果セットがある場合はメモリーを解放(INSERTの場合は不要)
    mysqli_free_result()
  7. データベースリンクをクローズ
    mysqli_close()

データベースを最初に指定する場合

MySQLに接続後にDBを選択/変更する場合

 

PHP – str_replace~文字列の置換

概要

str_replace()は文字列中の対象文字列を指定した文字列に置き換える。

str_replace($search, $replace, $string);

$searchは置き換えられる文字列、$replaceは置き換える文字列、$stringは対象文字列。

基本形

文字列の変換

以下の例は、対象文字列中の’ab’を’AB’に変換している。

半角スペースの削除

以下の例では、文字列中の半角スペースを全て削除している。trimと異なり、文字列中のすべてのスペースを削除。

全角スペースの削除

全角スペースを削除する例。

全角文字の置換

全角文字も問題なく検索・置換できる。

複数文字列の置換

複数の文字列の同一文字列への置換

第1引数を文字列の配列にすると、各要素文字列の何れかに該当すれば第2引数に置き換えられる。

これを利用して、文字列が半角スペースと全角スペースだけで構成されていないかチェックができる。

if (str_replace([' ', ' '], "") === '') {}

複数の文字列セットの置換

第1引数と第2引数を配列にすると、対応する要素によって置換される。