PHP の型宣言(strict_types の使い方)を徹底解説!初心者でもわかる型の指定方法
新人
「PHPの型宣言って何ですか?」
先輩
「PHPの型宣言は、変数や関数の引数に決まったデータの種類(型)を指定する機能です。」
新人
「型って具体的に何ですか?」
先輩
「例えば、数字や文字列など、データの種類のことだよ。PHPでは、型宣言を使うと、決まった型のデータしか受け付けないようにできるんだ。」
新人
「それを使うとどんなメリットがあるんですか?」
先輩
「じゃあ、具体的に型宣言のメリットを見ていこう!」
1. PHPの型宣言とは?
PHPの型宣言とは、「この入れ物には、この種類のデータだけを入れる」と最初に約束しておく仕組みです。具体的には、関数の引数や戻り値に型を指定して、数字なら数字、文字なら文字だけを受け渡しします。これにより「思っていた型と違ったせいで計算に失敗した」「表示が崩れた」といった初歩的なミスを早めに防げます。まずは名前シールを貼る感覚で、どの箱にどんな中身を入れるかを決めるイメージをつかみましょう。
代表的なデータの種類(型)は次のとおりです。
- 整数(
int) - 小数(
float) - 文字列(
string) - 真偽値(
bool) - 配列(
array) - オブジェクト(
object) - 呼び出し可能なもの(
callable)など
最小サンプル:引数と戻り値に型を付けると「意図」がはっきりする
<?php
// 総和を計算する関数:配列だけを受け取り、整数を返す
function total(array $numbers): int {
$sum = 0;
foreach ($numbers as $n) {
$sum += $n; // ここでは整数の足し算を想定
}
return $sum; // 戻り値は必ずint
}
// 正しい使い方(配列を渡す)
echo total([3, 4, 5]); // 12
// 間違った使い方の例(説明のみ):文字の列などを渡すと型が合わず失敗
// echo total("3,4,5"); // ←型の不一致でエラー(後の章で詳しく)
?>
- 引数:関数に渡す入力。上の例では
$numbers。 - 戻り値:関数から返ってくる結果。上の例では合計の整数。
- 型宣言:受け取る型や返す型を、
array・intなどで明記すること。
まずは「数字は数字のまま」「文字は文字のまま」という前提をコードに書き込むだけで、読みやすさと安心感がぐっと上がります。以降の章で扱う細かなルール(厳密なチェックの有無など)は、一歩進んだ話として覚えていけば十分です。
2. 型宣言を使うメリット
型宣言は「この関数は何を受け取り、何を返すのか」をコードにハッキリ書き残す仕組みです。実はこれだけで、チームでも一人開発でもミスがぐっと減ります。初心者ほど、意図が伝わる書き方=型を付けると覚えておくと安心です。
■ まずは短い比較サンプル
同じ「合計する」関数でも、型の有無で読みやすさが変わります。
<?php
// 型なし:読み手は「何を渡してよいか」を推測する必要がある
function total($a, $b) {
return $a + $b;
}
echo total(10, 5); // 15(たまたま動く)
echo total("10", "5"); // これも動くので、誤入力に気づきにくい
// 型あり:引数と戻り値の「約束」を明文化
function totalTyped(int $a, int $b): int {
return $a + $b;
}
echo totalTyped(10, 5); // 15(意図が明確)
上の例では、型を付けた totalTyped() の方が「整数を受け取り、整数を返す」ことがひと目で分かります。レビューや後からの読み直しでも迷いません。
■ 型宣言で得られる具体的な効果
- エラーを未然に防げる ― 間違った型のデータが渡ると早い段階で気づける。テストやレビューでの発見もしやすい。
- コードの可読性が向上する ― 引数・戻り値の型が明確なので、関数の役割や前提条件が“説明書なし”で伝わる。
- デバッグがしやすい ― 受け取り方が決まっているため、原因の切り分け(入力か、処理か、出力か)がラク。
- 保守と拡張に強くなる ― 将来の仕様変更時も「どの型が影響するか」を追いやすく、破壊的変更を避けやすい。
- ツールの支援を受けやすい ― IDE の補完や静的解析が働き、タイポや渡し間違いを早期に指摘してくれる。
- 「この関数は何用?」と迷ったら、引数と戻り値に型を付けて“用途の一言メモ”にする。
- 数値計算や文字列操作など、扱うデータが決まっている処理ほど型宣言の効果が大きい。
- まずは基本型(
int/float/string/bool/array)から付けるだけでOK。
3. strict_types の基本的な使い方
PHPでは、strict_types を使うことで、型の厳密なチェックを行うことができます。通常、PHPは型を自動的に変換しますが、strict_types=1 を指定すると、決められた型以外のデータは受け付けなくなります。
■ strict_types を有効にする
ファイルの一番上に declare(strict_types=1); を書くと、厳密な型チェックが適用されます。
<?php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(3, 5); // 出力: 8
?>
■ strict_types を使わない場合(デフォルト)
PHPのデフォルトの動作では、型を自動的に変換します。例えば、文字列の "3" を数値として扱うことができます。
<?php
function add(int $a, int $b): int {
return $a + $b;
}
echo add("3", "5"); // 出力: 8(型変換される)
?>
このように、文字列 "3" も整数 3 に自動変換されるため、エラーになりません。
■ strict_types=1 を指定した場合
厳密な型チェックを有効にすると、型が一致しない場合にエラーになります。
<?php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add("3", "5"); // エラー: 型が一致しない
?>
Fatal error: Uncaught TypeError: add(): Argument #1 must be of type int, string given
このように、文字列の "3" を渡すとエラーが発生します。これにより、型のミスを防ぐことができます。
4. strict_types=1 を指定した場合の動作
PHP で strict_types=1 を指定すると、関数の引数や戻り値の型が厳密にチェックされるようになります。つまり、指定した型と完全に一致するデータ型でないとエラーになります。
■ 厳密な型チェックの例
以下のコードは、int 型の引数を持つ関数に対して、文字列を渡した場合の動作を示しています。
<?php
declare(strict_types=1);
function multiply(int $a, int $b): int {
return $a * $b;
}
echo multiply(5, "3"); // エラー発生
?>
Fatal error: Uncaught TypeError: multiply(): Argument #2 must be of type int, string given
このように、引数 $b に文字列 "3" を渡したため、エラーが発生します。strict_types=1 を有効にすることで、意図しない型変換を防ぎ、バグを減らすことができます。
5. strict_types=0(デフォルト)の動作との違い
PHPのデフォルトの設定では、関数の引数や戻り値の型が厳密にチェックされず、自動的に型変換が行われます。
■ デフォルト(strict_types=0)の動作
以下のコードは、厳密な型チェックを行わない場合の動作を示しています。
<?php
function multiply(int $a, int $b): int {
return $a * $b;
}
echo multiply(5, "3"); // 出力: 15
?>
この場合、$b に文字列 "3" を渡していますが、自動的に整数に変換されて計算が実行されます。
■ strict_types=1 との比較
以下のように、同じ関数でも strict_types=1 を指定するとエラーになり、指定しない場合は自動的に型変換が行われるという違いがあります。
strict_types=1: 型が厳密にチェックされ、間違った型のデータはエラーになる。strict_types=0: 型が自動的に変換され、異なる型のデータでも処理が続行される。
安全性を高めるためには、strict_types=1 を使用することが推奨されます。
6. 型宣言と関数の引数・戻り値の関係
PHP では、関数の引数や戻り値に型を指定することができます。これにより、関数の動作をより明確にし、エラーを防ぐことができます。
■ 引数に型を指定する
関数の引数に型を指定すると、その型以外のデータを渡した場合にエラーを出すことができます。
<?php
declare(strict_types=1);
function greet(string $name) {
echo "こんにちは、" . $name . "さん!";
}
greet("田中"); // 出力: こんにちは、田中さん!
greet(123); // エラー発生
?>
Fatal error: Uncaught TypeError: greet(): Argument #1 must be of type string, int given
このように、数値 123 を渡すとエラーが発生します。
■ 戻り値に型を指定する
関数の戻り値の型も指定することができます。
<?php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(5, 3); // 出力: 8
echo add(5, 2.5); // エラー発生
?>
Fatal error: Uncaught TypeError: add(): Return value must be of type int, float returned
戻り値の型をintに指定しているため、小数 2.5 を渡すとエラーになります。
■ 戻り値の型を柔軟にする(Union 型)
PHP 8.0 以降では、複数の型を指定することができます(Union 型)。
<?php
declare(strict_types=1);
function getValue(int $num): int|string {
if ($num > 10) {
return "大きい値";
}
return $num;
}
echo getValue(5); // 出力: 5
echo getValue(15); // 出力: 大きい値
?>
このように、戻り値の型にint|stringを指定することで、条件によって異なる型のデータを返せるようになります。
7. strict_types を使用する際の注意点
strict_types=1 を使用すると、厳密な型チェックが適用されるため、型のミスを防ぐことができますが、いくつか注意点もあります。
■ 関数間で strict_types の影響を受ける
strict_types はファイル単位で適用されるため、異なるファイルで関数を呼び出す際に注意が必要です。
<?php
// file1.php
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
?>
<?php
// file2.php
include 'file1.php';
echo add("3", "5"); // Fatal error: TypeError
?>
このように、strict_types=1 を適用したファイルの関数を別のファイルから呼び出すと、型の不一致によるエラーが発生します。
■ 配列の型チェックには strict_types だけでは不十分
PHP では、配列の要素ごとに型を指定することはできません。そのため、配列の中のデータ型を統一する場合は、手動でチェックする必要があります。
<?php
declare(strict_types=1);
function sumArray(array $numbers): int {
$sum = 0;
foreach ($numbers as $num) {
if (!is_int($num)) {
throw new TypeError("配列の要素はすべて整数である必要があります");
}
$sum += $num;
}
return $sum;
}
echo sumArray([1, 2, 3]); // 出力: 6
echo sumArray([1, "2", 3]); // TypeError 発生
?>
このように、配列の要素の型を手動でチェックすることで、厳密な型チェックを適用することができます。
8. 型宣言を適用する際のベストプラクティス
PHP で型宣言を活用する際に、より安全で可読性の高いコードを書くためのベストプラクティスを紹介します。
■ すべてのファイルで strict_types=1 を使用する
厳密な型チェックを有効にすることで、型のミスを未然に防ぐことができます。チーム開発の場合も、一貫性を持たせるために、すべての PHP ファイルで strict_types=1 を適用することが推奨されます。
■ 関数やメソッドには必ず型宣言をつける
関数の引数や戻り値には、明確に型を指定することで、バグの発生を防ぐことができます。
<?php
declare(strict_types=1);
function multiply(int $a, int $b): int {
return $a * $b;
}
echo multiply(4, 5); // 出力: 20
?>
型を指定することで、意図しないデータが渡された場合にエラーが発生し、バグを早期に発見できます。
■ 戻り値の型を適切に指定する
戻り値の型を指定することで、関数の出力が意図しない型になるのを防ぐことができます。
<?php
declare(strict_types=1);
function getMessage(bool $success): string {
return $success ? "成功しました" : "失敗しました";
}
echo getMessage(true); // 出力: 成功しました
?>
戻り値の型が明確になることで、関数の仕様を簡単に理解できるようになります。
9. PHP の型宣言と strict_types のまとめ
本記事では、PHP の型宣言と strict_types の使い方について詳しく解説しました。最後に、重要なポイントを振り返ります。
■ strict_types のポイント
strict_types=1を指定すると、厳密な型チェックが行われる。strict_types=0(デフォルト)では、PHP が型を自動変換するため、意図しない動作が発生することがある。- 関数の引数や戻り値に型を指定することで、コードの可読性と安全性が向上する。
■ 型宣言のポイント
- 引数や戻り値には、適切な型を指定する。
- 複数の型を許容する場合は、PHP 8.0 以降で導入された Union 型(例:
int|string)を活用する。 - 配列の型チェックは
strict_typesだけでは不十分なので、手動でチェックを行う。
■ strict_types を適用するベストプラクティス
- プロジェクト全体で
strict_types=1を適用し、一貫した型の管理を行う。 - 関数の型指定を必ず行い、データのやり取りを明確にする。
- エラーが発生する可能性がある場合は、
try-catchを使用して適切に処理する。
PHP で型宣言を活用することで、コードのバグを減らし、保守しやすいプログラムを作成することができます。ぜひ、strict_types を活用して、より安全な PHP コードを書いてみてください。
まとめ
ここまでの内容を振り返ると、PHPの型宣言とstrict_typesは、初心者がつまずきやすいポイントでありながら、しっかりと理解しておくことでコードの信頼性と読みやすさを大きく高めてくれる重要な仕組みだということがわかります。PHPはもともと動的型付け言語として柔軟に扱える一方で、型にあまり意識を向けずにコードを書いてしまうと、「本当は数字のはずだったのに文字列が紛れ込んでいた」「本来は真偽値だけが入る想定だったのに数値が混ざってしまった」といった予期しない動作やバグが起こりやすくなります。そこで、型宣言やstrict_types=1を活用して、PHPでも型を意識したプログラミングを行うことが、長く使えるコードを書くための大きな一歩になります。
特に、関数の引数や戻り値にintやstring、bool、arrayといった型宣言を付けることで、「この関数はどのような値を受け取って、どのような値を返すのか」が一目でわかるようになります。これはチーム開発だけでなく、数か月後の自分がコードを読み返すときにも大きな助けになります。PHPの型宣言は、難しい文法を覚えるというよりも、「自分が想定している値の種類を、コードの中に正直に書き添えておく」ための道具だと考えると理解しやすくなります。型宣言を使うことで、あとから仕様を思い出したり、関数の意図を説明したりする手間がぐっと減り、メンテナンス性が高いコードへとつながっていきます。
また、strict_types=1をファイルの先頭で宣言することで、PHPの自動型変換に頼らず、厳密な型チェックを行うことができるようになります。デフォルトの動作では、文字列の"3"が整数の3に自動的に変換されるため、一見便利に感じられますが、入力値が増えたり処理が複雑になったりすると、「どこかで勝手に変換されてしまったせいでバグが混入する」という状況を招きがちです。そこで、strict_types=1を使って型宣言を厳格に守らせることで、想定外の型が渡されたときにすぐエラーとして気づけるようになり、早い段階で問題を修正できるようになります。エラーが出ることは決して悪いことではなく、「おかしな値が紛れ込んでいる」というサインとして役立ちます。
さらに、PHPの型宣言は引数だけでなく戻り値にも指定できるため、「必ず整数を返す関数」「必ず文字列を返す関数」「場合によって整数か文字列かを返す関数」といったように、関数の振る舞いを細かく設計することができます。PHP8以降で使えるUnion型を活用すれば、int|stringのように複数の型を組み合わせて表現できるため、柔軟さを保ちつつ、意図しない型の混入を防ぐこともできます。条件によって戻り値の型が変わるロジックを書くときでも、Union型を明示しておくことで、後から読む人に「この関数はこういう場合にこういう型を返す」という情報を丁寧に伝えることができます。
一方で、配列の要素ごとの型を完全に制御するには、strict_typesだけでは不十分であることにも触れました。配列の中に整数だけが入っていてほしい場合や、文字列だけを扱いたい場合には、is_int()やis_string()、instanceofなどを使って自分でチェックする必要があります。こうした手動のチェックは少し手間に感じるかもしれませんが、その分、後から「思ってもみなかった値が入っていた」というトラブルを防ぐことができます。特に、外部からの入力やAPIのレスポンスなど、信頼しすぎると危険なデータを扱うときには、配列の中身まできちんと確認する習慣をつけておくと安心です。
型宣言とstrict_typesを実際のプロジェクトに取り入れるときには、いきなりすべてのファイルに適用するのではなく、新しく作るクラスや新規機能のファイルから徐々に導入していく方法がおすすめです。既存のコードには暗黙の型変換に頼った書き方が残っている場合も多いため、まずは新しい部分で厳密な型管理に慣れ、その後少しずつ既存コードの関数にも型宣言を追加していくと移行がスムーズです。最終的にプロジェクト全体でstrict_types=1を統一して使えるようになれば、「どこかのファイルだけ自動型変換に頼っていた」という不一致も減り、チーム全体で同じルールに基づいたPHPの型設計ができるようになります。
ここで、記事全体のポイントを一つのサンプルプログラムとして整理してみましょう。型宣言、strict_types=1、戻り値の型指定、Union型、配列の中身チェックといった要素をまとめて使うと、PHPでここまで読みやすく安全なコードが書けるというイメージが掴めるはずです。
<?php
declare(strict_types=1);
/**
* ユーザーの年齢と名前から簡単なメッセージを生成するサンプル。
* 型宣言と strict_types を組み合わせて安全に処理する。
*/
function buildProfileMessage(string $name, int $age): string
{
return "こんにちは、{$name}さん({$age}歳)";
}
/**
* 配列から整数だけを合計するサンプル。
* 配列の要素の型を自前でチェックして、意図しない値をはじく。
*/
function safeSum(array $values): int
{
$sum = 0;
foreach ($values as $v) {
if (!is_int($v)) {
throw new TypeError("配列の要素には整数だけを渡してください");
}
$sum += $v;
}
return $sum;
}
/**
* 条件によって文字列または整数を返すサンプル。
* PHP 8 以降の Union 型を使って戻り値の型を明示する。
*/
function judgeScore(int $score): int|string
{
if ($score < 0) {
return "不正な値です";
} elseif ($score >= 80) {
return "合格";
}
return $score;
}
echo buildProfileMessage("田中", 28) . PHP_EOL;
echo safeSum([1, 2, 3]) . PHP_EOL;
echo judgeScore(85) . PHP_EOL;
echo judgeScore(40) . PHP_EOL;
echo judgeScore(-5) . PHP_EOL;
このサンプルでは、PHPの型宣言を通じて、名前は必ず文字列として扱うこと、年齢や点数は整数として扱うこと、配列の要素も整数だけを許可することをはっきりとコードに書き込んでいます。また、条件によって整数や文字列を返す関数にはUnion型を指定することで、「数値のまま返すこともあれば、結果を表すメッセージを返すこともある」という仕様をわかりやすく表現しています。型宣言とstrict_types=1を組み合わせることで、PHPプログラムの中に「意図」と「制約」を自然な形で埋め込めるようになり、バグの少ない堅実なアプリケーション作りに近づくことができます。
総じて、PHPの型宣言とstrict_typesは、覚えるときこそ少し構えてしまうかもしれませんが、一度慣れてしまえばむしろ積極的に使いたくなる便利な仕組みです。関数の引数と戻り値にきちんと型を付け、ファイルの先頭にはdeclare(strict_types=1);を書き、配列や外部入力の型を丁寧に確認する。この基本的な流れを意識するだけで、初心者でも一段階上のPHPコードに近づくことができます。今日学んだ考え方を、自分の小さなスクリプトや学習用の練習コードから少しずつ取り入れてみると、型に強いPHPの感覚が自然と身についていくはずです。
生徒
「きょうのPHPの型宣言と strict_types の話を聞いて、今までなんとなく書いていたコードが、じつはかなりあいまいだったんだなあと感じました。」
先生
「そうですね。動いているうちは気付きにくいけれど、あとから仕様が変わったり、別の人が修正したりするときに、型がはっきりしているかどうかが効いてくるんですよ。」
生徒
「引数や戻り値に int や string を付けるだけで、関数の意味がぐっとわかりやすくなりました。エディタの補完も賢くなった気がします。」
先生
「エディタや静的解析ツールも、型情報があると正しくサポートしやすくなりますからね。型宣言は人間のためだけでなく、道具のための情報にもなっているんです。」
生徒
「それから、strict_types=1 を付けると最初はエラーだらけになるんじゃないかと心配でしたけど、むしろどこがあいまいだったのか教えてもらえる感じで、すごく勉強になりました。」
先生
「エラーは間違いを指摘してくれる案内板のようなものです。最初は驚くかもしれませんが、ひとつずつ直していけば、自然と型に強いコードに育っていきますよ。」
生徒
「配列の中身までチェックする例も印象的でした。たしかに、数字ばかりのつもりが文字列が混ざっていた、なんてことは現場でもありそうですね。」
先生
「そうですね。外部入力やファイルの読み込み結果など、完全には信頼できないデータを扱うときこそ、型宣言とあわせて丁寧なチェックが役に立ちます。小さな配列の合計関数でも、その考え方は十分に応用できます。」
生徒
「これからは、新しいPHPファイルを作るときには、いちばん上に declare(strict_types=1); を書くところから始めてみようと思います。」
先生
「とてもよい習慣ですね。型宣言と strict_types を味方につければ、初心者のうちから落ち着いた安定したコードが書けるようになります。少しずつで構わないので、今日学んだことを自分のプロジェクトでも試してみてください。」