PHP/

メインページ > 工学 > 情報技術 > プログラミング > PHP PHPは、汎用スクリプト言語ですが、CGI/FastCGIあるいはウェブサーバー組込みモジュールを介してウェブサービスで利用されることか多く、本書でもウェブでの利用を念頭に解説します。
PHPのコードは通常、モジュール、デーモン、あるいはCommon Gateway Interface (CGI) 実行ファイルとして実装されたPHPインタプリターによってウェブサーバー上で処理されます。 ウェブサーバー上では、PHPコードが解釈され実行された結果、生成されたHTMLやバイナリ画像データなど、あらゆる種類のデータがHTTPレスポンスの全体または一部を形成することになります。 様々なウェブテンプレートシステム、ウェブコンテンツ管理システム、およびウェブフレームワークが存在し、これらのシステムを使ってレスポンスの生成を統制し、円滑化することができます。 さらに、PHPはウェブ以外のプログラミングにも応用することができ、スタンドアローンのグラフィカルなアプリケーションやロボットやドローン制御などの組込みシステムでも使用可能です。
PHPは2022年12月現在、唯一サポートされているバージョン PHP 8 が提供されています。
PHPは動的なウェブページを構築することを大きく意識したプログラミング言語で、開発用のウェブサーバーを内蔵しています。 このため、特にApache HTTP Server/nginxやh2oなどでウェブサーバー環境を構築することなく、プログラミングの学習を開始できます。
実際の運用に開発用の内蔵ウェブサーバーを使うことは、パフォーマスやセキュリティの問題から非推奨ですが、ウェブサーバーとPHP処理系を連携するセットアップ(相応のネットワーク管理とシステム管理者権限とPHPの知識が必要)はハードルを高くしてしまうので、学習の開始には内蔵ウェブサーバーを使うのが良い選択でしょう。
いまの環境にPHPがインストールされているか確認しましょう。
コマンドラインから
を実行します
もし
PHPは多くのUnixとUnix互換OS、とWindowsのようなUnix非互換OSで動作します。
公式のWindows向けダウンロードページにビルド済みバイナリーが提供されています。
もしあなたが、Microsoft Visual Studio を使っているのであれば、Visual Studio Marketplace から、PHP Tools for Visual Studio 2022をインストールすることで、Visual Studio に統合された、PHP開発環境を使用できます。
もしあなたが、Visual Studio code(vscode)を使っているのであれば、Visual Studio Marketplace から、PHP Tools for Visual Studio Codeをインストールすることで、vscode に統合された、PHP開発環境を使用できます。
PHP は macOS X (10.0.0) から macOS Monterey (12.0.0) までの macOS にバンドルされています。デフォルトのウェブサーバーでPHPを有効にするには、Apacheの設定ファイルhttpd.confの数行をアンコメントする必要がありますが、CGIやCLIはデフォルトで有効になっています(ターミナルプログラムで簡単にアクセスできます)。
macOS Monterey 以降は、標準ではバンドルされていないので、homebrew を使ってインストールするか、ソースコードからビルドします。
ports/pkg コレクションに lang/php81 lang/php81-extensions があります。
portmaster でビルドしインストール
pkg でビルド済みバイナリーをインストール
多くのGNU/Linuxのディストリビューションでは、PHPが標準でインストールされています。
くわしくは、利用中のディストリビューションとパッケージマネージャーのマニュアルを参照してください。
Windows の「メモ帳」(notepad.exe)のようなプレーンテキストの編集できるエディターが必要です。 HTMLの編集ができる環境であれば、そのまま使えます。
内蔵ウェブサーバーは、アプリケーションの開発を支援するために設計されています。また、テスト目的や制御された環境で実行されるアプリケーションのデモにも有用です。このサーバーは、フルスペックのウェブサーバーではありません。公共のネットワークで使用することはできません。
内蔵ウェブサーバーの起動
終了するには
1行だけのプログラムを入力しサーバーを起動します。
ここで、http://localhost:8000/phpinfo.phpをウェブブラウザーで開くと、PHPの諸元が表示されます。
ターミナルを見ると
のように内蔵ウェブサーバーとウェブブラウザーの様子が表示されます。
サーバー停止
コマンドラインから phpinfo.php を実行(先頭五行)。
おなじコードでも、ウェブサーバーからの実行と、コマンドラインからの実行で出力に違いがありますが、実行そのものはできています。
PHPは、ウェブサーバーでコンテンツを動的に生成する用途を念頭に開発されてきましたが、コマンドラインから単独でスクリプトを実行することができます。 このため、PHPをインストールするだけで、コマンドラインでPHPを使えるようになります。 サーバー側での開発が目的であれば、この章はとばしても構いませんが、サーバー側での開発でも、サーバーとの連携に問題があるのか、PHP言語単体でも問題が再現するの障害分離の目的だけでも、コマンドラインからの使用を習得する意味はあります。
次のようなスクリプトを用意します。
PHPにも、対話シェル( Interactive shell )とよばれるREPL( Read-Eval-Print Loop )があり、PHPインタープリターに直接コマンドを与え、即座に応答を得ることができます。

Hello World ハローワールド とは、画面に「Hello World!」と表示するプログラミングの本の最初に書いてあるプログラムです。
PHPのHello Worldプログラムは次のようになります。
上記のコードをテキストエディタで書いて hello1.php の名前で保存します。 これを、ウェブサーバー(CGI/MPM/FastCGIなどでPHPのスクリプトが実行可能にセットアップされているとします)にアップロードし、アップロードされたスクリプトをウェブブラウザで開くと
と表示されます。
あるいは、コマンドラインから
のように実行することができます。
と思った方もおられると思いますが、PHPはHTML(などのテキスト)に様々な処理を加えることで機能する「埋込み型言語」なので、地のテキストをそのまま表示するのはPHPの大事な機能です。
2例目
3例目
4例目
ウェブサーバー(たとえばapacheなど)あるいはコマンドラインから php にスクリプトを与え実行すると、HTMLに埋込まれた <?php から ?>のPHPの疑似タグの間のコードがPHPインタープリターに解釈され、地のHTMLに展開されます。
PHPでは、動的に文字列をHTMLをに埋込むことができます。 埋込まれたPHPのコードがどこに展開されるか見てみましょう。
ここは、phpタグの外です。ここからphpタグ内側Hello World!こんにちはphpタグを脱出。
PHPには、echoとprintと2つの標準出力に表示する機能がありますが、この2つの立ち位置は大きく違います。
PHPタグには、2つの短縮形式があります。
「echo 文の短縮形式」は可読性が高く副作用もないので、積極的に使うべきです。
これに対し「php開始タグの短縮形式」は
PHPは、ただ単純にHTMLに文字列を埋め込めるだけでなく、ループで繰返し構造をHTMLに展開できます。
TABLE要素を使った表組みなどの複合的な構造も、このようにHTMLとPHPのコードが出たり入ったりしながら、編み込むようにコード化します。
WordPressのテーマなどで、より複雑なPHPの(DOMとはまた違った)ドキュメント構造のデザインワークを見ることができます。
このように、PHPはテンプレート記述言語としての特徴を強く持っており、類似のものには ePerl や eRuby のようなスクリプト言語のテンプレート記述拡張がありますが、最初からテンプレート記述言語として設計されているスクリプト言語は、PHP以外に普及例は見当たりません。
PHPのコメントには3種類あります。
コメントは、プログラムのデーターやロジックに影響を与えず、自由な文書をプログラムに含めることができます。 コメントには、なにを書いてもいいのですが、プログラムのロジックをそのまま記すのは、冗長であるうえにコードの変更にコメントが追従せずズレが生じる原因になります。
次のような要素がコメントによく書かれます
[TODO]

変数は、値に名前をつけてプログラム中から参照できるようにする仕組みです。 変数は必ず名前を持ち、名前は識別子のルールに従います。
変数の名前は、$ で始まり識別子が続きます。
識別子は、先頭が _ または英字、それに 0 文字以上の _ または 英数字が続きます。
また、PHPでは、変数名の大文字小文字を区別します。
関数、ラベル、定数、クラス、トレイト、インターフェース、名前空間なども名前を持つことができますが、それぞれ識別子の規則に従います。
変数を使ったプログラム。
ほかの例も下記に見ていきましょう。
これは、変数の文字列への埋込み機能を使うと次のようにも書けます。
print は上位互換で短縮表記もある echo あるの殆ど使われませんが、Cのprintf()/sprintf()と同じ機能の、 printf()/sprintf()がPHPにはあり、書式化出力に便利です。
PHPでは他のプログラミング言語同様、数学風の演算子式で計算を行います。
整数除算は、intdiv(被除数, 除数) です
PHPも、多くのプログラミング言語と同じく演算子に優先順位があります。
は
ではなく
の順で評価されます(それぞれの演算子の優先順位については、後ほど表にまとめます)。
異なる優先順位の演算子であれば、優先順位に従い評価すればよいのですが、同じ優先順位の演算子が続いた場合はどうでしょう。
...これは交換則が成り立つので良い例ではないですね。
は
ではなく
の順で評価されます。このような評価順序の演算子を左結合の演算子と呼びます。
演算子は概ね左結合ですが、少数の例外があります。
これ(代入演算子)は、
の順(右結合)で評価されます。
また、
(冪乗演算子)も
の順(右結合)で評価されます。
リテラルとは、ハードコードされた値のことです。リテラルはスクリプトの中で特定の値を表現する手段となります。例えば代入の右辺には次のようなものがあります。
PHPの型と型名とリテラルの例を示します。
PHPには、$で始まる変数とは別に、イミュータブルなオブジェクト=定数を宣言することができます。
組込み関数 define() を使っても定義できますが
というバグ級の仕様上の問題(8.0.0で一部是正)があります。
const が使えるのであれば、define()は使うべきではありません。
const と似た仕組みに、PHP 8.1.0 以降のクラスのプロパティのreadonly修飾子があります。 ただし、readonly修飾子はプロパティにしか使えません。
また、クラスはクラススコープの定数「クラス定数」を定義することができます。
PHPには9つのマジカル定数( Magic constants )があり、それらは使用される場所によって変化します。 たとえば、__LINE__ の値は、スクリプトのどの行で使用されるかに依存します。 これらの「魔法の」定数は、実行時に解決される通常の定数とは異なり、すべてコンパイル時に解決されます。 これらの特殊な定数は大文字と小文字を区別しません。
今後に使う予定のない変数に unset() 関数を適用することで、明示的にその変数を使わないことを表明できます。 また、unsetした変数に束縛されていたメモリーオブジェクトのリファレンスカウントが一つ減るので、メモリーが開放される可能性があります。
unsetの適用後、変数を参照すると、言語処理系が警告をしてくれるので、バグなどを発見しやすくなります。
ためしに下記コード例では、unsetの適用後、変数を参照しています。
PHPでは、ループ変数のスコープはループではなく関数スコープ(あるいはグローバルスコープ)なので、ループを抜けたあと悪さをしないように、unset() しましょう(ループから脱走したリファレンスを使って代入すると発見困難なバグになります)。
ドメインによっては、 $ループ変数 = null; で標準化していることもありますが趣旨は同じです。
null は、変数の束縛を解く時につかわれ、その意味では unset() と似ています。 NULLが入った変数は、isset()はfalseを返します。
2022年12月現在の最新の安定バージョン v8.1.13 では、未定義(Undefined)の変数参照すると警告( Warning )が出ます。
エラー制御演算子(@)は、名前と機能がやや乖離していて、「メッセージ抑制演算子」程度の機能しかありません。 エラー制御演算子には、トラブルシューティングに役立つエラーや警告を表示させないという害悪があるので、他の方法(例えば例外処理)を検討するべきです。
PHPの値には「型」があります。
どのような型があるか見てみましょう。
PHP では、変数宣言の構文は持ちません。機能的には変数への始めての代入が初期化を伴った宣言とも考えられますが、v8.1の時点でも変数に型を指定したり、型アノテーションを与える方法はありません。 変数に型がない一方、値は必ず型を持ちます。
演算子式を考えてみましょう。
このコードの二項演算子バージョンも書けますが、v7とv8で結果が異なる組合せがあったり、PHPの言語設計の弱点の1つに上げらます。
v8.1で関数の引数と戻値の型を指定する構文が追加されたので、状況はある程度改善されたのですが、変数に型を宣言することは、v8.1(及び開発中のv8.2)でもできません。
配列( array )は、数値や文字列など任意の型の値を順番を持って保持するデーター型です。
配列リテラル( array literal )は、要素を ,(カンマ)で区切り全体を [ ](角括弧) で囲んで表します。 最後の要素のあとの,はあってもなくても構いません。
[0]: 月
[1]: 火
[2]: 水
[3]: 木
[4]: 金
[5]: 土
[6]: 日
$ary[] = 42 は array_push($ary, 42) と同じ意味で、配列変数 $ary の末尾に 42 が追加されます。
数学で、疎行列(スパース行列)と言うと殆どの要素が 0 の行列ですが、PHPの疎な配列は値のない要素がある配列です。
PHPの配列のインデックスに負の整数を使うのは合法です。
配列の中に配列を入れることができ、これは二次元配列になります。
配列の中に二次元配列を入れることができ、これは三次元配列になります。
配列の中に三次元配列を入れることができ、これは四次元配列になります。
...

連想配列( associative array )は、キー(整数や文字列など任意のスカラー型値)と値(任意の型)をペアとした集合を保持するデーター型です。 値は重複して構いませんが、キーは1つの連想配列の中ではユニークでなければいけません。
PHPでは、配列と連想配列の区別がありません。配列は整数をキーとする連想配列です。
連想配列リテラル( associative array literal )は、キー => 値ペアを ,(カンマ)で区切り全体を [ ](角括弧) で囲んで表します。 最後の要素のあとの,はあってもなくても構いません。
Mon => 月
Tue => 火
Wed => 水
Thu => 木
Fri => 金
Sat => 土
Sun => 日
配列の項目で疎な配列と負のインデックスについて扱いましたが、配列がキーを整数に限定した特殊なケースであることがわかると、一見奇異な挙動が、連想配列の基本機能からくるものだったとわかります。このように連想配列のインフラを使って配列を実装している処理系に JavaScript があります。
この実装上の選択の理由はいくつかありますが
⇒ インデックス(=整数値)をハッシュキーとしハッシュテーブル(連想配列)のインフラを使い実装する
プログラミング言語は、丁度楽譜のように左から右、上から下に実行します。 しかし、PHPの最初の目的が静的なHTMLをサーバー側で動的に生成することだったことを思い出しましょう。
次の例は、時刻によって表示するメッセージを変えています。
PHPには、if, switch, match の3つの分岐構文があります。
PHPには、C風のifがあります。else ifの短縮構文があるほか、テキストに埋込むのに適した代替構文があります。
例:
PHPには、C風のswitchがあり、フォールスルーの挙動などほとんど同じですが、case の式に定数式以外の式が使える他、文字列などの比較も「緩やかな比較」で行えます。
PHPのmatchは、switchと似ていますが、文ではなく式なので値が取れるほか、比較には「厳密な比較」が使われます。
matchには、代替構文も埋込み構文もありません。
if や while なでの条件式で、使われる比較演算子には2種類あります。
なお、=等号1個は単なる代入命令ですが条件式で使われると代入された値を真理値として評価されます。
==は、型を厳格には区別しない「緩やかな比較」演算子です。
===は、型まで一致していることを要求する「厳密な比較」演算子です。
!==は型まで一致していない、あるいは値が一致していないと真をかえす演算子です。
PHPは、基本機能としてセッション管理機能を提供しています(認証機能ではありません)。
プログラミング言語は、丁度楽譜のように左から右、上から下に実行します。 しかし、PHPの最初の目的が静的なHTMLをサーバー側で動的に生成することだったことを思い出しましょう。
次の例は、九九表をWiki記法のテーブルとして生成します。
PHPには、while, do-while, for, foreach の4つの反復文と、break, continue の2つの反復制御文があります。
また、goto 演算子はありますが、ループからの大域脱出はbreak, continue の引数(オプション;ディフォルトは 1)でループのレベルを変えるなど、goto が使われがちな状況に代替手段を提供しているので、ほかのプログラミング言語ほど goto の出番はありません。
PHPの反復文や複文は、スコープを持ちません。
whileは、まず条件式を評価し、真なら続く文(単文あるいは複文)を実行し条件式を再び評価します。もし、偽ならばループの次に移ります。
do-whileは、文(単文あるいは複文)を実行し条件式を評価します。真なら文を再び評価します。もし、偽ならばループの次に移ります。
forは、C風の3つの項を持つfor文です。
#whileの例と同じロジックを for(;;) で書き直しました(結果は同じなので省略します)。
foreachは、配列に代表される「反復可能オブジェクト」(iterable object)を反復します。
foreachには、配列版と連想配列版があります。
ループ変数を、参照にすることで配列の要素を変更できます。
PHPでは、ひとまとまりの処理に名前をつけ、あとから何度も呼出せるようにする仕組みがあります。 これを関数(かんすう;【英】Function)といいます。 関数を作ることを、「関数定義」関数を使うことを「関数呼出し」といいます。
PHPには、すでに有用な関数が多数用意されており、これらを「組込み関数」と呼びます。
プログラマーは、組込み関数・文・式を組合わせて新しい関数を定義することができます。 新しく定義された関数を「ユーザー定義関数」と呼びます。
上のプログラムは、次のようにもかけます。
関数は、呼出し元に値を返すことができます。 値を返すには return文を使い、returnは単一の式を取ります。 もし、returnに値を与えないと、その関数の戻値型は void 型となります。
例えば、下記のコードは、単純に関数fが1を返す関数です。
PHPの関数は、0個以上の引数を渡し1つの戻値を返すことができます。 可変長引数や引数のディフォルト値、またキーワード引数もサポートしています。
型宣言は、関数の引数や返り値、そして PHP 7.4.0 以降ではクラスのプロパティに追加することができます。 これらは、呼出し時に指定した型の値であることを保証し、 一致しない場合は TypeError がスローされます。 strict_types を 1 にセットすると、型宣言漏れをエラーにできます。
プリミティブ型のほか、クラスやインターフェースの名前は、型名として認識されます。
PHPでは、名前空間のトップレベルで代入された変数をグローバル変数と呼び、関数内で代入された変数をローカル変数と呼びます。 PHPに変数宣言はないので、最初の代入が宣言に準じた扱いになります。 関数内のローカル変数は(static 宣言されなければ)動的で、関数を抜けると揮発します。 関数の中から、グローバル変数を参照するには、3つの方法があります。
3つ方法がありますが、どれも使わないと関数からのグローバル変数の参照は PHP Warning: Undefined variable $eeeになり失敗します。
関数の内側で作られた変数は関数を抜けると揮発します。
関数から抜けても、次回の呼出しで値を保持してほしいときは、ローカル変数を static 宣言します。

関数の中で関数を定義してもクロージャーにはなりませんが、無名関数でクロージャーを実現できます。 PHPには、無名関数を定義する方法に、アロー関数と関数式の2つがあります。
関数は、自分の定義の中に自分を含めることができます。
ジェネレター関数は、値を返す代わりに、yieldで必要なだけの値を生成することを除けば、通常の関数と同じように見えます。 yieldを含む関数はすべてジェネレター関数です。
ジェネレター関数が呼出されると、繰返し実行可能なオブジェクト(iterable型のオブジェクト)が返されます。 そのオブジェクトに対して反復処理を行うと (たとえば foreach ループで)、 PHP は値が必要になるたびにオブジェクトの反復処理用メソッドをコールし、 ジェネレターが値を返した時点でその状態を保存して、次の値が必要になったときに再開できるようにします。
生成する値がなくなったら、ジェネレターは単に終了し、呼出し元のコードは配列の値がなくなったときと同じように続行できます。
ジェネレターは配列に似ていますが、配列は 要素数 × 要素1つあたりのサイズ のメモリーフットプリントを消費します。それに対しジェネレターは、yield で返す値は都度計算できるのでメモリー消費は配列に比べ小さくなります。
まとまった規模で、実用的な目的に叶うコードを読まないと機能の存在理由などの言語設計に思い至りにくいので、コードの断片から少し踏み込んだプログラムを掲載します。
PHPの組込み関数には、array_reduce(),array_map() のように array_ はじまる配列関数群があります。 これらは便利なのですが、配列とハッシュ兼用でJavaScriptやRubyなどから来ると面食らうことがあります。 また、配列の添字がcallback関数にわたらない仕様も移植のときに問題になります。 そこで、上記の問題をクリアした配列専用の関数群を作ってみました。 また、sum() は、カハンの加算アルゴリズムを使い誤差を最小にするようにしています。
たとえば、htmlファイルとして
のようなhtmlファイルを書き、◯◯.html でドキュメントルートにアップロードする。たとえば myform.html というファイル名だとしよう。
なお、このコードの表示するページは、
のようにレンダリングされます(ブラウザによって表示内容の細部は異なります)。
さて、http://localhost/formtest.html にウェブブラウザでアクセスして、ウェブブラウザで見たときに「登録」と書いてあるボタン 登録 を押すと、ページが切り替わり、「catchTest.php」から作成されたhtmlファイルのウェブページに切り替わる。
form action="catchTest.php" method="post" のプロパティ内容にしたがって、そういう処理がされている。
type属性がtextのinput 要素は文字列入力欄で、 のようなレンダリングがなされ、1行の文字列が入力できます。
登録
input要素の属性nameは、ページ外部とデータのやり取りをするための名前。
しかし、これだけだと、まだPHPファイルが無い。
このように、 $_REQUEST['名前'], でHTMLフォームからの入力を受け取れる。もちろん、引数の名前は、html側で、input要素のnameプロパティで定義したものでなければならない。
さきほどの登録ボタンのあるページで、ボタンを押すと
というふうに、画面がphpのページに遷移して、◯◯の部分にインプットボックスにある文字列を入れた結果が出て来る。
なお、遷移先のphpのページでブラウザのソース表示の機能を使用しても
(◯◯の部分には、入力した文字列が入る)のように、サーバーによって生成されたhtmlが表示されるだけであり、もとのPHPソースコードはサーバー側には表示されない。
また、ブラウザで直接
にアクセスしても、
と表示されるだけである。
そのページのソースコードをウェブブラウザで見ても、
と表示されるだけである。
変数名などはブラウザ側では表示されないが、echoのテキスト文字列などは表示されてしまうので、けっして機密情報などをechoテキスト文字列に入れないように注意する必要がある。
念のため、サーバーアプリ作成後にはソースを見てみるのが安全である。

PHPには、(サーバー側にある)ファイルを読書きする機能があります。

PHPをウェブサーバー上で動かしている場合のファイル書込みは、セキュリティ上の驚異に直結するので慎重になるべきです。
ここでは、ごく小さな永続オブジェクトが必要な、アクセスカウンターを例に取ります。

このコードには以下のような欠点があり、アジャイルにはともかく実務には使えません。
PHPでダウンロードをブラウザに問いかけるには、下記のように header 関数というのを使って、ブラウザに問い掛けできます。
書式は
です。
実験のさいには、あらかじめ画像データを作成しておいてください。
そして、ブラウザから、上記のPHPを実行します。(コマンドラインから実行しても、意味不明の文字列が表示されるだけです。)
成功すれば、ページ起動時に
と出て、「キャンセル」または「OK」のボタンが出てきます。
Content-Type: application/octet-stream の 「octet-stream 」は、種類を特定しないバイナリデータであることを宣言しています。画像データなどをダウンロードさせたい場合は画像ならバイナリ形式ですので、この 「octet-stream」を指定してもダウンロード可能です。
ダウンロードしたいファイルのファイル形式によっては、Content-Type で具体的に指定することもできます。
画像の場合、
画像以外でも、
さて、
は、ダウンロードしたときのファイル名を上記コードでは $fname で指定しています。なので、ほかの名称でも構いません。たとえば
とすれば、ダウンロードされたファイル名は「test」になります。
ダウンロード開始は readfile関数でなくても、 file_get_contents 関数でもダウンロード問い掛けを出来ます。
環境や、アップロードするファイルの種類によっては
が必要です。
これがないと、ファイルにバッファ内の余計なデータがついたままブラウザに送信されてしまい、ダウンロード自体はできても、読込みエラーになってしまい、さっかくダウンロードした価値が無くなってしまいます。

上記のコードだと、ページが表示される前にダウンロードが始まってしまう。そのため、とても見づらくなります。
上記のPHPコードにprintなどの命令を書いても、うまく動作しないです。(基本的に、ダウンロード用のリンクでは、画像表示や文字表示は、あまり機能しないです。)
実務的な方法としては、別のHTMLファイルで上記PHPコードにアクセスするリンクを配置し、
のようにして、このHTMLファイルに先にリンクしてもらうようにするのが良い。
すると、先にこのHTMLだけが表示されます。
そして、「ダウンロード」リンクをクリックすると、ページはそのままで(このHTMLが表示されたままで)、ダウンロードのポップアップが出るので、あとはブラウザ側でユーザーにダウンロードしてもらえば済む。
PHPは、複数のRDBMSとの連携機能を持ちます。 連携の方法として
の2つがあります。
PHP5.4以降のPHPには、標準でSQLiteへのインタフェースが付属しています。
SQLiteは、以下のような学習用途に適した特徴を持っています。
SQLiteの特徴としては、
sqlite3 が、SQLite3のデーターベースの保守管理を行うコマンドラインインターフェースです。 sqlite3 が、アプリケーションプログラムがリンクされるわけではありません。 sqlite3 自身も、SQLite3がリンクされた、アプリケーションプログラムの1つだと言えます。
PHPは、SQLite3クラスでSQLite をサポートしています。
PDO(PHP Data Object) は、PHPに拡張モジュールとして標準で提供されているデーターベース抽象化レイヤーの1つです。 各種データベースへの接続を抽象化して、ユーザーコードからDBMSの違いを隠蔽します。 PDOは、オブジェクト指向のAPIを提供します(手続き指向のAPIはありません)。
同内容で、HTMLに出力してみましょう。
PHPとMySQLを連携するには、MySQLのインストールとセットアップが必要です。
MySQLiは、以前のMySQLを強化しMySQL 4.1 以上で提供される機能を利用できるようにした拡張モジュールです。 MySQLiは、拡張モジュールなのでPHP本体とは別にインストールする必要があります。 オペレーションシステム/ディストリビューションのパッケージ管理システムでパッケージの検索・インストールを行った後にセットアップを行います。
MySQLには、オブジェクト指向のAPIと手続き指向のAPIの2つのAPIがあります。
コンストラクターとプロパティは、アクセス修飾子を指定することで同時に定義できます。 また、readonly修飾子で初期値から変更できないプロパティを作ることもできます。
インスタンスを参照する変数が1つもなくなると、インスタンスは回収されます。 そのタイミングで資源を返すためのデストラクターが呼出されます。 また、readonly修飾子で初期値から変更できないプロパティを作ることもできます。
__setと__getは動的プロパティへの代入と参照をインターセプトする特殊関数で、いわゆるアクセサです。
object (の公開プロパティ)を array(連想配列)に変換したり、array(連想配列)を object に変換することができます。 これは、「オブジェクトの配列」を使いたい場合、簡素に表現することを可能にします。
PHPの object は array と同じくイテレーション可能です。 object は、foreach で反復可能です。
クラスの継承に当たっては、可視性のコントロールに注意が必要です。
プロパティ(インスタンス変数)は、それぞれのインスタンスを構成する要素ですが、クラスに属する変数=クラス変数、そしてクラスに属する定数=クラス定数を定義することができます。
__ からはじまるメソッドは、マジックメソッドといい処理系が特定のタイミングで暗黙に呼出します。 このまでに紹介した、コンストラクターもデストラクターもマジックメソッドです。
__toStringは、文字列を必要とする文脈にオブジェクトがあると呼出されます。
Trait はクラスと似てプロパティやメソッドを持てますが、インスタンス化できず、継承元にも継承先にもなれませんが、クラスが use してプロパティとメソッドをMixinできます。
Interface はメソッドの宣言だけを行い、クラス定義で Interface を implements 句で指定した場合、そのクラスは Interface で宣言したメソッドを定義しなければいけません。定義しないとエラーになります。
前二節で解説した Trait と Interface を参照したクラスの例です。
Enumをクラスと一緒に解説するのは奇異に感じられるかもしれませんが、言語処理系としては、Enumはclassのインフラを使って実装しているので、メソッドやメソッドのアクセス記述子などの働きは同じです。
今節で取り上げた case に値を与えない Enum を Pure Enum といいます。 Pure Enum は UnitEnum interface の Implement です。
前節で紹介したEnumのように case が特定のスカラー値と結びついていない Enum を Pure Enum といいます。 これに対して、これから紹介する case にスカラー型とスカラー値を明示した Enum を Backed Enum といいます。
機能的には連想配列と似ていますが、連想配列はキーが重複しないことが保証されますが、Backed Enum は case が重複しないとともに、value も重複しないことが保証されていることが異なります。
Backed Enum は BackedEnum interface の Implement です。
まとまった規模で、実用的な目的に叶うコードを読まないと機能の存在理由などの言語設計に思い至りにくいので、コードの断片から少し踏み込んだプログラムを掲載します。
PHPには複素数がないので、クラスとして実装しました。 ただ、8.1.13 の時点ではまだ演算子オーバーロードはないので、$x->add($y) のようにメソッドで実装しました。
図形クラス(Shape)から正方形(Square)や楕円形(Oval)などを派生しています。 Shape自身は、interface Areable の実装で、Areableは共通するメソッド area()を定義しており、area() を実装しないとShapeから派生できません。