PHPの値には「型」があります。

どのような型があるか見てみましょう。

<?php
echo "var_dump(1) --> ", var_dump(1);
echo "var_dump(1 == 1) --> ", var_dump(1 == 1);
echo "var_dump(1 != 1) --> ", var_dump(1 != 1);
echo "var_dump(null) --> ", var_dump(null);
echo "var_dump(Null) --> ", var_dump(null);
echo "var_dump(2.73) --> ", var_dump(2.73);
echo "var_dump(1.0) --> ", var_dump(1.0);
echo "var_dump(1+1.0) --> ", var_dump(1+1.0);
echo "var_dump(NAN) --> ", var_dump(NAN);
echo "var_dump(INF) --> ", var_dump(INF);
echo "var_dump('ABC') --> ", var_dump('ABC');
echo "var_dump([1, 2, 3]) --> ", var_dump([1, 2, 3]);
echo 'var_dump(["a" => 1, "b" => 2]) --> ', var_dump(["a" => 1, "b" => 2]);
function f(){};
echo 'function f(){};', PHP_EOL;
echo 'var_dump(f()) --> ', var_dump(f());

?>
実行結果
var_dump(1) --> int(1)
var_dump(1 == 1) --> bool(true)
var_dump(1 != 1) --> bool(false)
var_dump(null) --> NULL
var_dump(Null) --> NULL
var_dump(2.73) --> float(2.73)
var_dump(1.0) --> float(1)
var_dump(1+1.0) --> float(2)
var_dump(NAN) --> float(NAN)
var_dump(INF) --> float(INF)
var_dump('ABC') --> string(3) "ABC"
var_dump([1, 2, 3]) --> array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
var_dump(["a" => 1, "b" => 2]) --> array(2) {
  ["a"]=>
  int(1)
  ["b"]=>
  int(2)
}
function f(){}; 
var_dump(f()) --> NULL
var_dump() は、文字列でパラメーターの "型(値)" を返す関数です。
ここでは扱っていませんが、class, enum, resource も型。

型ジャグリング

編集

PHP では、変数宣言の構文は持ちません。機能的には変数への始めての代入が初期化を伴った宣言とも考えられますが、v8.1の時点でも変数に型を指定したり、型アノテーションを与える方法はありません。 変数に型がない一方、値は必ず型を持ちます。

演算子式を考えてみましょう。

<?= "var_dump(-'12') --> ", var_dump(-'12'); ?>
<?= "var_dump(-'12' == 12) --> ", var_dump(-'12' == -12); ?>
<?= "var_dump(-'12' === 12) --> ", var_dump(-'12' === -12); ?>
<?= "var_dump('-12') --> ", var_dump('-12'); ?>
<?= "var_dump('-12' == 12) --> ", var_dump('-12' == -12); ?>
<?= "var_dump('-12' === 12) --> ", var_dump('-12' === -12); ?>
実行結果
var_dump(-'12') --> int(-12)
var_dump(-'12' == 12) --> bool(true)
var_dump(-'12' === 12) --> bool(true)
var_dump('-12') --> string(3) "-12"
var_dump('-12' == 12) --> bool(true) 
var_dump('-12' === 12) --> bool(false)
  1. string('12')に単項演算子(-)を作用させると、int(-12)
    文字列から整数に暗黙の変換が行われました
  2. -'12' は 12 と、==(緩やかな比較)で一致
  3. -'12' は 12 と、===(厳密な比較)でも一致
  4. string('-12')
    これは文字列リテラル
  5. '-12' は 12 と、==(緩やかな比較)で一致
  6. '-12' は 12 と、===(厳密な比較)では不一致
CなどのPHP以外のプログラム言語でも暗黙の型変換は行われます(例:整数と浮動小数点数の加算の結果が浮動小数点数になる)。
このように比較的弱い型付けの言語の中でも、文字列と数値の間で暗黙の型変換が行われるのは、AWK・Perlなどのテキストプロセッシング志向のプログラミング言語に限られます。
同じ動的型付けのプログラミング言語でも、PythonやRubyは文字列と数値の間で暗黙の型変換が行われません。
このような、PHPやPerlの柔軟すぎる暗黙の型変換は、時に柔軟すぎるがゆえにマジカルでトリックフルになりがちなので「型ジャグリング」と揶揄される場合もあります。

このコードの二項演算子バージョンも書けますが、v7とv8で結果が異なる組合せがあったり、PHPの言語設計の弱点の1つに上げらます。

v8.1で関数の引数と戻値の型を指定する構文が追加されたので、状況はある程度改善されたのですが、変数に型を宣言することは、v8.1(及び開発中のv8.2)でもできません。