7.

PHP の型キャスト|(int) の挙動・filter_var での検証・strict_types

編集
この記事の要点
  • キャストは (int) (float) (string) (bool) (array) (object) の 6 種類
  • (int)"12abc" は 12。エラーにならず先頭の数値だけを取る
  • intval() は基数を指定できる。settype()変数そのものを書き換える
  • 入力値の検証には filter_var()「数値として妥当か」を判定できる
  • declare(strict_types=1) を付けると引数と戻り値の自動変換が止まる

キャストの一覧

var_dump((int)"42");        // int(42)
var_dump((float)"1.5");     // float(1.5)
var_dump((string)42);       // string(2) "42"
var_dump((bool)"0");        // bool(false)  ← "0" は偽
var_dump((array)"a");       // ["a"]
var_dump((object)['n'=>1]); // stdClass {n: 1}

// 別名
(integer)$x;   // (int) と同じ
(boolean)$x;   // (bool) と同じ
(double)$x;    // (float) と同じ

文字列から数値への変換ルール

var_dump((int)"42");        // 42
var_dump((int)"42abc");     // 42     ← 先頭の数値だけ拾う。エラーにならない
var_dump((int)"abc");       // 0      ← 数値が無ければ 0
var_dump((int)"");          // 0
var_dump((int)" 42");       // 42     先頭の空白は無視される
var_dump((int)"0x1A");      // 0      16 進表記は解釈されない
var_dump((int)"1e3");       // 1000   指数表記は解釈される
var_dump((int)"3.9");       // 3      切り捨て(四捨五入ではない)
var_dump((int)-3.9);        // -3     0 方向に切り捨て
var_dump((int)null);        // 0
var_dump((int)true);        // 1

変換に失敗しても例外は出ません。「入力が数値かどうか」を判定したいなら、キャストではなく検証関数を使います。

入力値の検証

$input = $_GET['page'] ?? '';

// 1. 数値として妥当かを判定してから使う
$page = filter_var($input, FILTER_VALIDATE_INT);
if ($page === false) {
    $page = 1;                       // 数値でなければ既定値
}

// 範囲も一緒に検証できる
$page = filter_var($input, FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 100, 'default' => 1],
]);

// 2. is_numeric で数値文字列かを見る
var_dump(is_numeric("42"));    // true
var_dump(is_numeric("42abc")); // false
var_dump(is_numeric("1e3"));   // true
var_dump(is_numeric(" 42"));   // true   先頭空白は許される
var_dump(is_numeric("42 "));   // PHP 8.0 以降は true(8.0 で変更)

// 3. 整数かどうか
var_dump(ctype_digit("42"));   // true   0-9 だけか(負数は false)

filter_var()「妥当でなければ falseを返すので、(int) と違って不正入力を検出できます。0 が返る場合と false が返る場合を区別するため、判定は必ず === false で行ってください。

関数による変換

var_dump(intval("42"));          // 42
var_dump(intval("1A", 16));      // 26     基数を指定できる(キャストにはできない)
var_dump(intval("0x1A", 0));     // 26     0 なら接頭辞から自動判別
var_dump(floatval("1.5kg"));     // 1.5
var_dump(strval(1.0));           // "1"
var_dump(boolval("0"));          // false

$x = "42";
settype($x, "integer");          // 変数そのものを書き換える
var_dump($x);                    // int(42)

var_dump(number_format(1234567)); // "1,234,567"  ← 表示用。数値ではなく文字列

bool への変換

(bool) の結果
false 0 0.0 -0.0 "" "0" [] nullfalse
それ以外すべて("0.0" "false" " " [0] -1 を含む)true
var_dump((bool)"0");       // false   ← 文字列の "0" だけ特別扱い
var_dump((bool)"0.0");     // true
var_dump((bool)"false");   // true
var_dump((bool)[]);        // false
var_dump((bool)[0]);       // true    要素があるので真

"0" が偽になるのは PHP 特有です。フォームから来た文字列の "0" を「入力あり」と判定したいときは === ''strlen() で見ます。

配列・オブジェクトへの変換

var_dump((array)"abc");          // ["abc"]        要素 1 個の配列
var_dump((array)null);           // []             空配列
var_dump((array)5);              // [5]

class User {
    public string $name = '田中';
    protected int $age = 30;
    private bool $admin = false;
}
print_r((array)new User());
// ['name' => '田中', "\0*\0age" => 30, "\0User\0admin" => false]

オブジェクトを配列にキャストすると、protected / private のキーに制御文字が混ざります。実用には get_object_vars()json_decode(json_encode($obj), true) を使ってください(オブジェクトを配列に変換する方法)。

暗黙の型変換と strict_types

function half(int $n): int {
    return (int)($n / 2);
}

half("10");    // 5      既定では "10" が int に変換される
half("abc");   // TypeError(PHP 8 以降)
half(3.9);     // Deprecated: 暗黙の float→int 変換で精度が落ちる
<?php
declare(strict_types=1);      // ファイルの先頭行に置く(他の文より前)

function half(int $n): int { return (int)($n / 2); }

half(10);      // 5
half("10");    // TypeError: half(): Argument #1 ($n) must be of type int, string given

declare(strict_types=1)そのファイルで書かれた呼び出しにだけ効きます。ライブラリ側に付けても、呼ぶ側のファイルに無ければ変換されます。新規のファイルには付けておくと、型の取り違えを早い段階で発見できます。

数値の精度

var_dump(0.1 + 0.2 == 0.3);           // false  浮動小数点の誤差
var_dump(abs(0.1 + 0.2 - 0.3) < 1e-9); // true

var_dump((int)"9223372036854775808"); // int(9223372036854775807)  桁あふれで丸められる
var_dump(PHP_INT_MAX);                // 9223372036854775807

// 金額は文字列 + bcmath で扱う
echo bcadd('0.1', '0.2', 1);          // 0.3

金額や数量など誤差が許されない計算では float を使わず、整数(最小単位で保持)か bcmath を使います。

日付との相互変換

// 文字列 → DateTime
$d = new DateTimeImmutable('2026-09-07 12:00:00');
$d = DateTimeImmutable::createFromFormat('Y/m/d', '2026/09/07');
if ($d === false) {
    // 形式が合わないと false。必ず確認する
}

// DateTime → 文字列
echo $d->format('Y-m-d H:i:s');

// 文字列 → UNIX 時刻(失敗すると false)
$ts = strtotime('2026-09-07');
var_dump($ts === false);

// UNIX 時刻 → 文字列
echo date('Y-m-d', $ts);

// タイムゾーンを明示する
$d = new DateTimeImmutable('now', new DateTimeZone('Asia/Tokyo'));

strtotime() は解釈できない文字列で false を返します。(int)strtotime($s) と書くと失敗が 0(=1970年)になって気づけません。必ず === false で判定してください。

JSON との変換

$data = ['name' => '田中', 'age' => 30];

echo json_encode($data);                            // {"name":"田中","age":30}
echo json_encode($data, JSON_UNESCAPED_UNICODE);    // {"name":"田中","age":30}

$back = json_decode('{"a":1}');          // stdClass として受け取る
$back = json_decode('{"a":1}', true);    // 連想配列として受け取る

// 失敗の検出(PHP 7.3 以降)
try {
    json_decode('{bad}', true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo $e->getMessage();      // Syntax error
}

// 数値がとても大きいと精度が落ちる
var_dump(json_decode('{"id":12345678901234567890}')->id);      // float
var_dump(json_decode('{"id":12345678901234567890}', false, 512,
    JSON_BIGINT_AS_STRING)->id);                              // string

json_decode() は失敗しても既定では null を返すだけです。JSON_THROW_ON_ERROR を付けると例外になり、握りつぶしを防げます。

フォームの値はすべて文字列

// チェックボックスは「送られてこない」か "on"
$isPublic = isset($_POST['is_public']);          // bool として受ける

// 数値
$qty = filter_input(INPUT_POST, 'qty', FILTER_VALIDATE_INT) ?: 1;

// 金額(小数を扱うなら文字列のまま検証してから整数化する)
$raw = $_POST['price'] ?? '';
if (!preg_match('/\A\d+(\.\d{1,2})?\z/', $raw)) {
    throw new InvalidArgumentException('金額の形式が不正です');
}
$priceInSen = (int)round((float)$raw * 100);      // 最小単位の整数で保持する

// 空文字と 0 と未入力を区別する
$note = $_POST['note'] ?? null;
if ($note === null)      { /* 項目自体が無い */ }
elseif ($note === '')    { /* 入力欄が空 */ }

$_GET / $_POST の値は常に文字列(または配列)です。1"1" の違いで === の比較が食い違うため、受け取った直後に検証して型を決めてしまうのが安全です。

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本事項
  2. HTMLへの埋め込み
  3. 変数
  4. 可変変数
  5. 定数
  6. データ型
  7. キャスト
  8. エスケープ文字
  9. 配列
  10. 演算子
  11. 代入の際の注意点
  12. 条件分岐
  13. 繰り返し処理
  14. クラスとインスタンス
  15. コンストラクタ
  16. 関数
  17. スーパーグローバル変数
  18. スコープ
  19. staticについて
  20. yieldについて
  21. ファイルのアップロード方法
  22. DB接続方法
  23. SQL実行方法
  24. カプセル化の具体例
  25. 継承の構文
  26. オーバーライド
  27. ポリモーフィズム(多様性)の具体例
  28. 抽象クラス・メソッドの構文と具体例
  29. GET通信
  30. try catchで全てのエラーを拾う方法

最近更新/作成されたページ