PHP本格入門の私家版正誤表
このページには「PHP本格入門」に含まれる誤りを集めています。この本には2020年の現代的なPHPコミュニティの価値観とも反する点が多くありますが、このページにおいては明確に間違いといえる点に絞ってリストアップしています。
1-3 WebサーバーとPHP (p38-40)
p38下部からはじまる「PHPモジュールを介してPHPプログラムが実行される」という説明は妥当です。
しかし、直後の1-3-2 PHPの2つの実行方法 - CGI版とCLI版という説明は不適切です。
Apacheに組み込むPHPモジュールは、CGI版のものです。OSコマンド(phpコマンド)で実行できるCLI版は、バッチ処理(Webページを介さずに、オフラインで定期実行される処理)などを実行する目的で使われます。
(PHP本格入門 上, p39より引用)
本書では触れられていませんが、PHPの実行環境の違いはSAPI(Server API)といいます。 CGIはHTTPリクエストの度にプロセス(PHPであればphp-cgiというコマンド)を起動するという実行であり別物です。 CGIは実行効率の問題で避けられがちですが、共用のレンタルサーバなどでは現役です。
なお、モジュールとCGIの違いについてはパーフェクトPHPでは明確に説明されています。
PHPでWebアプリケーションのコードを書く上では「CLIとそれ以外」という捉え方で概ね支障ありません。
1-4 XAMPPによる開発環境のセットアップ (p41-)
上記の説明の通り、Apacheモジュール版PHP(apache2handler)とCGI版PHP(php-cgi)は別物です。
XAMPPに含まれているApacheには、すでにCGI版のPHPモジュールが組み込まれています。
(PHP本格入門 上, p41より引用)
XAMPPのApacheにPHPモジュールが組み込まれているのは正しいですが、それはCGI版ではありません
XAMPPにはphp-cgiコマンドも同梱されているのでCGIとして動作させることも可能ではあります。
特別な事情がない限りそんなことをするメリットはまったくありません。
どうしても必要ない限りはやらないでください。
2-1-2 変数の値を出力する - echo命令、print命令
PHPにはディレクティブという用語があり和訳すると「命令」に近い語なので適切な語選択ではないように思われます。 ドットの方が値の連結コストがかかるので、カンマよりも若干スピードが落ちます。カンマを使えるechoの方がわずかにアドバンテージがあるので、本書では基本的にecho命令を使うことにします。
出力する文字列の大きさにもよりますが、ほぼほぼ誤差です。
printよりもechoの方が文字数が少ないのでタイプ数が少なく済むということであれば同意します。
2-1-3 デバッグのための変数の情報を出力する - var_dump命令
var_dump()は関数であり、上記と同じく「命令」と呼ぶことも、echo/printと同一視することも適切ではありません。
この例に限っていえば問題はありませんが、var_dump()の出力は基本的にHTMLエスケープが施されていませんので、意図的に<p></p>の中に囲って出力するのが教育的に良い例だとは私には考えられません。 code:hello/dump.php
<body>
<?php $total = 500 * 1.08 ?>
<p><?php var_dump($total);?></p>
</body>
(PHP本格入門 上, p65より引用)
2-2-1 単一のデータを保存する - スカラー変数とデータ型
PHPはPerlではないので、スカラー変数/配列のような区別はありません。
本書でこれ以降のスカラー変数という用語を用いた文章で何を説明したいのか不明瞭です。
2-7-2 値のデータ型を変換する - キャスト
「値のデータ型を変換する」という表現は正しいです。
$valという変数を変換する場合、型キャスト、関数の記法はそれぞれ以下のようになります。
• 型キャストで変換する場合 → (int)$val
• 関数で変換する場合は→ intval($val)
(PHP本格入門 上, p72より引用)
型キャストならびに関数のどちらも「変数を変換する」という機能を提供するものではありません。それぞれの結果を再代入などしなければ変数の内容などに作用するものではないからです。
型キャストは高速だが関数の方が見やすい
(PHP本格入門 上, p73より引用)
これはPHP7ではintval()の呼び出し(基数指定なしの場合)はオペコードコンパイル時に型キャストに変換されるので実行時に差が出ることはできません。
ただしこれには条件があって、namespace内のコードでは ns\intval()のような関数呼び出しになるのでキャストには変換されません。
これを避けるにはuse function intval;するか、\intval()のように\を前置すると確実にできます。
本書では下のChaper 8以外ほどんとnamespaceが出てくることはありません。
最適化しなかったとしても実行時にボトルネックになるような速度差が生じるとは考えにくいです。
2-2-8 複数の値を順序立てて保存する - 配列
スカラー変数は単一の値を保存するためのものでしたが、2つ以上の同じ種類の値をまとめて扱いたいときもあります。そんなときに使うのが、配列です。スカラー変数が1つの値を入れる容器のイメージであるのに対して、配列は引き出しのようなイメージです。それぞれの引き出しには、0から始まる番号が振られています。
(PHP本格入門 上, p75より引用)
変数と配列は同列に並べるような概念の存在ではありません。説明の便宜のために独自の用語を導入しているのだとしても何を指しているのか不明瞭ですし、PHPの実際とも反しています。
2-3-13 論理演算子と命令文の組み合わせで、シンプルな条件分岐を表す (p105)
メッセージを表示して処理を中断するdie命令(2-4-7項)との組み合わせで以下のように書くのも、よく使われるイディオムです。
code:php
defined(〜) || die('エラーメッセージ');
(PHP本格入門 上, p106より引用)
dieはexitのエイリアスです。
このコードは動作しますが、異常状態からの回復や事後処理が困難になるため、現代的なPHPでは好まれません。
2-6-14 クロージャーをcallable型の引数として渡す (p165-167)
型宣言されているように、クロージャーはcallableというデータ型の1つです。callableは、クロージャーも含めた、コール可能な関数を表す特殊なデータ型です。
(PHP本格入門 上, p167より引用)
クロージャーはClosureオブジェクトです。callableは特定のデータ型ではなく、特殊な複合型です。
2-7 共通部分を外部ファイル化し、プログラム間で共有する - require命令、include命令 (p170)
この章以降dirname(__FILE__)が頻出していますが、これはすべて__DIR__で書くことができます。
パフォーマンスという意味で気にするべきことはほぼありませんが、わざわざ長く書く意味は皆無です。
3-9 インスタンスとの付き合い方 - オブジェクト型変数の性質 p300
「オブジェクト型変数」という種類の変数が存在するわけではありません。
PHPマニュアルでは以下のように説明しています。
PHP 5 でのオブジェクト指向プログラミングのポイントとしてよく言われるのは 「オブジェクトはデフォルトでは参照渡しとなります」ということです。 しかし、正確には少し異なります。 この節では、いくつかの例を用いてその誤解をといていきます。
本書のこの章の内容は間違いだとまでは言えませんがPHPマニュアルとは別の用語を以て説明しています。
4-1-3 関数の構文を理解する
Note データ型「mixed」の表記について
引数/戻り値のデータ型が特に定められていないときはmixedというデータ型で表記します。ただし、mixedはあくまで表記上の都合で使われるデータ型であり、PHPの文法上、存在するデータ型ではありません。
本書が対象とするPHP 7.2の時点での用法としては上記の説明は適切です。
これまではPHPマニュアルおよびPHPDocで使われていた仮想的な型でしたが、正式にトップ型として定義されたということです。