2
0

More than 3 years have passed since last update.

phpの型変換が難しくて混乱するので整理した(配列×boolean×if文)

Posted at

もうずっとこれに翻弄されているので整理しようと思いました

PHPの自動的な型変換について

公式より
https://www.php.net/manual/ja/language.types.boolean.php#language.types.boolean.casting

bool に明示的に変換を行うには、キャスト (bool) または (boolean) を使用します。しかし、演算子、関数、制御構造が bool 型の引数を必要とする場合には、値は自動的に変換されるため、 多くの場合はキャストは不要です。

基本的には明示的にわざわざキャストしたりしなくて良いということらしい。
キャストまではしないにしろ、if文とかで使うのに明示的に論理式などになっている方が好みなのに。
でも公式にこう書かれてしまうとやりづらい、、

困っていること

既存のコードで
・フレームワークの仕様により配列が無限に登場している
・配列がif文の条件に無限に使われており、PHPによる型変換の結果のbool値が使われるのではなく、isset()の結果のbool値が使われている
・isset()使った方がまだ分かりやすいけど、自動的な型変換の動きが理解できれば不要な気がする

isset()の挙動

https://www.php.net/manual/ja/function.isset.php
公式によると、変数がセットされ且つnullではない値になっている場合trueを返す。
また配列に関しては、キーが存在しない又はキーに紐づく値がNULLだとfalseを返し、それ以外はtrueを返すよう。

また、下記のように文字列のオフセットを取得する場合の結果は

<?php
$expected_array_got_string = 'somestring';
var_dump(isset($expected_array_got_string['some_key']));
var_dump(isset($expected_array_got_string[0]));
var_dump(isset($expected_array_got_string['0']));
var_dump(isset($expected_array_got_string[0.5]));
var_dump(isset($expected_array_got_string['0.5']));
var_dump(isset($expected_array_got_string['0 Mostel']));
?>

これとの事。integerと文字列0の場合だけオフセット可能なように変換してくれるらしい。
このオフセットと自動変換の挙動に頼る事ないコードを書きたいとしか思えない。

bool(false)
bool(true)
bool(true)
bool(true)
bool(false)
bool(false)

配列×if文×型の自動変換の組み合わせのコードを掘り下げる

こんなコードがある

$test = $this->request->getData('test.data');
if (isset($test)){
  //処理
}

これだとisset()の挙動により、指定の配列の値がnullならfalseを返してくるという事でまず間違いない。
次に、issetを使用せず変数となっている配列の値から型の自動変換が行われる事を前提に、下記のようなコードに変更してみた

$test = $this->request->getData('test.data');
if ($test){
  //処理
}

見た目はこちらの方がスマートである。
でも何しでかすかわからない不安があって今まではどうしてもisset使いたくなってしまっていたけど、今日はちゃんと公式で確認。

bool に変換する場合、次の値は false とみなされます。
boolean の false
integer の 0 および -0 (ゼロ)
float の 0.0 および -0.0 (ゼロ)
空の文字列、 および文字列の "0"
要素の数がゼロである 配列
特別な値 NULL (値がセットされていない変数を含む)
属性がない空要素から作成された SimpleXML オブジェクト。つまり、子要素も属性もない要素です。

指定の配列の値(要素)がゼロ、又は値がNULL、又は値がセットされていない変数の場合falseを返してくれるよう。
ここまでわかればisset消しても大丈夫そうだな。型変換理解している風を装って消そう。
(でもなんとなく使いたい気持ちになる明示的じゃないと不安になる病)

おまけ

変数を使わなくてもいける
でもif文以降も同じ配列の値を使うなら、変数使った方がすっきりする
(既存のコードでもisset使われてたから、PHPの自動的な型変換に不安を覚える人は多いのかもしれない)

if ($this->request->getData('test.data')){
  //処理
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0