この記事の最終更新日: 2025年5月9日

PHPはバージョン8.1以降、言語レベルではネイティブなGenericsをサポートしていませんが、DocBlockアノテーションを通じてPHPStanやPsalmといった静的解析ツールがGenerics型を解釈し、型安全性を大幅に向上させています。さらにRFC「Generic Types and Functions」提案によって、将来的なネイティブサポートの実現にも期待が集まっています。本記事では、現状のDocBlockベースの使い方から静的解析ツール別の設定、将来展望までを網羅的に解説します。
1. PHPにおけるGenericsの概念とRFC提案
PHPの公式仕様にはGenericsが実装されていませんが、RFC「Generic Types and Functions」では、Collection<T>
のようなジェネリック型を言語機能として導入する案が提示されています。これにより、エンティティごとにコレクションクラスを作成する手間を省き、重複コードを削減できます。
DocBlockレベルでは、@template
タグを用いて型パラメータを定義し、@param T[] $array
や@return T|null
で型情報を明示する運用が主流です。これを静的解析ツールが解釈することで、実行時に近い型安全を確保できます。
2. DocBlockベースのジェネリクス仕様
2.1 基本パターン
/**
* @template T
* @param T[] $array
* @return T|null
*/
function first(array $array) {
return $array[0] ?? null;
}
上記の宣言により、first([1,2,3])
はint|null
、first(["a","b"])
はstring|null
として扱われます。
2.2 制約付きGenerics(Upper Bounds)
特定の型を継承・実装したオブジェクトのみを受け付けたい場合、of
キーワードで上限制約を設定できます。以下はException
のサブクラスに限定する例です。
/**
* @template T of \Exception
* @param T $exception
* @return T
*/
function wrapException($exception) {
return $exception;
}
2.3 共変・反変(Variance)
ジェネリクスの共変性を@template-covariant
、反変性を@template-contravariant
で指定し、APIの柔軟性を高めることが可能です。
/**
* @template-covariant T
*/
interface Collection {}
3. PHPStanでのGenericsサポート
PHPStanはGenericsに関する設定が豊富です。
@template
/@phpstan-template
で型パラメータを宣言可能- エラー無視設定:
generics.notGeneric
やmissingType.generics
をignoreErrors
で抑制
parameters:
ignoreErrors:
- '#generics\.notGeneric#'
4. PsalmでのGenericsサポート
Psalmでは@psalm-template
タグを活用し、より細かな型制御が可能です。
/**
* @template T
* @psalm-param T $value
* @psalm-return T
*/
function mirror($value) {
return $value;
}
5. Iterable型・ユーティリティ型との組み合わせ
DocBlockでは、イテラブルやマップ型のキー・値を型安全に扱う記法が用意されています。
/** @var iterable<string, User> $usersById */
PHPStanではCollection<int, Type>
のようにジェネリックなコレクションを記述可能です。
6. 現状と将来展望
DocBlockベースのGenericsは現場で広く活用されていますが、あくまで静的解析ツール依存です。The PHP Foundationのレポートでは、Javaに近いDocBlockGenericsの利点と、ランタイム影響がない制約が指摘されています。
Generics導入によるエンジン負荷とコミュニティ要望のバランスは今後の課題として議論中です。
7. ベストプラクティス
- DocBlockで必ず型パラメータを定義する。
- 上限制約(
of
)で安全性を強化する。 - 共変(
@template-covariant
)/反変(@template-contravariant
)の適切な設定。 - エラー無視は最終手段として利用。
- RFC提案動向をウォッチし、将来的な言語機能対応を見据える。
8. まとめ
現状のPHPでは、DocBlockアノテーションを通じたGenericsサポートが最前線です。PHPStanやPsalmの設定を使いこなし、コードの型安全性と可読性を両立させましょう。将来のネイティブGenerics実装にも備え、ジェネリクス設計を積極的に取り入れてください。
出典
- RFC: Generic Types and Functions – https://wiki.php.net/rfc/generics
- Psalm: Templated Annotations – https://psalm.dev/docs/annotating_code/templated_annotations/
- PHPStan: Generics in PHP using PHPDocs – https://phpstan.org/blog/generics-in-php-using-phpdocs
- PHPStan: Guide to Call-site Generic Variance – https://phpstan.org/blog/guide-to-call-site-generic-variance
- PHPStan: Error Identifier generics.notGeneric – https://phpstan.org/error-identifiers/generics.notGeneric
- PHPStan: Generics By Examples – https://phpstan.org/blog/generics-by-examples
- StackOverflow: Generics on Interfaces – https://stackoverflow.com/questions/76921179/generics-on-interfaces
- PHPStan: PHPDoc types – https://phpstan.org/writing-php-code/phpdoc-types
- The PHP Foundation: State of Generics and Collections – https://thephp.foundation/blog/2024/08/19/state-of-generics-and-collections/
- Reddit: Generics via Attributes in PHP – https://www.reddit.com/r/PHP/comments/yi9g9v/generics_via_attributes_in_php_can_we_have_them

大阪のエンジニアが書いているブログ。
コメント