Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # PHP基礎について
- ## 変数について
- - `$変数名`で変数を表す。
- - 型表示はしなくて良い。入れるデータによって型が変換される
- - 可変変数
- `$$変数`ある変数に格納された文字列を別の変数の識別子と認識し、その識別子にアクセスする方法
- 例
- ```php
- <?php
- $var = 1;
- $var_name = 'var';
- echo $$var_name , PHP_EOL; //1が出力される
- ?>
- ```
- `var_name`にvarの文字列が入っており、$$をすることで`$var_name`が`$var`となり、1が出力される結果となる。
- - グローバルスコープとローカルスコープ
- - グローバルスコープ
- phpブロック`<?php ?>`の中はグローバルスコープとされ、別のPHPブロックや、別のファイルでグローバルスコープに定義された変数は
- 同じようにグローバルスコープで使うことが出来る。
- PHPにはブロックスコープ(<?php ?> ごとの定義の範囲のこと)は存在せずブロックを抜けた後でも定義された変数を使うことが出来る。
- - ローカルスコープ
- 関数やクラスのメソッド内のスコープのこと。このスコープではグローバルスコープなど、その関数やメソッドの外側で定義された変数にはアクセス出来ない。
- 例)
- ```php
- $foo = 1;
- function example function() {
- $foo = 10; //グローバルスコープのfooではなく、ローカルスコープで新しく定義されたfooになる
- $bar = 20;
- }
- some_function();
- echo $foo , PHP_EOL; //1
- echo $bar , PHP_EOL; //エラー 値が入っていない。
- ```
- もしローカルスコープ内でグローバルスコープの値を参照したい場合は先頭に`global`をつけると参照できるが、
- ローカルスコープないで変数が変化しないとは限らないので`global`は極力避けたほうが良い
- ## 型
- - 型の種類
- PHPには全部で8種類の型が存在する
- 1. 整数型 (int)
- 2. 浮動小数点数型 (float,double)
- 3. 文字列(string)
- シングルクォートの場合、エスケープシーケンスは展開されない。ダブルクォートは展開される。
- 4. 論理型 (true,false)
- 5. 配列型
- 連想配列と普通の配列(明示的に添字配列)は区別されていない。
- 6. オブジェクト型
- 7. リソース型
- 8. null型
- ## 型変換
- - 方の明示的なキャストと関数
- | 型 | C言語風のキャスト | 変換関数 |
- |:-----------|-------------------------:|:--------------------------:|
- | This | (bool),(boolean) | - |
- | column | (int), (integer) | intval() |
- | will | (float),(double),(real) | floatval(),doubleval() |
- | be | (string) | strval() |
- | left | (array) | - |
- | aligned | (object) | - |
- - 自動キャストの発生条件
- - 異なる方同士で演算を行う場合
- - 演算子、制御構造、関数やメソッドが特定の型の引数を必要としており、それとは異なる型を渡した時
- 関数の中に違う型が渡され、その関数ではその型がサポートされていない場合、警告が発生する。
- - 自動キャストの危険性
- 比較演算子を用いて、文字列'0'と'0.0'が等しいかどうか判定するプログラムを書いたとする。
- ```php
- if ('0' == '0.0'){
- echo '文字列は正しいです';
- }
- else {
- echo '正しくないです';
- }
- // 文字列がは正しいです と出力されてしまう。
- ```
- これは数値らしい文字列を整数型と浮動小数点型に変換し、
- 整数型と浮動小数点型を合わせるために自動で整数型に変換して比較したためである。
- このようなプログラムは危険性をはらんでいる。
- 例えばユーザ登録の際に、パスワードを確認のために2回入力する時に一致しているかの判定。
- ユーザが0123を入力し、確認用に123を入力してしまったら、0123を入力したのに登録した際には0123で登録されてしまうことがある。
- - ===と!===
- 2つの演算子は`==`と`!=`とほぼ一緒の役割だが、比較対象の型が違う場合、キャストされないので、型が違うとtrueかfalseを出力される。
- これにより、上記の問題を解決することが出来る。
- ## 型変換の注意
- webアプリケーションの場合、クライアントから送信された値は数値であろうと文字列であろうとすべて文字列型になる。
- しかし、PHPでは比較演算を使った自動キャスト等が行われるが、お作法的によろしくない。
- そこで、引数として期待している値の型が決まっている場合は明示的にキャストを行い、厳密な比較演算子(===)を使うと安全
- ## 論理型
- PHPでは、なにか値があるものはほとんどがtrueとされる。
- PHPがfalseと判断する要因は7つ
- - false(論理型)
- - 0(整数型)
- - 0.0(浮動小数点型)
- - 空の文字列("")、文字列のゼロ("0")
- - 要素の数がゼロの配列
- - null(値がセットされていない変数を含む)
- - からのタグから作成されたSimpleXMLオブジェクト
- ## ヒアドキュメント
- - ヒアドキュメントとは?
- ヒアドキュメント構文`<<<`のあとに終端識別子(EOI等)を定義し、終端識別子が出現するまで文字列とする。
- 終端識別子は必ず行頭から始まり、直前に空白(インデント)を含めず、すぐに改行する必要がある。
- ヒアドキュメント内で使用する変数はそのまま`$変数名`で置き、配列やメンバ変数などは`{$変数名[キー]}`のように、
- {}で囲む。
- 例)
- ```php
- $foo = 10;
- $text = <<< EOI
- ヒアドキュメントではこのように
- 複数行に渡る文章をそのまま表示することが出来る。
- ちなみに"$foo"の中身は$fooである。
- EOI;
- //ちなみに"$foo"の中身は10である。 と出力される。
- ```
- ## マジック定数について
- - マジック定数とは?
- その定数が記述された場所によって動的にその値が変化する定義済み変数
- | マジック定数 | 意味 |
- |:---------------------|----------------------------------------------------:|
- | `__FILE__` | ファイルの名前とフルパス |
- | `__DIR__` | そのファイルの存在するディレクトリ名 |
- | `__LINE__` | そのファイル上の行番号 |
- | `__FUNCTION__` | 関数名 宣言時の関数名を大文字小文字区別して返す |
- | `__CLASS__` | クラス名 宣言時の関数名を大文字小文字区別して返す |
- | `__METHOD__` | メソッド名 宣言時の関数名を大文字小文字区別して返す|
- | `__NAMESPACE__` | 現在の名前空間の名前 |
- ## PHPの変数命名規則について
- スネークケースが一般的だが、最近のトレンドとしてキャメルケースを用いることが多い。
- キャメルケースを使いましょう。
- ## エラーケースについて
- PHPの実行時にエラーが発生するが、エラーの種類は大きく分けて4つある
- - Parse error, Syntax error
- 構文に何かしらのミスが有るときにエラーを吐く
- - Fatal error
- 実行が停止するエラー
- 定義されていない関数を呼びだそうとした時などに発生する。
- - Warning, Notice
- 注意、警告はするが、実行されるエラー
- - 何も表示されない
- 構文等にはエラーはないが、実行された結果がそぐわない時
- ## htmlとの連携
- - formについて
- `<input>`タグの`name`属性をPHPが操作する。ここは設定しなければならない
- - hiddenタグの使いドコロについて
- データを何処かのファイルを経由しながら移動したい時に使うと良い。
- 特に経由ファイルの中でデータ表示しなくていい場合に使う。
- - hiddenタグのvalueについて
- valueには渡したいデータが入るのだが、変数を渡さなければならない時は、
- valueの値に `.$変数名.`で変数の両脇に結合演算子を入れてやると良い。
- 無いとエラーになるので注意
- - ラジオボタンやチェックボックス、リストボックスの値取得
- これらの入力した値はvalue属性に入っているので、valueを変更すると良い。
- - checkboxなどの複数選択可の場合の処理
- 複数選択の値を出力させるにはhtml側とPHP側に工夫が必要
- - html側の処理
- name属性に`データ名[]`と入力する。これにより、PHP側に配列として渡される。
- 配列には順番に内容が格納されていく。
- フォームに記入された内容はもともと、配列として格納されているので、配列の配列として格納される。
- - PHP側の処理
- foreach文を使って格納された配列を他の変数に格納して表示する。
- ## 文字列の連結について
- - 文字の連結は`.`で連結する
- ## シングルクォートとダブルクォートの違い
- `'`は文字列がそのまま出てくるが、`"`だと変数の内容が表示される。
- 一般的にどちらを使っても良いが、クォートが重なるときはわかるように区別しながら書くと良い
- 自分的にはどちらかを統一して書いたほうが綺麗で読みやすいと思う
- - クォーテーションの使い分け
- `print 'I'm studying'`などの省略形を入れるとシングルクォートが入るのだが、
- この時に文字列を囲むシングルクォートと省略形のシングルクォートがダブってエラーを起こしてしまう。
- そこで、次の2つの方法を使ってシングルクォートを回避する。
- 1. `"`を使う方法 (これが一般的)
- `print "I'm studying";`
- 2. エスケープシーケンスを使う方法(どうしてもシングルクォートが使いたい場合)
- `print 'I\'m studying';
- ## エスケープシーケンスについて
- - エスケープシーケンスとは?
- \マークを記述するとその直後の記号はPHPの要素として無視されるようになり混ぜることが出来る。
- - エスケープシーケンスの種類
- | エスケープシーケンス | 意味 |
- |:---------------------|-------------------:|
- | \n | 改行 |
- | \r | キャリッジリターン |
- | \t | タブ |
- | \\\ | \ |
- | \$ | $ |
- | \" | " |
- | \' | ' |
- - PHP_EOLとは?
- php側で自動的に改行を行ってくれる定数である。`echo 'aaaaa', PHP_EOL;`
- ## クロスサイトスクリプト対策について
- - クロスサイトスクリプトとは?
- ウェブページの入力部分をアプリケーションがオウム返しすることによって生成するアプリケーションの性質を利用して悪意のあるスクリプトを注入する攻撃のこと
- つまり、フォーム入力などユーザが入力できる部分で悪意のあるユーザがスクリプトを入力し、送信することを指す。
- - 対策方法(サニタイジングという)
- 入力フォームに入る変数に対して`htmlspecialchars($変数名,ENT_QUOTES)`をつけてやると文字列を実行せずそのまま表示されるようになるので良い。
- ちなみに`ENT_QUOTES`は定数扱いなので絶対にシングルクォートで囲まないこと。
- ## データベースとの連携について
- ### mysqli関数を使う方法
- - 連携ステップ
- 1. データベースに接続する
- 2. データベースエンジンにSQL文で命令を書く
- 3. データベースから切断する
- - 実際のコード
- ```php
- //データベース接続
- $db = mysqli_connect('ホスト名','ユーザ名','パスワード','データベース名');
- if(!$db){
- die(mysqli_connecet_error());
- }
- $db = mysqli_set_charset('$db','文字コード');
- //SQLの実行
- mysqli_query('$db','SQL文') or die(mysqli_error($db));
- ```
- - 接続プログラムを共通プログラムにする
- まず、データベースに接続するプログラムを別に制作する。
- dbconnect.php
- ```php
- <?php
- $db = mysqli_connect('localhost','root','','mydb') or die(mysqli_connect_error());
- ?>
- ```
- 別のプログラムでそのデータベースに接続したいときは`require(dbconnect.php)`の関数を使うだけで接続が可能となる。
- このrequireは別のプログラムを指定して読み込む関数である。
- - データベースのデータを取得
- `$recodSet = mysqli_query('$db','SQL文') or die(mysqli_error($db));`をプリント表示しても何も表示されない。
- そこで`mysqli_fetch_assoc()`関数を使ってデータを取得する。
- ```php
- $db = mysqli_connect('ホスト名','ユーザ名','パスワード','データベース名');
- if(!$db){
- die(mysqli_connecet_error());
- }
- $db = mysqli_set_charset('$db','文字コード');
- //SQLの実行したデータを取得
- $recordSet = mysqli_query('$db','SQL文') or die(mysqli_error($db));
- $data = mysqli_fetch_assoc($recordSet);
- echo $data['フィールド名']; //フィールドにある1件目のデータのみ表示
- //フィールドのデータをすべて表示したい場合
- while ($data = mysqli_fetch_assoc($recordSet)){
- echo $data['フィールド名'];
- }
- ```
- `mysqli_query()`関数での戻り値は「レコードセット」と呼ばれるテーブルでの横軸を指すレコードが複数集まったものが帰ってくる。
- このレコードセットから1件のデータを取り出さなければデータとしては利用できない。
- `mysqli_fetch_assoc()`でこのレコードセットを1件ごとに連想配列に変換して取ってくる。
- 連想配列のキーはフィールド名に相当する。
- ### COUNTなどが出てきた場合の`mysqli_fetch_assoc()`
- 下記のレコードセットを取ってくる場合、連想配列名がめんどくさいことになってしまう。
- ```php
- $recordSet = mysqli_query($db,'SELECT COUNT(フィールド名) FROM テーブル名');
- $data = mysqli_fetch_assoc($recordSet);
- echo '件数は' .data['COUNT(フィールド名)]'. '件です'; //フィールド名にはSQLで計算した関数名が入るのでキーがめんどくさくなる
- ```
- そこで、このめんどくさいキー名を解消するためにSQLの`AS`を使ってフィールド名を変更してやる
- ```php
- //AS を使用し、変数名を簡潔にした
- $recordSet = mysqli_query($db,'SELECT COUNT(フィールド名) AS record_count FROM テーブル名');
- $data = mysqli_fetch_assoc($recordSet);
- //キー入力も簡単になった
- echo '件数は' .data['COUNT(record_count)]'. '件です';
- ```
- - フォームからの情報をSQLに保存する
- sprintfを用いて入力したデータの書式を整えてSQL文にする
- ```php
- $sql = sprintf('INSERT INTO テーブル名 SET フィールド名1 = %d, フィールド名2 = "%s", フィールド名3 = %d, フィールド名4 = "%s", フィールド名5 = NOW()',
- mysqli_real_escape_string($db,$_POST['maker_id']),
- mysqli_real_escape_string($db,$_POST['item_name']),
- mysqli_real_escape_string($db,$_POST['price']),
- mysqli_real_escape_string($db,$_POST['keyword'])
- );
- mysqli_query($db,$sql) or die(mysqli_error());
- ```
- ### PDO関数を使う方法
- - 連携ステップ
- 1. データベースに接続する
- 2. データベースエンジンにSQL文で命令を書く
- 3. データベースから切断する
- - 実際のコード
- ```php
- <?php
- //1. データベース接続
- $dsn = 'mysql:dbname=データベース名;host=ホスト名';
- $user = 'ユーザ名'; //mysqlで設定したユーザ名を入力
- $password = 'パスワード'; //mysqlで設定したパスワードを入力
- $dbh = new PDO($dsn, $user, $password);
- //2. データベースエンジンにSQL文で命令を書く
- $sql = 'INSERT INTO anketo(nickname,email,goiken) VALUES("'.$nickname.'","'.$email.'","'.$iken.'")'; //SQL文を書く
- $stmt = $dbh -> prepare($sql);
- $stmt -> execute();
- //3. データベースから切断
- $dbh = null;
- ?>
- ```
- - データ格納場所について
- $stmtの変数に(厳密には変数ではない)データが格納されている
- `$rec = $stmt -> fetch(PDO::FETCH_ASSOC)`
- これにより1タプルのデータを取得できる。
- その後に
- ```php
- <?php
- print $rec['属性名'];
- print $rec['属性名'];
- print $rec['属性名'];
- ?>
- ```
- とやればデータを表示することが出来る。
- ちなみにデータが取得できなくなるとfalseを返す
- ## SQLインジェクションについて
- - SQLインジェクションとは?
- SQLのデータを検索する際に入力フォームからSQL文を入力することで個人情報の不正取得や改ざんなどが行われる行為
- - SQLインジェクション対策(mysqli編)
- `mysqli_real_escape_string($db,'文字列')`を使ってsqlインジェクションを防ぐ
- この関数は危険な文字を無害化してくれる関数である
- - SQLインジェクション対策(PDO編)
- 1. 文字の連結をやめてデータを入れたい部分を?にする
- `$sql = 'SELECT * FROM テーブル名 WHERE 属性名 = ?`
- 2. データを別の変数に格納する
- `$data[] = $code;`
- 3. SQL文で命令を出すときにデータを格納した変数を指定する。
- `$stmt ->execute($data);`
- - 複数のデータを検索する場合
- 1. 文字の連結をやめてデータを入れたい部分を?にする
- `$sql = 'SELECT * FROM テーブル名 WHERE 属性名 = ? AND 属性名=?`
- 2. データを別の変数に格納する(配列なのでデータを何個でも格納できる)
- `$data[] = $変数名;`
- `$data[] = $変数名;`
- 3. SQL文で命令を出すときにデータを格納した変数を指定する。
- `$stmt ->execute($data);`
- ## エラートラップについて
- - エラー回避方法
- `try-catch`をすることでサーバーダウンなどのエラー時に別の処理を行うことが出来る。
- ```php
- <?php
- try{
- //本来の処理
- }
- catch (Exception $e){
- //エラー時の処理
- }
- ```
- ## 時刻表示について
- - 時刻表示の関数
- `date`関数を用いる。
- ```php
- date(フォーマット)
- date(フォーマット,タイムスタンプ)
- ```
- - 引数1つの時
- 現在時刻を指定したフォーマットで出力する
- - 引数2つの時
- 第2引数のタイムスタンプを指定したフォーマットで出力
- ```php
- <? php
- date_default_timezone_set('Asia/Tokyo');
- print date("Y/m/d" H:i:s") . '<br>';
- print date("Y/m/01") . '<br>';
- print date("Y/m/t") .'<br>';
- //日付と曜日を出力する
- $w = date("w");
- $week_name = array("日","月","火","水","木","金","土");
- print date("Y/m/d") . "($weekname[$w])\n";
- ```
- date関数を使うときは`date_default_timezone_set('Asia/Tokyo');`を必ず入力すること
- - date関数のパラメータについて
- | 引数 | 指定内容 |
- |:---------------------|------------------------------------------------:|
- | Y | 年を4桁で(一般的) |
- | y | 年を2桁で |
- | n | 月 |
- | m | 月で、1桁の場合、前に0をつける |
- | F | 月を英語表記 |
- | M | 月を英語の3文字表記 |
- | j | 日 |
- | d | 日で1桁の場合、前に0をつける |
- | w | 曜日を数字表記(日曜日=0,土曜日=6) |
- | H | 時間を24時間単位で、1桁の場合0を前につける |
- | h | 時間を12時間単位で、1桁の場合0を前につける |
- | i | 分で、1桁の場合前に0をつける |
- | s | 秒で、1桁の場合前に0をつける |
- ## 特別な変数について
- - フォームの送信方法 (get)
- getは「URLパラメータ」と呼ばれており、URLの後ろに`?=data`を表示する。
- データがURLで丸見えになってしまうので、メールでURLを配信、検索結果のURLを表示などに使う
- - フォームの送信方法 (post)
- データを隠して飛ばすことができる。
- このため、会員登録や問い合わせフォームに使用する。
- - $_GET
- formのgetの値をそのまま取得する変数
- formの値がpostの場合に`$_GET`をするとエラーを吐くので注意
- - $_POST
- formのmethodの値がpostの時に値を取得する変数
- formの値がgetの場合に`$_POST`をするとエラーを吐くので注意
- -$_REQUEST
- formのmethodの値がgetまたはpostの時に使えるオールマイティーな変数
- オールマイティーさ故に危険性がある。
- `$_GET`の代わりに`$_REQUEST`を使うのは問題ないが
- `$_POST`の代わりに使うとフォームから送信された内容をURLから上書きできるなど、かなり危険
- 特別な理由がない限り`$_GETか` `$_POST`を使い分けて使う
- ## 配列について
- - array
- 配列はarray関数を用いてデータを格納する。
- 配列のデータには予め番号が振っており、0から始まる。
- 配列の要素を追加する際は末尾に,を付け忘れてエラーを引き起こすことを防ぐため、基本的には最後の要素にも,をつけて初期化する。
- - 要素の追加について
- 2つの方法があり、関数を使う方法とブラケット[]を使って挿入する方法がある。
- - ブラケット
- `配列名[] = 'データ名';`で配列に要素を加える事が出来る。
- - array_push
- 配列にデータを挿入する関数`array_push(配列名,データ);`
- - array_pop
- 配列からデータを削除する関数`array_pop(配列名,データ);`
- - foreach
- ```php
- foreach($pref[] as $value){
- //処理内容
- }
- ```
- 配列の値を新たに変数宣言したvalueに入れて1回の処理、次の配列の値をvalueに入れて2回めの処理・・・と繰り返していく関数
- 利点として絶対に無限にならない、参照スべき変数を限定できる、要素の内容を表す変数名で参照できる。などがある
- PHPで配列または連想配列を繰り返す処理であればこれを使うべきである。
- - 連想配列でのforeach
- ```php
- <?php
- foreach($pref as キー => データ){
- //処理内容
- }
- ?>
- ```
- prefの連想配列からキーとデータを分解して1つずつ格納し、繰り返し処理を1回繰り返す、次の連想配列をキーとデータに分解し、処理を1回繰り返す・・・と繰り返していく。
- この新しく格納したキーとデータはforeachブロックを抜けた後も生き残る。
- - foreachの参照渡し
- foreachを用いた場合、要素は一時的な変数にコピーされるが、&をつけることで、
- 要素の参照(関数の中で変数の値を変更すると元の変数の値も同じように変更されること)を行うことが出来る。
- ```php
- foreach($配列名 = &$データ名){
- データ名 = 'black';
- }
- //すべての要素がblackになる
- ```
- この参照渡しは余り推奨されていない。ブロックスコープがないため、foreachブロックを抜けた後も値が維持され、
- 配列の最後の要素への参照を持ち続けるため、思わぬところで配列の最後の要素を破壊する可能性がある。
- そこでforeach参照を使う場合は`unset()`を使って参照を解除すると良い
- ```php
- foreach($配列名 = &$データ名){
- データ名 = 'black';
- }
- unset($データ名); //参照渡しが消える
- ```
- ## 連想配列
- 配列のインデックス(0...n)と数字で割り振られていたが、連想配列ではこのインデックスを自由に割り振ることが出来る。
- 入力順が保証されている順序付きマップである。
- `$data = array('インデックス名(キー)'=>'データ')`で連想配列を構成する
- 連想配列を取り出すには`$data['インデックス名(キー)']`のように配列のキー名を入れることでデータを参照できる。
- - キーに用いる要素
- - 文字列
- - 整数
- のみだが、下記の3つも使うことが出来る。その場合の条件は
- - 論理型(trueは整数の1,falseは整数の0)
- - 浮動小数点型(小数点以下は切り捨て、整数で表示)
- - null (空文字列)
- となる。
- - キーの重複
- キーが重複している場合は後に定義された要素のデータに上書きされる。
- - 連想配列での操作方法
- `array_key_exists()` : 配列の中に指定したキーが有るかどうかを検索する
- `array_key()` : 配列のキーを全て取り出し、配列として取得することが出来る。
- `key()` : 配列からキーを取り出すことができる。`prev`や`next`,`each`などのファンクションと一緒に使う
- `ksort,krsort()` : 配列をキーを基準に並び替える
- ## 繰り返し制御
- - for
- C言語と同じく`for($i=0; $i<$n $i++){処理内容}`で繰り返しを構成する。
- 配列の個数を使ったfor文を作る場合,cont関数を使うことで`for($i=0; i<count($n) i++){処理内容}`よりよいfor文を構成することができる
- - while
- こちらも同じくC言語と同じく `while(条件){処理内容}` 条件がfalseになるまで繰り返される。
- - 制御について
- - break
- 繰り返し制御や分岐制御などのブロックから抜ける時に使う
- 特定の条件時に反復を終わらせたい時に使用する
- - continue
- 現在の繰り返し処理を途中で修了し、次の繰り返しを行う。 fizz-buzz問題にいいかも
- ## 条件分岐
- - if-else
- C言語と同じく`if(条件){処理内容}else{処理内容}`で条件分岐を構成する
- (わかりづらくなるため推奨はできない)
- - trueの省略
- ifでの条件を記入する際に出力する値がtrueであれば、`==true`を省略することが出来る
- - falseの省略
- ifでの条件を記入する際に出力する値がfalseであれば、`==false`を省略し,条件の一番前に!をつけることで省略出来る
- - switch文
- 複雑な分岐を行いたい場合、switch文を使うことでif-else構文を繰り返すよりも綺麗に記述できる。
- 変数を格納し、与えられたデータにマッチするcaseに入る。
- もし与えられたデータにマッチしなかった場合はdefaultの値になる。
- breakがないと次にbreak文があるか、switch文が閉じるまですべて実行される。
- ```php
- switch ($変数){
- case 'データ1':
- echo 'テスト1';
- break;
- case 'データ2':
- echo 'テスト2';
- break;
- case 'データ3':
- echo 'テスト3';
- break;
- case 'データ4':
- echo 'テスト2';
- break;
- default:
- echo 'デフォルトですよ';
- break;
- }
- ```
- - 条件分岐の際のテクニック
- - 値が空だった時
- `$data==""` よりも`empty($data)`のほうがかっこよくていい
- `empty(変数)`は変数の中が空かどうか確かめる関数で、空の時はtrue,入っているときはfalseを出力する
- - is_numeric
- 数字かどうか判定し、数字であればtrue,数字でなければfalseを出力する。
- ## 便利な関数について
- - `mb_convert_kana`
- 全角文字を半角文字に変換する。 `mb_convert_kana('文字列','n','文字コード')` nで全角から半角に変換できる。
- - `preg_match`
- 正規表現が正しく入力されているかを判定する。正規表現にマッチしない場合はfalseを返し、あっている場合はその値を返す
- - `header`
- webページのヘッダー情報を出力させるための関数。以下の様なことが出来る。
- - ページの遷移(主に使われる)
- - エラーとしてwebブラウザに認識させる
- - ファイルをダウンロードさせる
- - webブラウザのキャッシュ機能を無効にする
- ページを移動させるときはそれ以降のプログラムを実行させないように`exit()`を合わせて記述する
- header関数を使うとたまにエラーを吐く時があるが、これはヘッダーがすでに送信されてしまっているのでヘッダーを変更できなかったという意味で、
- webページは内容を送信する直前にヘッダー情報を送信する。そのため内容が送信された後でheaderで送信しようとしても遅いという状態になる
- なのでhtm文をかかずに直接phpの文章から始めるとエラーを吐かずに実行できる
- - `isset`
- 変数が格納されているか(NULLでないか)を調べる関数
- 格納されている場合はTRUE、NULLの場合はFALSEを返す
- - `rand`
- 乱数を生成する関数。`rand(最小の数字,最大の数字)` 最小の数字から最大の数字の範囲で乱数を生成する
- - `floor`.`ceil`,`round`
- 左から順番に切り捨て、切り上げ、四捨五入である。`round(数値,少数第何位を四捨五入するか);`
- - `substr`
- `substr(文字列,切り取りはじめる文字, 長さ);` or `substr(文字列,長さ);` で切り取る文字数のはじめは0から始まる。 負の数を指定すると一番最後の文字からスタートする。
- - `max`
- `max(数字1,数字2)`2つのパラメータを比べて大きい方を返す関数
- - `var_dump()`
- 変数や式などを引数として、その変数や式の中に何のデータが入っているかを確認することが出来る。
- 主にデバック用やテスト用で使うと効果的
- ## 写真のアップロード
- - html側の処理
- ```html
- <form class="" action="sample21.php" method="post" enctype="multipart/form-data">
- <p>写真</p>
- <input type="file" name="my_img">
- <input type="submit" value="送信する">
- </form>
- ```
- formの属性に`enctype="multipart/form-data"`を追加する。
- これは文字情報のみのフォームに加えてファイルをそのまま送信することが出来る方式
- ファイルを送信する際はmethodが`get`ではなく、`post`でなければならない
- - php側の処理①
- ファイルの取得は`$_FILES`で取得でき、このデータは連想配列で格納されている
- | データのキー | データ内容 |
- |:---------------------|------------------------------------------------:|
- | name | ファイル名 |
- | type | ファイルのタイプ |
- | tmp_name | 一時的に格納されたファイル名 |
- | error | エラー内容を表示 (ない場合は0 |
- | size | ファイルサイズ |
- `tmp_name`についてだが、このファイルアップロードはフォームが送信されると一時的にそのファイルをtmpディレクトリに保存する。
- なので、この一時的なフォルダから適切なディレクトリに移動させてwebブラウザに表示させる。
- `move_uplode_file(コピー元,コピー先)`でファイルを移動させることが出来る。
- ちなみにコピー先のファイルパスについてだが、`$filePath= './image '. $file['name'];`とすると
- 本来imageフォルダに入れたいのに入らずに名前に`image+ファイル名`になってしまい、場所がうまく設定できなくなるので、
- 必ず`$filePath= './image/ '. $file['name'];` のようにディレクトリの最後には`/`を入れること。
- - php側の処理②
- ファイルアップロードはセキュリティ的に最も危険なものの1つでウィルスやスクリプトをアップロードされることもあるので気をつけなければならない
- そこで拡張子に着目して、画像だけを受け入れたい場合は拡張子がgif,jpg,pngの画像ファイルのみを受け入れれば良い。
- ```php
- $ext= substr($file['name'],-4); //後ろから4文字切り取る
- if($ext == .gif || $ext == .jpg || $ext == .png){
- //処理内容
- }
- ```
- このように拡張子を取り出して、画像の拡張子に当てはまっているか判定を行う
- ## ファイル操作
- - ファイルに内容を書き込む
- `file_put_contents('ファイルパス','書き込む内容');`
- ファイルパスには予めファイルの格納場所を作っておく。
- ファイルに内容を書き込めなかった時、falseを返す。
- ファイルの内容については簡単に見られてしまう。なので、通常はhtdocsフォルダなどのドキュメントルートと呼ばれる場所よりも外に保存すると良い
- `file_put_contents(''../../test/test.txt,'書き込む内容')`このようにドキュメントルートよりも階層を上げて保存すれば良い
- - ファイルの内容を取得する
- `file_get_contents('ファイルパス/ファイル名');`
- テキストから読み込んだ内容は変数に保存するなど自由に利用することが出来る。
- - ファイルの内容を取得して出力する
- `readfile('ファイルパス/ファイル名')`;
- この場合は読み込んだ内容を変数に代入できないので、読み込んだ内容を加工したい場合は`file_get_contents`を使う
- ## PHPブロックをまたぐブロック文
- PHPはファイル中のPHPブロックのみをソースコードとして認識して実行するが、
- 1つのファイル内であれば、複数のPHPブロックをまたぐ文をつくることができ、処理される。
- つまり、1度、PHPブロックを抜け、HTMLコードが交じる場合でも、if文の構文ブロックは継続されている。
- ```php
- <?php
- if(isset($データ)){
- ?>
- <p><?php echo $data;</p>
- <?php
- }
- ?>
- //わかりづらいが、 ifのphpブロックを閉じた後,htmlがあり、その後またphpブロックで}をやっている。
- //このような文になっても正しく実行される
- ```
- このようなhtmlをまたぐコードには`{}`だけでなく、`:`や、endifなどを用いる。
- これらはPHP文だけでは使うことはないが、htmlとの混合は可読性を高めるために用いられる。
- ```php
- <?php if ($value) : ?>
- <P> このメッセージは$valueがtrueの時に表示される </p>
- <?php else : ?>
- <p> このメッセージは$valueがfalseの時に表示される</p>
- <?php endif; ?>
- ```
- ## requireとrequire_onece
- - requireとは
- 別のファイルに記述されたphpファイルを読み込むための関数。
- 読み込む対象のファイルがない場合、Fatal errorになり実行が終了する。
- 名前空間が定義されていないファイルを読み込んだ時読み込んだファイルに定義されているクラスはグローバルとなり、
- 読み込んだ先でも利用することが出来る。
- また、読み込むファイルで何らかの処理や出力をしている場合は読み込んだ時点で実行される
- - require と require_onceの違い
- require_onceは一度だけrequireをする関数で、ファイルが既に読みこまれている場合は再読み込みをしない。
- 同じファイルが何回も読み込まれると関数の再定義などが行われ、エラーの原因となる。また、変数が再代入されて値が変わったりすることもあるので
- これを起こさないためにもrequire_onceを使うと良い
- -include と include_once
- これもrequireとrequire_onceと同じ挙動をするのだが、明らかな違いとして、ファイルが存在しなかった時、Fatalエラーではなく、警告を出して実行する
- ## 関数
- - 関数の基本
- ```php
- function 関数名(引数,・・・){
- //関数の中身
- }
- ```
- このように定義された関数は名前空間を定義していない場合はグローバルスコープに定義される。
- どのような型でも渡す事ができ、どのような型でも返すことが出来る。
- PHPに標準で備わっている関数との名前の衝突に注意。
- - 引数のデフォルト値
- 関数の引数にデフォルト値を与えることが出来る。
- 引数にすることが出来るのは定数値のみとなっており、デフォルト値に演算結果を代入はできない。
- ```php
- function hello($name,$greeting = 'Hello!'){
- echo $greeting,$name ,PHP_EOL;
- }
- hello('Bob','Good morning'); // Good morning ! Bob
- hello('Tom'); // Hello! Tom
- ```
- 引数にデフォルト値を与えると、呼び出す際に省略すると、デフォルト値が出力される。
- また、呼び出す際に、引数をちゃんと入れてやるとデフォルト値から変更されて出力される。
- デフォルトを持つ引数は、持たない引数よりも後に定義しなければならない。
- - タイプヒンティング
- 引数に渡されるべき値を特定のクラスまたは配列(array)に限定することが出来る。
- スカラー型(in,string,boolなど)には使えない。
- もし設定した場合、関数を呼び出す際にちゃんとした型の変数を入れないとFatal errorになり、実行が中断される。
- ```php
- function 関数名 (array $変数名){ //タイプヒンティング
- //処理内容
- }
- $array = array(1,2,3,);
- 関数名($array) //ちゃんと実行される
- 関数名(1) //配列ではないので、エラーが起こる
- ```
- - 可変関数
- 関数の名前を変数として格納して、それを呼び出して関数として使う方法
- ```php
- function 関数名1($変数名1) {
- if(function_exists($変数名){
- $name(); //可変関数での呼び出し
- }
- }
- function foo(){
- echo 'foo called',PHP_EOL;
- }
- 関数名1('foo'); //関数fooを呼び出す
- ```
- - 無名関数
- 名前の無い関数。 変数に関数を代入する事もできる。
- ```php
- $add = function($v1,$v2){
- return $v1 + $v2;
- }
- //関数の呼び出し
- echo $add();
- ```
- - クロージャー
- 関数の中に関数を作成して関数で使用していた値を継承して中の関数で操作すること。
- 間違った例)
- ```PHP
- function test(){
- $hello = "hello world";
- $myFunc = function(){
- echo($hello);
- }
- }
- //エラーを吐く
- ```
- この場合、無名関数内では無名関数外の変数は使えないので`$hello`に値が入らず、エラーが出てしまう。
- そこで、`use`を使って無名関数外のtest()の値を使って無名関数の操作をする。
- ```php
- function test(){
- $hello = "hello world";
- $myFunc = function() use ($hello);{
- echo($hello);
- }
- }
- //hello world
- ```
- 無名関数の中の値を外の関数で使いたい場合は&を使って参照渡しをする
- ```php
- function method() {
- $hello = 'hello';
- $closure = function() use (&$hello){ //参照渡し
- $hello = 'goodby';
- echo "${hello}! world!", PHP_EOL;
- };
- $closure(); // goodby! world!
- echo $hello; // goodby
- }
- method();
- ```
- - クロージャーの利点
- 1. 関数の中に関数を作って操作するので、グローバル変数の宣言を減らすことが出来る。
- 2. 関数を内包化するので外部からアクセスできないようになる。 他で同じ変数を使っても値が干渉しない
- ## PHPでのオブジェクト指向
- - クラスの定義
- ```php
- class クラス名{
- クラスの実装
- }
- ```
- - インスタンスの記述と生成
- work()メソッドを持った従業員クラスEmplyeeクラスを作成したとする。
- ```php
- class Employee{
- public function work(){
- echo '働いています' ,PHP_EOL;
- }
- }
- ```
- クラスを使うときはnew 演算子を使ってクラスをインスタンス化(実際に値を入れて生成すること)する。
- メソッドの呼び出しには`->`アロー演算子を使って呼び出す。
- ```php
- $yamada = new Employee();
- $yamada->work();
- $suzuki = clone $yamada;
- ```
- 同じクラスを使ってインスタンスを生成するときは`clone`を使って複製する。
- newによって生成されたオブジェクトは`unset()`で開放できる。
- - アクセス修飾子
- メソッドやプロパティ(メンバ変数)がどこからアクセス可能かを表す修飾子
- - public
- クラスの外部から呼び出し、参照ができる。
- - private
- 自分のクラスの内側のみからの参照、呼び出しができる。 クラス内でのみデータを使うときに使う
- - protected
- 自分のクラスの内側または自分のクラスを継承したクラスの内側ののみ参照、呼び出しができる。
- ```php
- class Employee{
- public name; //従業員の名前
- private $state = '働いている'; //従業員の状態を表す
- public function work(){
- echo $state;
- }
- }
- $yamada = new Employee();
- $yamada->name = '山田';
- echo $yamada->state,$yamada->name, 'さん'; //stateがprivateに設定されているため、呼び出すことができず、エラー
- yamada->work(); //workメソッドはpublicなので $stateをメソッド内で処理して呼び出すことが出来る。
- ```
- - $this
- オブジェクトのインスタンス化をすると、クラス内のメソッドで利用できる$thisという変数が定義される。
- $thisはクラス内で使われ、自分自身のオブジェクトの参照を意味する。
- ```php
- class Employee{
- public name; //従業員の名前
- private $state = '働いている'; //従業員の状態を表す
- public function getState()
- {
- return $this->$state; //$thisは呼ばれたインスタンスを指す
- }
- public function setState($state)
- {
- $this ->state =$state;
- }
- public function work(){
- echo $state;
- }
- }
- $yamada = new Employee();
- $yamada->name = 'やまだ';
- $yamada->setState('休憩している');
- $yamada->name,'さんは', $yamada->getState(),PHP_EOL;//山田さんは休憩していると出力される
- ```
- - static~~おじさん~~プロパティ
- 静的なプロパティで、プロパティ宣言時にstaticをつけると
- そのプロパティはクラスがインスタンス化されてなくても呼び出すことが出来る。
- staticを呼び出すときは`クラス名::$プロパティ名`
- ```php
- class Employee
- {
- public $name;
- public static $company = '香川高専';
- }
- echo '従業員はみんな、', Employee::$comperny, 'に努めています', PHP_EOL; //香川高専に勤めていると出る。
- ```
- - self
- クラスの内部でのstaticプロパティを使ってメソッドを作る場合、$thisではなくselfを使ってアクセスする。
- $thisとの違いはインスタンス化したデータを指すのか、内部で生成したデータを指すのかのちがいである。
- ```php
- class Employee{
- public static $company = '香川高専';
- public static function getCompany(){
- return self::$company;
- }
- public static function setCompany($value){
- self::company = $value;
- }
- }
- echo Employee::getCompany(),PHP_EOL; //社名の出力
- Employee::setCompany('技術評論社'); //社名を変えるとき
- ```
- - コンストラクタとデストラクタ
- - コンストラクタ
- クラスのインスタンスが作られるタイミングで自動的に呼ばれるメソッド
- インスタンスを生成するときに、無駄な入力を避けることが出来る。
- `function __construct(){//処理}`で使うことが出来る。
- - デストラクタ
- クラスのインスタンスが消されるタイミングで自動的に呼ばれるメソッド
- ```php
- class Employee{
- public name; //従業員の名前
- private $state = '働いている'; //従業員の状態を表す
- public function __construct($name){ //インスタンスが生成された時に名前を格納する
- $this->name = $name;
- }
- public function getState()
- {
- return $this->$state;
- }
- public function setState($state)
- {
- $this ->state =$state;
- }
- public function work(){
- echo $state;
- }
- }
- $yamada = new Employee('山田');
- ```
- コンストラクタに入れる場合は外部で呼び出すことはなくなるのでプロパティを`private`にする。
- - 継承
- あるメソッドやプロパティを引き継いで新しいクラスを定義すること。
- 継承されたクラスを親クラス、継承したクラスを子クラスという。
- 子クラスではプロパティやメソッドをすべて引き継ぐ。
- 引き継いだもののうち、publicまたはprotectedなものに限定して内部からアクセスすることが出来る
- 外部からのアクセスはpublicに限定される
- PHPでは多重継承(1つの親クラスと外の親クラスを継承すること)は許されておらず、継承する親クラスは1つだけ
- ```php
- class Programmer extends Employee{ //Programmerクラスは Employeeクラスを継承する
- }
- ```
- - オーバーライド
- 親クラスに定義したメソッドやプロパティを子クラスに同じ名前で定義すると、
- 子クラスでの実装が上書きされ、別の動きを実装する。
- ```php
- //Employeeクラスの子クラス
- class Programmer extends Employee
- {
- //親クラスのworkメソッドをオーバーライド
- public function work(){
- echo 'プログラムを書いています',PHP_EOL;
- }
- }
- ```
- オーバーライドしたメソッドは親クラスのメソッドと引数が違ってはいけない。
- コンストラクタはインスタンスを構築するための特別なメソッドなので、親クラスのコンストラクタと違っても良い
- - parent
- 親クラスを表すワードで、親のクラスを呼ぶときに使う。
- selfと同じく`parent::`
- ```php
- //親クラスのコンストラクタを呼び出したい時
- class Programmer extends Employee
- {
- public function __construct($name,$type){
- parent::__construct($name,$type); //親クラスのコンストラクタを呼び出す
- }
- }
- ```
- - final
- finalキーワードをつけて宣言すると、そのメソッドは継承された子クラスでオーバーライドできなくなる
- ```php
- class Employee {
- public $salary = 20;
- public final function getSalary
- {
- return $this->salary;
- }
- }
- class Programmer extend Employee{
- //メソッドをオーバーライドするとエラーを吐く
- public function getSalary()
- {
- return $this->salary *2;
- }
- }
- ```
- - 標準クラス
- プロパティやメソッドを持たない`stdClass`と呼ばれる標準クラスがある。
- 未定義のインスタンスプロパティを新たに作成できる。
- ```php
- $obj = new stdClass(); //空のクラスを作成
- $obj->some_member = 1; //クラスの中にプロパティを生成(初期化)
- ```
- - 抽象クラス
- 共通の機能を抽象的な親クラスで定義し、特有の機能は個々の子クラスでそれぞれ実装させたい場合に実装する
- 抽象クラスではメソッドの実装はせず、宣言するのみにする。
- 抽象クラスはabstructメソッド以外の実態のあるメソッドを定義することもできる。
- その場合はabstructキーワードを付けず、普通のメソッドと同様に定義する。
- 抽象クラスはそれ自体をインスタンス化することはできない。
- 必ずその抽象クラスを継承したクラスをインスタンス化する必要がある
- ```php
- abstract クラス名
- {
- abstract public function work();
- abstract public function state();
- public function メソッド名
- }
- class Programmer extends クラス名
- {
- public function work()
- {
- }
- }
- //抽象クラスのstate()メソッドを子クラスで使っていないのでエラーが起こる
- ```
- - インターフェース
- 複数の異なるクラスに共通の機能を実装するために、その実体を定義することなく指定する仕組み
- interfaceを用いると特定のオブジェクトが特定の機能を有することを保証する。
- interfaceのメソッドは`public`でなければならない
- ```php
- //インターフェースの定義
- interface インターフェース名
- {
- インターフェースの定義;
- }
- ```
- インターフェースでは実態のあるメソッドを定義できない。
- ```php
- //インターフェースの利用
- class クラス名 implements インターフェース名,・・・
- {
- クラスの定義
- }
- ```
- 実装例)
- ```php
- interface Reader
- {
- public function read();
- }
- interface Writer
- {
- public function write($value);
- }
- class Configure implements Reader,Writer
- {
- public function write($value)
- {
- //書き込みの処理
- }
- public function read();
- {
- //読み込みの処理
- }
- }
- ```
- インターフェースを取り込んでいる状態でインターフェース内のメソッドを実装しないとエラーを吐く
- - インターフェースのチェック
- タイプヒンティングを使ってインターフェースのメソッドの引数が正しく使われているか判定する
- ```
- interface MyInterface
- {
- public function メソッド名($データ名);
- }
- class クラス名
- {
- public function メソッド名(MyInterface $データ名){
- }
- }
- ```
- - マジックメソッド
- コンストラクタ`__constract`のような特定の条件で自動的に呼び出されるメソッド。
- どんなクラスでも定義でき、定義されている場合は必要に応じて呼び出される。
- - オーバロード
- 特定の処理がクラスまたはオブジェクトに施された時のデフォルトの挙動を上書きする機能
- クラスやオブジェクトのアクセス不可能なプロパティやメソッドが参照された時、通常エラーが発生する挙動を
- `__get()`,`__set()`,`__isset()`,`__unset()`,`__call()`,`__callStatic()`のマジックメソッドを使ってエラーの挙動を上書きできる。
- - `__get()`
- アクセス不可能なプロパティを取得するときに呼び出す
- - `__set()`
- アクセス不可能なプロパティに代入するときに呼び出す
- - `__isset()`
- アクセス不可能なプロパティに対してisset()かempty()を実行した時に呼び出す
- - `__unset()`
- アクセス不可能なプロパティに対してunset()を実行した時に呼び出す
- - `__call()`
- アクセス不能なメソッドを呼び出す時に呼び出すときに呼び出す
- - `__callStatic()`
- アクセス不可能なメソッドをstaticに呼び出すときに呼び出す
- - 遅延静的束縛
- 子クラスでインスタンスを生成したのにもかかわらず、メソッドを実行すると`self`を使っているために継承された親クラスの静的メソッドで実行されてしまう。
- これを防ぐためにstaticを使ってこクラスで実行してもらう方法
- 例)
- ```php
- class Foo {
- public function helloGateway(){
- self::hello();
- }
- public function hello(){
- echo __CLASS__,'hello',PHP_EOL;
- }
- }
- class Bar extends Foo{
- public static function hello(){
- echo __CLASS__ ,'hello',PHP_EOL;
- }
- }
- $bar = new Bar();
- $bar -> helloGateway(); // Foo hello が出てきてしまう。
- ```
- この例の場合、`self`を使っているため親クラスの`hello()`メソッドを実行してしまった。
- このselfをstaticに変えて実行すると
- ```php
- class Foo {
- public function helloGateway(){
- static::hello(); //selfからstaticに変更した
- }
- public function hello(){
- echo __CLASS__,'hello',PHP_EOL;
- }
- }
- class Bar extends Foo{
- public static function hello(){
- echo __CLASS__ ,'hello',PHP_EOL;
- }
- }
- $bar = new Bar();
- $bar -> helloGateway(); // bar hello 正常に動作した
- ```
- - オートロード
- 自動的にそのクラスが定義されているファイルを読み込む機能
- 定義されていないクラスを使おうとした時に、指定されたオートロード関数が呼び出される。
- `__autoload()`はクラス名を引数として渡してそのクラスファイルを読み込むメソッドを返す
- require_onceでファイルを読み込むよりオートロードを使ってファイルを読み込むほうがモダンである(らしい)
- - `__autoload()`関数を使用したファイル内のクラスを呼び出すコード
- ```php
- function __autoload($name) //クラス名を引数として取得する
- {
- $filename = $name . 'php';
- if(is_readable($filename)){
- require $filename; //ファイルの読み込み
- }
- }
- $obj = new Foo();
- ```
- `__autoload()`を呼び出した後にそのファイルの中に呼びだそうとしているクラスがない場合、エラーを吐く
- - `sql_autoload_register()`関数
- `__autoload()`には2つの問題がある。
- 1. グローバル関数でなければならない
- 2. 処理を1つしか登録できない
- あるファイルでオートロードの仕組みを使い、それを別のオートロードの仕組みを使ったスクリプトから読み込みたいということはできない。
- それを解決するのが `sql_autoload_register()`。 出来ることは2つある。
- 1. オートロードに使われる処理をコールバック関数の形式で指定できる
- 2. クラスを複数のコールバック関数で登録できる
- 複数のコールバック関数が登録されている場合、そのクラスが定義されるまでコールバック関数を呼び出し続ける。
- `sql_autoload_register()`で登録したクラス、関数を格納し、新しい定義されていないクラスを呼び出すと、それらの登録したクラスで処理し、
- 結果を出力する
- ```php
- <?php
- function __autoload($name)
- {
- echo '__autoload(' . $name . ') was called.', PHP_EOL;
- }
- class Hoge
- {
- public static function load($name)
- {
- echo 'Hoge::load(' . $name . ') was called.', PHP_EOL;
- }
- }
- class Bar
- {
- public function load($name)
- {
- echo '$bar->load(' . $name . ') was called.', PHP_EOL;
- $file = $name . '.php';
- if (is_readable($file)) {
- require_once $file;
- }
- }
- }
- function load($name)
- {
- echo 'load(' . $name . ') was called.', PHP_EOL;
- }
- spl_autoload_register('__autoload');
- spl_autoload_register('Hoge::load');
- $bar = new Bar();
- spl_autoload_register(array($bar, 'load'));
- spl_autoload_register('load');
- $foo = new Foo();
- /* 出力:
- __autoload(Foo) was called.
- Hoge::load(Foo) was called.
- $bar->load(Foo) was called.
- */
- ?>
- ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement