
2026/05/20 5:41
PHP の奇抜な特徴
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
本文は、PHP が不当に低い評判を受けていると主張しており、一方で成熟した言語であり、他の現代技術と同等の多様性を備えていると述べています。Laravel などの強力なフレームワークや低摩擦点を賞賛する一方で、著者は開発者に重大な障壁を生み出している特定の設計選択を強調しています。核心的な問題は、標準ライブラリが伝統的な配列ではなく順序付き辞書に依存しており、データをソートやフィルタリングする際に予期せぬ挙動を引き起こすことです。さらに、PHP の型システムは初期化されていないプロパティへのアクセスに対し fatal エラーを発生させることで null を返さないよう強制し、エンジニアが膨大な防御的チェックを書くことを余儀なくさせます。この摩擦は、PHP 5 および PHP 7 で型を導入しましたが、古い動的振る舞いを完全に排除できず、その歴史から生じています。これらの矛盾を解決するために、著者は nullable タイプがデフォルトで null となる一方で、non-nullable タイプは厳密に初期化が必要であるという明確なアプローチを提案しています。このような設計パターンを実装することで、複雑性を削減し、メンテナンスを簡素化するとともに、PHP フレームワークを使用する組織が開発サイクルの速度低下を防ぎ、 cumbersome な状態管理から回避できるようになります。
本文
PHP 開発者による深層考察:奇妙な配列と不親切な型システム
著者が 5 年間 PHP で業務開発に従事し、PHP は成熟しており広く採用されている言語であることを再確認したエッセイです。しかし、実務経験から特に深刻と感じた「配列の挙動」と「型システムの弱点」について解説します。
1. 奇妙すぎる配列(Arrays)
本当は辞書構造
PHP の標準ライブラリにおけるデータ構造と言えば、基本的に**「配列」**のみです。 これは意図的な設計で、順序付きキー・バリューの辞書として機能し、メモリブロックに割り当てられた固定サイズのオブジェクトコレクション(従来の意味での配列)とは異なります。
$fruits = ["apples", "oranges", "limes"]; // カウント・アクセス・プレビューは可能 count($fruits); // 3 $fruits[0]; // "apples" print_r($fruits); // Array(...)
インデックスの欠陥:柔軟性の代償
「単純な」配列を改変(mutations)すると、動作はキーと値の両方に影響を与えます。インプレースの変更や関数の返り値によって、キーの順序が整合性を失いしまいます。
// フィルタリング後に配列がおかしくなる $filteredFruits = array_filter($fruits, fn ($name) => str_contains($name, "limes")); print_r($filteredFruits); /* Array( [2] => limes ) */ // 最初の要素がアクセスできない! print($filteredFruits[0]); /* PHP Warning: Undefined array key 0 */ // unset で削除するとインデックスも空く unset($fruits[0]);
修正の義務:array_values()
これらの配列を自然な連続したインデックス(
[0], [1]...)に戻す唯一の方法は、array_values() 関数を使用することです。これを怠ると微細なバグが発生します。
// 正しい再帰的アプローチ $filteredFruitsFixed = array_values($filteredFruits); // Array( [0] => limes ) $fruitsFixed = array_values($fruits); // Array( [0] => apples, [1] => oranges, [2] => limes )
PHP は単純なコレクションをサポートしていないため、99% のケースで順序索引化を望んでも無理があります。まるで**漏れのある抽象(leaky abstraction)**のように感じられます。
2. クラスのプロパティの型は混乱を招く
型システムの複雑さ
PHP7 でクラスプロパティの型定義が可能になりましたが、動的に型付けされた言語に基づいているため、以下の矛盾があります。
- レギュラー設計ではなく、既存の実装後からルールを適用するため。
- **未初期化(uninitialized)**という隠れた状態が発生する。
Book
クラスのトリッククイズ
Book3 つの文字列プロパティを持つクラスを定義した際のプロパティの状態の違いを確認します。
class Book { public $title; // 1. × untyped(レガシー) public string $author; // 2. ○ typed (string) public ?string $publisher; // 3. ○ nullable typed (?string) }
インスタンス化後のプロパティの状態:
| プロパティ | 定義タイプ | デフォルト値 | 動作特徴 |
|---|---|---|---|
| untyped | | 値を持っている(空文字列扱い) |
| typed () | 未定義 | アクセス不可(Fatal Error) |
| nullable () | 未定義 | アクセス不可(Fatal Error) |
Fatal Error が起きる理由
初期化されていない typed プロパティにアクセスすると、致命傷エラーが発生します。これは
NULL チェックとは異なる状態です。
$b = new Book(); // title: is_null は true になる(NULL なので OK) print("title is null: " . is_null($b->title)); /* title is null: 1 */ // author: 初期化されていないためアクセス不能 print("author is null: " . is_null($b->author)); /* PHP Fatal error: Typed property Book::author must not be accessed before initialization... */ // publisher: 同上
実務での困難さ
この挙動により、防御的なコード撰寫が難しくなります。特に動的に追加されたプロパティが存在する場合、どの関数がどの状態をカバーするか判断が複雑になります。
is_null()isset()property_exists()empty()
これらの関数を組み合わせる必要があり、開発負荷が増大します。著者は**「未初期化という状態はもともと必要なかった」**と主張しています。Nullable 型はデフォルト値を
null に設定し、非 Nullable 型はコンスストラクターでのパラメータ定義やデフォルト値宣言を求めるべきだと考えます。
3. 結論
PHP を批判するに足る点がある一方で、著者は**「不当な恨めしさ(undeserved hate)」**であると信じています。どんな言語でもトレードオフはありますが、PHP でも他の言語と同じタスクを達成可能です。
PHP の良い点
- 開発摩擦力が低い: スクリプトランゲージであり、ファイルを編集すれば即座に効力を発揮します。
- Laravel は優秀: 拡張性が高く実用的なウェブフレームワークです。「自動魔術的」と言われるスタイルでも設計は丁寧です。
- 型ヒントの利点:
が付いていることで、日々の業務の目的がいつも思い出せると助かっています 🤑以下の型宣言
言語の特性を理解し、イディオマティック(idiomatic)なコードを書くには、その弱さと強さを知る必要があります。