PHP

$callback に渡せる関数の2種類の方法
①通常の関数を文字列で渡す
function compareLength($s1, $s2){
return strlen($s1) >= strlen($s2);
}
echo maxByCriteria('compareLength', ["apple", "banana", "cherry"]);
・関数を文字列で渡す場合、その関数は function で定義する必要がある
→ PHP は compareLength をグローバル関数として認識する
→ maxByCriteria() 内で call_user_func($callback, ...) を使うと compareLength を適切に実行できる
→ PHP は function を先に定義しておくと、後の処理で文字列で呼び出せる
・通常の名前付き関数も、コールバック関数として問題なく使える。
②無名関数(クロージャ)を渡す
$compareAsciiTotal = function($s1, $s2){
return getAsciiTotal($s1) >= getAsciiTotal($s2);
};
echo maxByCriteria($compareAsciiTotal, ["apple", "banana", "cherry"]);
・無名関数の場合、$callback に 文字列 ではなく変数を渡す
→ 無名関数(クロージャ)は、通常の関数とは異なり文字列で呼び出せない
→ 変数 $compareAsciiTotal に格納された関数を maxByCriteria() に渡す必要がある
→ PHP では $callback に関数を渡すとき、無名関数はそのまま変数で渡さないとエラーになる
★PHPでは、変数に格納された関数(クロージャ)を使用する場合、その変数が定義されている必要がある。
→定義の順番が重要
※通常の関数はどこからでも呼べる

var_dump()
PHP の デバッグ用関数
変数の データ型と値 を詳細に表示するために使う。
$var = "Hello";
var_dump($var);
// 出力
string(5) "Hello"
※echo を使うと、戻り値が true の場合は 何も出力されないため、デバッグに向かない。
しっかり動作するかどうかを確かめるにはvar_dump()の方が適している。

関数名を 文字列として渡せる場合
- PHPの組み込み関数(strlen, strtoupper など)
function customArray($callback, $intArr) {
foreach ($intArr as $num) {
echo $callback($num) . PHP_EOL;
}
}
customArray('strlen', ['apple', 'banana', 'grape']); // OK
- グローバルスコープに定義された関数
function cube($n) {
return $n * $n * $n;
}
customArray('cube', [2, 3, 4]); // OK
- call_user_func() や call_user_func_array() を使う場合
function hello($name) {
return "Hello, $name!";
}
echo call_user_func('hello', 'Taro'); // Hello, Taro!
- クラスのメソッドを "クラス名::メソッド名" の形式で渡す
class MathUtil {
public static function square($n) {
return $n * $n;
}
}
customArray('MathUtil::square', [3, 5, 7]); // OK
- オブジェクトのメソッドを [$object, 'メソッド名'] で渡す
[$object, 'メソッド名'] は 「オブジェクト $object の 〜メソッドを指定する」 という意味になる。
PHPでは、関数のコールバックとしてオブジェクトのメソッドを指定する場合、[$obj, 'メソッド名'] の形式で書くルールがある。
class NumberProcessor {
public function double($n) {
return $n * 2;
}
}
$obj = new NumberProcessor();
customArray([$obj, 'double'], [3, 5, 7]); // OK

true・falseの表示
PHP で echo true は "1"、echo false は ""(空文字)と表示される。

foreach
PHPのforeachは配列とオブジェクトを反復する言語構文
unsetをしないと要素は最後の値を参照したままになる。
unset(変数); がない場合の問題
PHP の foreach は ループ変数を参照のまま保持する性質がある。
そのため、ループ終了後も変数は最後のループの値を保持したまま残ることになる。
unset(変数)は、予期しない参照の残留を防ぐ。foreach のループ変数を明示的に削除するための処理。
foreach (&変数) の場合は unset(変数); をしないとバグの原因になる

array_walk()
配列のすべての要素にコールバック関数を適用する。

クロージャ
PHPの場合inner関数を外部から隠蔽することができません。
PHPのクロージャでは、use構文を使用して外部の関数を変数のように扱うことができる。
これは、PHPが関数名を文字列として内部的に管理しているため。
→use構文で関数名を指定すると、その関数名に対応する関数への参照がクロージャに渡される
つまり、accessAlert という関数を外部で設定し、その関数を引数として使うときには、use($accessAlert)とすることで、あたかも関数を変数として扱うことができる。
PHPでは、関数内で定義された関数は、その外側の関数が実行されて初めて利用可能になるというスコープの概念があるため、「outer関数を呼び出した後なら、inner関数を呼び出せる」という仕組みになっている。
PHPにおいては、クロージャを使用する事で、関数の中で定義された関数を、関数の外から呼び出す事が可能。

グローバルスコープの変数を関数内で使用する方法
- global キーワードを使う
グローバル変数を関数内で直接参照する方法。
<?php
$currencyList = [
"USD" => 135,
"EUR" => 150,
"GBP" => 170
];
function getRate(string $currency) {
global $currencyList; // グローバル変数を参照
return $currencyList[$currency] ?? null;
}
echo getRate("USD"); // 135
- use を使ったクロージャのキャプチャ
クロージャ(無名関数)の use を使って変数をキャプチャする方法
<?php
$currencyList = [
"USD" => 135,
"EUR" => 150,
"GBP" => 170
];
$getRate = function(string $currency) use ($currencyList) {
return $currencyList[$currency] ?? null;
};
echo $getRate("USD"); // 135
・グローバル変数 $currencyList をキャプチャし、スコープを限定できる。
・global よりも カプセル化されていて安全。
・ただし、use でキャプチャした変数はデフォルトで「値渡し」(コピー)されるため、関数内で変更しても元の変数には影響しない。

正規表現
PHP では、関数の引数として渡された変数が未定義でも、関数内で代入されると自動的に定義される仕様になっている。

preg_match()
最初にマッチした1つだけを取得する。
[0] には 全文マッチ、[1]以降に キャプチャグループの内容が入る。
すべてのマッチを取得したい場合は preg_match_all() を使う。

暗黙の型変換
文字列であっても、*(乗算演算子)が使われると PHPが自動的に数値(float型)へ変換する。

$_POSTで受け取ったデータ
そのまま使用せず、適切な検証やサニタイズを行うことが重要。
例えば、htmlspecialchars()関数を使ってHTMLエスケープを行うことが推奨される。

$_SERVER['']
Web サーバーに関する様々な情報を取得するために利用できる便利なスーパーグローバル変数。
Web アプリケーション開発において、サーバー環境やリクエストに関する情報を取得したい場合に活用できる。
Web サーバーから提供される様々な情報を格納した配列。
この配列のキー('' の部分)に対応する値を取得することで、サーバー環境やリクエストに関する様々な情報を知ることができる。
$_SERVER 配列の主な要素
要素 | 説明 |
---|---|
PHP_SELF | 現在実行中のスクリプトのファイル名(ドキュメントルートからの相対パス) |
GATEWAY_INTERFACE | サーバーが使用している CGI のバージョン |
SERVER_ADDR | 現在のスクリプトが実行されているサーバーの IP アドレス |
SERVER_NAME | 現在のスクリプトが実行されているサーバーの名前 |
SERVER_SOFTWARE | サーバーソフトウェアの名前 |
SERVER_PROTOCOL | リクエストで使用されたプロトコルの名前とバージョン |
REQUEST_METHOD | リクエストメソッド(GET、POST など) |
REQUEST_TIME | リクエスト開始時のタイムスタンプ |
QUERY_STRING | URL のクエリ文字列 |
HTTP_ACCEPT | Accept ヘッダーの内容 |
HTTP_USER_AGENT | User-Agent ヘッダーの内容 |
REMOTE_ADDR | クライアントの IP アドレス |
REMOTE_HOST | クライアントのホスト名 |
DOCUMENT_ROOT | ドキュメントルートのパス |

htmlspecialchars()
HTMLの特殊文字をエスケープするために使用される関数。
これにより、クロスサイトスクリプティング(XSS)などのセキュリティリスクを防ぐことができる。
注意点
・htmlspecialchars() は、HTMLの特殊文字をエスケープするだけで、HTMLタグを削除するわけではない。HTMLタグを削除したい場合は、strip_tags() 関数を使用する。
・エンコーディングを指定しない場合、デフォルトのエンコーディングが使用される。エンコーディングを明示的に指定することを推奨される。

ダブルクォートで囲まれた文字列の中で、{$変数名} のように記述すると、PHP は変数の値を文字列に変換し、文字列内のその場所に挿入する。
※シングルクォートだと変数は展開されない。

assert ( mixed $assertion , Throwable $exception = ? ) : bool
assert() は、指定した assertion を調べて、結果が false の場合に指定したメッセージやアラートを返す

PHP内にHTML・JavaScriptコードを組み込む場合と、HTML内にPHPコードを組み込む場合の違い
① 処理のタイミング
1. PHP内にHTML・JavaScriptコードを組み込む場合
・PHPはサーバーサイドで実行され、HTML・JavaScriptコードを生成してブラウザに送信する。
・ブラウザは、送信されたHTML・JavaScriptコードを受け取り、レンダリングして実行する。
・つまり、PHPが先に実行され、HTML・JavaScriptは後から実行されます。
2. HTML内にPHPコードを組み込む場合
・サーバーは、HTMLファイル内のPHPコードを先に実行し、その結果をHTMLに埋め込む。
・その後、生成されたHTMLをブラウザに送信し、ブラウザがレンダリングする。
・この場合も、PHPが先に実行され、HTMLは後からレンダリングされる。
② コードの役割
1. PHP内にHTML・JavaScriptコードを組み込む場合
PHPは、HTML・JavaScriptコードを動的に生成するために使用される。
例えば、データベースから取得したデータをHTMLテーブルに表示したり、ユーザーの入力に応じてJavaScriptの動作を変更したりできる。
2. HTML内にPHPコードを組み込む場合
PHPは、HTMLの表示内容を動的に変更するために使用される。
例えば、現在の日時を表示したり、ユーザーのログイン状態に応じて異なるコンテンツを表示したりできる。
③ ファイルの拡張子
1. PHP内にHTML・JavaScriptコードを組み込む場合
・ファイルの拡張子は「.php」にする必要がある。
・サーバーは、「.php」ファイルをPHPスクリプトとして処理し、その結果をHTMLとして出力する。
2. HTML内にPHPコードを組み込む場合
・ファイルの拡張子は「.php」にする必要がある。
・サーバーは、「.php」ファイル内のPHPコードを実行し、HTMLコードを生成する。
PHPはHTMLやJavaScriptを生成する役割を担い、HTMLは生成された情報に基づいてブラウザに表示される役割を担っている。

ローカル環境でのWebアプリケーションの動作の流れ
1. VS Codeでの開発
VS Codeなどのテキストエディタで、PHPファイル(例:index.php)と、必要に応じてHTML、CSS、JavaScriptなどのファイルを作成する。
2. WebサーバーとPHP処理系のインストール
ローカル環境でPHPアプリケーションを動作させるためには、Webサーバー(Apache、Nginxなど)とPHP処理系(PHPインタプリタ)をインストールする必要がある。
これらのソフトウェアは、XAMPP、MAMP、Dockerなどのツールを利用して簡単にインストールできる。
3. アプリケーションサーバーとしてのPHP処理系
※https://tech.kurojica.com/archives/55908/ より画像引用
PHPファイルは、アプリケーションサーバーに保存されるというよりも、WebサーバーがPHP処理系を呼び出して実行する。
この場合、PHP処理系がアプリケーションサーバーの役割を果ます。
Webサーバーは、PHPファイルへのリクエストを受け取ると、PHP処理系に処理を委譲する。
PHP処理系は、PHPファイルを解析し、動的にHTMLコードを生成する。
4. Webサーバーからクライアントへのレスポンス
PHP処理系が生成したHTMLコードは、Webサーバーに返される。
Webサーバーは、このHTMLコードをクライアント(Webブラウザ)に送信する。
5. Webブラウザでの表示
Webブラウザは、Webサーバーから受け取ったHTMLコードを解析し、Webページとして表示する。
ローカル環境でアプリケーションが動作する理由
ローカル環境にWebサーバーとPHP処理系をインストールすることで、外部のVPSやコンテナを使用せずに、PC上でWebアプリケーションを動作させることができる。
Webブラウザは、ローカル環境で動作しているWebサーバーにアクセスし、Webページを表示する。
この場合、WebサーバーとPHP処理系は、PC内で連携して動作し、外部のサーバーとの通信は発生しない。
(具体例)
・XAMPPをインストールした場合、Apache WebサーバーとPHP処理系がインストールされる。
・index.php ファイルをXAMPPのhtdocsディレクトリに保存し、Webブラウザから http://localhost/index.php にアクセスすると、PHPファイルが実行され、生成されたHTMLコードがWebブラウザに表示される。
ローカル環境での開発は、外部のサーバーに依存せずに、手軽にWebアプリケーションを試すことができる

PHPのプログラム
プログラムは実行時、メモリにロードされて動作する
PHP のスクリプトは、PHP 処理系という、C 言語で書かれたプログラムが解釈して実行
メモリ内にスクリプト(PHP コード)を読み込む
メモリ内にスクリプトと対応する中間コードを生成(コンパイル)
中間コードを解釈
中間コードに記述された通り処理を行い、ある種の仮想マシンとして処理系の内部状態(メモリ内容)を更新していく
※https://qiita.com/sj-i/items/a29d54cfd83f230ddc3d より画像引用
PHP処理系
※https://speakerdeck.com/sji/php-deshi-zhong-nosukuriputonodong-zuo-woxia-karasi-ki-ru?slide=30 より画像引用
PHPプログラム処理の流れ
※https://iwatani.tv/programming/php-processing-of-php/ より画像引用

PDO(PHP Data Objects)
※https://logicoya.com/course/lesson/131 より画像引用
PHPにおけるnew PDO()は、PHP Data Objects (PDO)というデータベース接続のためのインターフェースを使用して、データベースとの接続を確立するためのオブジェクトを作成する際に使用される。
PDOとは
※https://gray-code.com/php/about-pdo/ より画像引用
PDOは、PHPからさまざまなデータベースに一貫した方法でアクセスするための拡張モジュールのこと。
MySQL、PostgreSQL、SQLiteなど、多くのデータベースシステムに対応している。
PDOを使用することで、データベースの種類に関係なく、同じようなコードでデータベース操作を行うことができる。
new PDO()の役割
new PDO()は、PDOクラスのインスタンス(オブジェクト)を作成する。
このオブジェクトは、データベースとの接続を確立し、SQLクエリの実行や結果の取得などのデータベース操作を行なうために使用される。
new PDO()の構文
※https://blog.oplan.co.jp/archives/2305 より画像引用
$pdo = new PDO(データソース名, ユーザー名, パスワード, オプション);
データソース名 (DSN)
データベースの種類、ホスト名、データベース名などの接続情報を指定します。
(例)"mysql:host=localhost;dbname=mydatabase"
ユーザー名
データベースに接続するためのユーザー名を指定する。
パスワード
データベースに接続するためのパスワードを指定する。
オプション
接続に関するオプションを配列で指定する。
(例)[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION](エラー処理モードの設定)
new PDO()を使用するメリット
データベースの抽象化
PDOを使用することで、データベースの種類に依存しないコードを書くことができる。
セキュリティ
プリペアドステートメントを使用することで、SQLインジェクション攻撃を防ぐことができる。
エラー処理
例外処理を使用することで、データベース操作のエラーを適切に処理できる。

$_POST
$_POSTスーパーグローバル変数は、フォームからPOSTメソッドで送信されたデータを連想配列として保持している。この配列のキーは、formタグ内の各入力要素のname属性の値に対応している。
重要な点
PHPの$_POSTは、name属性の値を大文字と小文字を区別して扱う。

スーパーグローバル変数
すべてのスコープで使用できる組み込みの変数
PHP の定義済み変数の中には "スーパーグローバル" というものがあります。 これは、スクリプト全体を通してすべてのスコープで使用可能な変数のことです。 関数やメソッドの内部からアクセスする際にも global $variable; などとする必要はありません。
$GLOBALS
$_SERVER
$_GET
URLのクエリ文字列を受け取る
$_POST
フォームのデータを受け取る
$_FILES
$_COOKIE
クライアントがクッキーを送信した場合、サーバー側でデータを取得
$_SESSION
ユーザーがログインした際に、サーバー側でセッションデータを保持
$_REQUEST
$_ENV
HTTPリクエストのデータを自動的に解析
PHPは、HTTPリクエストが到着すると、そのデータを自動的に解析し、適切なスーパーグローバル変数に格納する。
(例)GETリクエストのデータは $_GET に、POSTリクエストのデータは $_POST に格納される。
スクリプト内で簡単にアクセス可能
スーパーグローバル変数は、PHPスクリプトのどこからでもアクセスできるため、開発者が簡単にデータを利用できる。
データの構造化
スーパーグローバル変数は連想配列としてデータを保持するため、キーと値のペアでデータを整理できる。
(例)$_GET['name'] や $_POST['username'] のように、特定のデータに簡単にアクセスできる。
※https://www.php.net/manual/ja/language.variables.superglobals.php より引用