PHP7技術者認定初級試験に合格しましたので その勉強方法等、これから受験する方に向けての記事です。 要点だけまとめましたので試験前にさらっと確認すると良いかと思います。
下記の公式問題集に沿って要点をまとめてみました。 今回は7章から9章になります。 下記のテキストをやり込めば合格は確実です。
1章から6章はこちらで解説しました。
7.ユーザとの情報交換:Webフォームの作成
8.情報の保存:データベース
9.ファイルの操作
7.ユーザとの情報交換:Webフォームの作成
フォームを利用する場合<form>タグを使います。
phpにてフォームデータを利用する場合$_POST配列、$_GET配列を用います。 簡易的な入力フォームを作ってみましょう。 入力ボックスの中に入力した文字が表示される簡易的なものです。
以下コードです。 とくに大切なことは9行目のmethod = “post” です。 $_POST[]にて入力ボックスの中に入力した文字を渡す(サブミットする)ことができます。 どこに渡すかと言えばaction = “”になります。 “”の中に渡す先のファイル名を記載します。 “XXXXX.php”みたいな感じです。 今回は何も記載していないので同じファイルに渡すということになっています。10行目の name = “your_name” に入力ボックスの中に入力した文字が格納されます。17行目の$_POST[“your_name”] をechoして表示しています。
次は複数の値を渡す(サブミットする)入力フォームを作ってみましょう。 下記サンプルフォームです。 RED、BULE、GREENを選択して送信を押下しました。
以下コードです。 特に大切なのは11行目の<select name = “color[]” multiple> 複数の値を渡したい場合はcolor[]のように配列にします。 23行目から25行目にて表示しています。
フォーム内にタグやJavaScriptを含むデータをWebサーバに送信することで意図しない動作をさせる攻撃をクロスサイトスクリプティング攻撃 と言います。
クロスサイトスクリプティング攻撃 を防ぐためにstrip_tags()関数やhtmlentities()関数を利用します。
サーバ変数とはphpが稼働しているwebサーバーに関する情報を提供します。 $_SERVERにて表します。
$_SERVER [‘PHP_SELF’]は現在実行されているファイルパスを取得します。
$_SERVER[‘REMOTE_ADDR’]はwebサーバにリクエストしているユーザのIPアドレスを参照可能です。
$_SERVER[‘REMOTE_HOST’]はwebサーバにアクセスしているホストの名前を示します。
$_SERVER[‘REMOTE_PORT’]はユーザからwebサーバへ通信する際に使用されているポート番号を表します。
$_SERVER[‘REMOTE_USER’]は認証されたユーザ名を表します。
サブミットしたデータに半角スペース以外の値が入力されているか判定します。 trim()関数で文字列前後の半角スペースを削除し、strlen()関数で要素の長さを検証します。 文字数が0であれば入力を促し、0でなければ列前後のスペースを削除した入力データを表示します。下記サンプルコードです。
サブミットしたデータが整数か浮動小数点かを判定します。 filter_input()関数を用います。 INPUT_POST,”id”が$_POST[“id”]と同義になります。 FILTER_VALIDATE_INTにて整数かどうかの判定になります。 整数であればtrueを返します。 if文にてnullもしくはfalseであればtureとなりErrorが表示されます。 またarray(“options” => array(“min_range” =>0,”max_range” =>100000))にて値の範囲を指定できます。 そのため100001以上の数値を入力するとエラーとなります。
8.情報の保存:データベース
データベースを利用するにはデータベース管理システム(DBMS)を用います。
データベースを操作するにはSQLを用います。
SQLは基本的なものにINSERT、UPDATE、DELETE、SELECTがあります。
新しい表を作成するにはCREATEを利用します。
PDOとはデータベース接続用のクラスになります。 拡張モジュールでありデータベースの種類にかかわらず、利用が可能です。 ※クラスとは役立つ道具を持つ道具セット とらえると良いかと思います。 PDOはデータベースを制御するために必要な道具(機能)が一式揃っています。 クラスはnewして使う という決まりがあります。 newすると分身ができあがって、その分身をインスタンスと呼びます。 6行目が$dbが分身ですね。
PDOクラスを用いてデータベースへ接続するには以下のように記述します。 PDO(“データソース名”、”ユーザ名”、”パスワード”) 同じく6行目がそれです。 データソース名はmysql:host = XXXXXX;dbname = XXXXXXのように記述します。 5行目になります。
道具セットのPDOクラスの道具であるqueryメソッドを利用してみます。 11行目、$db->query($sql);と記述します。 ->はアロー演算子と言われます。 queryメソッドを利用するとPDOStatementというクラスのインスタンスができあがります。 ※道具セットの道具を用いて別の道具セットの鍵を開けるみたいなイメージでしょうか。 別の道具セットのインスタンスが$qになります。
$qの道具であるfetchメソッドを用います。 $q->fetch();となります。14行目。 fetchメソッドはテーブルから1行ずつ順番に取り出すことができます。 取り出した行を$rowに格納して、値があれば(trueなら)16行目の処理を実施します。 fetchメソッドは取り出した値が何もないならfalseとなりますのでwhile文を抜けます。 ※行全体を取得する場合はfetchAll()メソッドを用います。
テーブルに新規行を追加する場合、INSERT INTO テーブル名 VALUES(値1,値2,・・・); のように記述します。
1部の列のみ追加したい場合、INSERT INTO テーブル名(列名) VALUES(値); のように記述します。
テーブルデータを更新する場合、UPDATE テーブル名 SET 列名=値 WHERE 条件; のように記述します。 条件は、例えばID=1000のようにしてIDという列の値が1000の行をUPDATE する。ということになります。 下記のようなテーブにてシンプルな消しゴム→豪華な消しゴム へ変更するなら UPDATE goods set GoodsName=’豪華な消しゴム’ where GoodsID=1000;となります。
※whereの指定を忘れるとすべてが変わってしまいます。 注意してください。 UPDATE goods set GoodsName=’豪華な消しゴム;
DELETEを利用するとテーブルから行を削除することができます。 DELETE FROM テーブル名 WHERE 条件; のように記述します。 先ほどすべて豪華な消しゴムとなってしまったテーブルからPriceが2000以下のものを削除してみましょう。 DELETE FROM goods WHERE Price <= 2000;
※whereの指定を忘れるとすべて削除されてしまいます。
テーブルデータを取得する場合、SELECT文を用います。 すべてのデータを取得したい場合、下記のように記述します。 SELECT * FROM goods;
次にGoodsIDが1001と1002のものだけ取得します。 SELECT * FROM goods WHERE GoodsID = 1001 or GoodsID =1002;
次にPriceを基準に昇順に並べ替えてすべてのデータを取得します。 SELECT * FROM goods ORDER BY Price; ※逆、降順にしたい場合はPriceの後にDESCを加えます。 また取り出す行数を制限したい場合、LIMIT句を使います。 最初の2行を取り出す場合↓ SELECT * FROM goods ORDER BY Price LIMIT 2;
PDOクラスにはプリペアドステートメント と言われるセキュリティ対策の機能が付属しています。 まずサイバー攻撃とはどういうものか解説します。 あるインターネットショッピングサイトで個人情報を登録するとします。 下記の利用者様がいます。
ショッピングサイトで登録情報を確認したいとします。 大抵のサイトは下記のような個人情報の閲覧ページがあります。 個人IDを入力することで登録情報を閲覧できます。 ※通常はパスワードの入力も必須ですが簡易的なものですのでご了承ください。
一般的には自身のIDを入力しますが、 悪意のあるユーザが以下のように入力するとします。 1000 or 1 = 1 すると以下のように出力されます。 登録されているすべてのユーザー情報が出力されてしまいました。 なぜこのようなことがおきるのでしょうか?
ソースコードをみてみましょう。 特に重要なのは30行目のユーザが直で入力した値が$idに格納されています。 その$idが直でSQL文に挿入されている点です。33行目。 そのため1000 or 1 = 1がそのまま挿入されてselect * from person where ID = 1000 or 1 = 1が実行 されています。 whereというのは条件 です。 つまりIDが1000もしくは 1 と 1 が等しいもの という条件を指定しているのです。 1 と 1 が等しいというのは未来永劫変わらない事実ですのですべて真となりますので すべての行が出力されてしまいます。
このように不正にDBを操作して意図しない情報を表示したりすることをSQLインジェクション といいます。 こうした不正を防ぐためにプリペアドステートメント があります。 ようやく本題ですね。 お疲れ様です。
プリペアドステートメントを利用する前が コメントアウトした33行目~35行目になります。 プリペアドステートメントを使用した37行目と41行目です。 ユーザが入力した値を直でwhereに挿入するのではなく、? としています。 ? に入力したい値を配列にしておきます。39行目。 ※ ? をプレースホルダといいます。 query()でなくprepare()メソッドを利用します。 プレースホルダを利用するためです。 40行目のexecute()メソッドによってプレースホルダに代入すべき値を指定します。 また=のようなPG中で利用する特殊文字をただの文字として 扱ってくれます。 ※エスケープ処理といいます。
以上の処理の流れをプリペアドステートメントと呼びます。 テスト対策でも重要ですが、 実務において非常に大切ですので詳しく解説致しました。 1000 or 1 = 1と入力してみましょう。 何も表示されませんね。
9.ファイルの操作
ファイル全体内容 を処理する場合、読み込みではfile_get_contents()関数を利用します。 以下のようなテキストファイルをphpファイルの同階層に保存します。
以下のように表示されればOKです。
書き込み処理はfile_put_contents()関数を利用します。
以下のようなファイルが出来上がります。 ファイルが存在しなけばファイルを作ってくれます。
※file_get_contents()、file_put_contents()関数共にリモートファイル(ネットワーク上のファイル)も読み書 き可能です。 ※file_get_contents()関数ではHTMLで構成されたweb画面から必要な情報を抽出するスクリーンスクレイ ピングが可能です。
次はファイルの部分的な 処理をする場合です。 まずはファイルへの接続をオープンにするためfopen()関数を用います。 1番目の引数にファイル名、2番目はファイルモードで、ファイルに対する操作を指定しています。 rbは読み込みを意味しています。 fopen()関数はファイルへの接続が可能になった。 という情報を返します。 ※その情報はファイルポインタ と呼ばれます。 そのためfile_get_contents()と同様にecho $fileとしても中身が表示されるわけではありません。 次にfgets()関数を用いてファイルから1行を読み込んで 文字列を返します。 引数はファイルポインタを指定します。 fclose()関数で接続をクローズします。 よって指定ファイルの1行目が表示されます。
複数行の記載がある場合は以下のように記載することで最終行まで表示ができます。 4行目、$text = fgets($file);にて1行目のデータが取得できます。 for文の第3引数の$text = fgets($file);によって次の行のデータを取得します。 ※fgets()関数は自動的に行のカウントアップが行われます。 !feof($file);が繰り返しの条件になります。 feof()関数ではカウンターが末端かどうかをチェックします。 末端であればTrueを返します。 つまり!feof($file)ということは、Trueでないということです。Trueでないなら繰り返す ということですので、末端になるまではecho $text.”<br>”;を続けます。
以下のようにすべてのデータが表示されます。
カンマ区切りのCSVファイルを読み込む場合はfgetcsv()関数を利用します。 下記のようなCSVファイルを読み込みます。 ファイル名 = names.csv
fgetcsv()関数は下記のように配列で返してくれます。
コードは下記になります。 先ほどのfgetsをfgetcsvに書き換えています。 また配列を出力しますのでvar_dumpを利用します。 echo(‘<pre>’); echo(‘</pre>’); で囲っているのは単純に見やすくするためです。 ※ちなみにvar_dump($text);をfor文の外で行うと出力されません。 なぜなら$textは空だからです。
リダイレクトさせる場合にはheader()関数を利用します。 例えばログインしていないにもかかわらず、URLを直接打ち込んでアクセスしてきた場合に リダイレクトさせます。 書き方は以下のようなります。 header(“Location: ※リダイレクトさせたいURLを記述する”); 例 header(“Location: https://fukutakublog.com”); その他、ファイルダウンロードにも用いられますので覚えておきましょう。
ファイルが読み込み可能かどうかはis_writable()関数を利用します。 読み込み可能であればtrueを返します。 読み込み不可の場合はfalseとなります。 その他、書き込み可能かを判定するis_writable()関数、ファイルが存在するかを判定するfile_exists()関数があります。
file_get_contents()、fgets()関数は読み込みに失敗するとfalseを返します。 またtest.txtに何もデータがない場合、file_get_contents(“test.txt”)は文字列のfalseを返します。 そのため読み込みが失敗していないにも関わらずcouldn’t readが表示されてしまいます。
そのため、下記4行目のように同値演算子[===]を用います。 条件判定でのfalseはboolean型であるため、[===]演算子では型も含めて一致した場合にTrueと判定されることになります。
最後にディレクトリトラバーサルというサイバー攻撃のお話です。 Webサーバ内のファイル名を直接指定している場合、URLを書き換えることで意図していないファイルにアクセスする攻撃手法のことを指します。
お疲れ様でした。 中編は以上になります。 参考書籍は下記になります。 本サイトでは筆者が大切と思う要点だけまとめただけですので 合格のためには下記書籍をやり込んでください。