14957


PHPの変数の初期化はどのタイミングについて教えてください。

PHPの変数の初期化は下記を参照すると  
[PHP.net - 基本的な事](http://php.net/manual/ja/language.variables.basics.php)  
初期化されていない変数の値は状況に応じたその型のデフォルト値が入るようです。  
boolean：FALSE  
integer、float：ゼロ  
文字列：空の文字列  
配列：空の配列

このページには  
「PHP では変数を初期化する必要はありません。」  
とありましたが  
「初期化することはとてもいいことです」とも記述されていました。

そこでお伺いしたいのですが一般的に初期化は明示的に行う必要はありますでしょうか？  
また、初期化する場合PHPの初期化はどのタイミングで行うのでしょうか？  
どういう風に気を付けてコーディングしているかだけでも構いませんので教えてください。  
よろしくお願いします。


CC BY-SA 3.0
2015-08-28T08:27:55.133
14950
2015-08-29T03:57:35.107
2015-08-28T09:48:14.813
7918
7918
question
php 可読性
PHPを使っています。変数を初期化すべきかを教えてください。


> 初期化されていない変数の値は状況に応じたその型のデフォルト値が入るようです。  
>  boolean：FALSE  
>  integer、float：ゼロ  
>  文字列：空の文字列  
>  配列：空の配列

が初期化で良いのでは？

宣言時に、格納される値が設定できるのであれば、そのタイミングで設定すれば良し。  
そうでなければ、変数を使う前に、デフォルト値のままか？って判定すれば良いだけのように思いますが。

確かに、初期化は大事ですが、それ以上に大事なのは、

  1. 意図した有効値が入っているか判断できること
  2. 変数の値をコントロールして設定・取得できること

だと思います。

1はそのままですが、integerとかの『0』は普通の値なので、『0』が入る事があり得る変数でそのままにしておくと、使いたいタイミングで初期値の『0』なのか、意図して設定した『0』なのか分かりませんよね？  
そういう場合を考慮して、無効な値を自分で考えて初期化してやる必要があります。  
※その変数が取り得ない値を無効値と自分で決めてやります。身長や年齢とかなら負値とかですね。

2は変数が生まれて消えるまでをコントロールできるように作っているか？ってことです。  
例えば、globalな変数を様々な関数の中で設定したり、使用したりして、どのタイミングで設定されているかとか、このタイミングでこの変数使って良いのかとかを判断できなくなるのが典型的な悪い作りですね。

ぱっと思いつくのはこんな感じかな？と思います。

* * *

多分、初期化を口うるさく言われるのは、Cのポインタの使い方が一番影響してるんではないかと思いますよ。


CC BY-SA 3.0
2015-08-28T10:54:18.260
14957
2015-08-28T10:59:23.073
2015-08-28T10:59:23.073
2383
2383
14950
answer


リンク先のページの最後に

> 初期化されていない変数のデフォルト値に依存すると、そのファイルを include している別のファイルで同名の変数が使用されていた場合などに
> 問題を起こします。また、register_globals が on の場合には重大なセキュリティリスク
> を抱えることになります。初期化されていない変数を使用すると、 E_NOTICE レベルのエラーが発生します。
> しかし、初期化されていない配列に要素を追加する場合はエラーにはなりません。 変数が初期化されているかどうかの判断には、isset() を使用します。

と書いてあります。上のような問題が確実に起きないことを保証できる場合を除いて、初期化した方がいいのでは無いでしょうか？


CC BY-SA 3.0
2015-08-28T11:32:48.563
14960
2015-08-28T11:32:48.563
7347
14950
answer


### 1\. その変数、本当に未初期化でしょうか

例えば、PHPで別ファイルをincludeする場合、includeするファイルの中で定義された変数も現在のスコープに取り込まれます。

index.php

[code]

    include "hoge.php";
    
    echo $i + 0;
    
[/code]

hoge.php

[code]

    $i = 1000;
    
[/code]

index.php において `$i` は初期化されていないので、出力される値は0でしょうか？いいえ、 hoge.php で `$i = 1000`
と定義されているので、index.php でも `$i` の値は 1000 です。

もうひとつの例として、for文を挙げましょう。

[code]

    for ($i = 0; $i < 10; $i++) {
    }
    
    //
    // あれこれ
    //
    
    echo $i + 0;
    
[/code]

最後の行で出力される値はいくつでしょうか？for文で使われた値が残っているので、 11 が正解です。

### 2\. 「状況に応じたその型」はいつ決まるのか

[code]

    $hoge = $undefined_var;
    
[/code]

`$hoge` の値はどうなるでしょうか？マニュアルでは以下のように書かれていますが・・・この場合は？

> 初期化されていない変数の値は、状況に応じたその型のデフォルト値 - boolean なら FALSE、integer や float ならゼロ、 文字列
> (echo で使う場合など) なら空の文字列、配列なら空の配列となります。  
>  \--- <http://php.net/manual/ja/language.variables.basics.php> より引用

答えは、 `NULL` です。

PHPでは数値、論理値、文字列、配列、オブジェクト、NULL は相互に自動的に変換されます。先ほどの `NULL` も、
**未初期化の変数を参照した時点ではなく、型変換の必要が生じたときに初めて**
、いずれかのデフォルト値に変換されることになります。なので特定の型を期待しているとはまります。

[code]

    function print_size($w, $h) {
        echo "width: $w, height: $h\n";
    }
    
    $width = 100;
    print_size($width, $height);
    
[/code]

`width: 100, height: 0` ではなく、 `width: 100, height:` と表示されます。未定義の変数 `$height`
を渡したことで `$h` は NULL になっていますが、NULL を文字列に変換したら空文字列ですよね。

[code]

    function insert($value) {
        $dbh = new PDO("pgsql:dbname=test", "user", "pass");
        $stmt = $dbh->prepare('insert into test values (?)');
        $stmt->execute(array($value));
    }
    
    $foo = 0;
    insert($foo);
    insert($undef);
    
[/code]

データベースにもNULLという概念があります。上記の書き方では `$value` は内部的に文字列になってデータベースに渡されますが、`"0"`
がDB側でも数値として扱われる一方で、 `""` がNULLとして扱われたりします（様々な要因で変化しますが）。

[PHP: 型の相互変換 - Manual](http://php.net/manual/ja/language.types.type-
juggling.php)

その変数や値がどこでどのように使われるのか把握できていれば大丈夫とはいえ、上記のような心配を抱えるぐらいなら明示的に初期値を指定したほうがまだ安心できます。

変数が定義され、かつ値がNULLでないことは `isset()`
で確認できますが、豚吐露さんも書かれているように無効値を決めて初期化しておくのはいい方法だと思います。


CC BY-SA 3.0
2015-08-28T12:31:06.833
14962
2015-08-28T12:36:57.203
2015-08-28T12:36:57.203
8000
8000
14950
answer


変数の初期化については一般的に、コーディングスタイルやコーディングルールで語られることがあります。

初期化し忘れによるバグを防ぐ、デフォルト値の勘違い、分りにくさの解消、といった目的で明示的に初期化することを義務付ける場合があります。

PHPではデフォルトの値が入るので初期化は不要ですが「初期化することはとてもいいことです」というのはそういう意味だと思います。


CC BY-SA 3.0
2015-08-29T03:57:35.107
14986
2015-08-29T03:57:35.107
5008
14950
answer