PHP の型キャストの挙動のまとめ

PHP には、他の言語にもよくある「型キャスト」( typecasting )の機能があります。

正しく使えればきっと便利な機能なのですが、 PHP の場合は直感的ではない挙動をする場合がかなり多いので、使うときは細心の注意が必要です。

代表的なパターンを以下にかんたんにまとめてみました。

  • (int)
  • (array)
  • (object)

(int)

int 型への型変換の場合。

// 文字列
(int) '5'      // => 5
(int) '3x'     // => 3
(int) '-2'     // => -2
(int) '- 2'    // => 0
(int) '1,500'  // => 1
(int) 'apple'  // => 0

// 配列
(int) []         // => 0
(int) [3, 4, 5]  // => 1

// オブジェクト
(int) new stdClass()
// => PHP error:  Object of class stdClass could not be converted to int

オブジェクトが int 型に変換できないのは直感的ですが、文字列から int 型への変換のルールがゆるいのと、配列が int 型に変換できてしまうのは個人的に気持ちが悪いです。

int 型に関しては、 float 型が配列のキーとして使われたときの挙動にも注意が必要です。

$a = ['あんぱん', 'ジャムパン'];

$a[0.9]  // => 'あんぱん'
$a['0.9']  // => NULL

# 次の分岐については環境次第
$a[0.9999999]  // => 'あんぱん'
$a[0.99999999999999999999]  // => 'ジャムパン'

(array)

array 型への型変換の場合。

// スカラ型
(array) null     // => []
(array) true     // => [true]
(array) false    // => [false]
(array) 3        // => [3]
(array) 'apple'  // => ['apple']

// オブジェクト
$obj = new stdClass();
$obj->id = 10;
$obj->name = 'Hasebe';
(array) $obj;  // => ['id' => 10, 'name' => 'Hasebe']

スカラ型が array にキャストできてしまうのは個人的に驚きです。

関数の入り口付近で次のようなコードが書かれている場合がありますが、これはこの配列のキャストを使うとシンプルに書けそうです。

if (!is_array($ids)) {
  $ids = [$id]);
}

(object)

object 型への型変換の場合。

// スカラ型
(object) null     // => {}
(object) false    // => { "scalar": false }
(object) 10       // => { "scalar": 10 }

// 配列
(object) ['name' => 'Hayato']   // => { "name": "Hayato" }

私は全体を通して「なんじゃこりゃ・・・」と思うところがところどころあるのですが、みなさんはいかがでしょうか。

ふだんは nullfalse はあまり強く意識して区別はしていませんが、この挙動を見ると nullfalse はぜんぜん別物なんだということがよくわかります。

アクロバティックな動きをする部分は用法用量を守って正しく使いたい(あるいは使いたくない)ところですね。