21774


**最終的にやりたいこと**  
・3つの状態をフラグのように変数で管理したい

**最初に考えたこと**  
・変数に数字を入れようと思ったのですが、数字だと分かりにくいので、true、false、null、未定義辺りで条件分岐したい(可能なら)

**質問**  
・例えば、$hoge が下記何れかであると仮定して;  
true、false、null、未定義

**下記のように条件分岐できるでしょうか？**  
・$hogeが、trueなら  
・$hogeが、falseなら  
・$hogeが、nullなら  
・$hogeが、未定義なら


CC BY-SA 3.0
2016-02-06T09:06:47.300
21770
2016-02-08T05:43:55.537
7886
question
php
未定義、true、fasle で条件分岐できる？


nullと未定義を区別する方法がわからなかったので、不完全な回答になりますが、true、false、nullまたは未定義、ならば簡単に判別できますね。

[code]

    if( !isset($hoge) ) {
      echo "未定義 or null";
    } else if( $hoge === true ) {
      echo "true";
    } else if( $hoge === false ) {
      echo "false";
    } else {
      echo "other";
    }
    
[/code]

(仮定にあるように「true、false、null、未定義」の何れかであるなら、最後は要らないのですが、まぁ念のため。)

そもそも「数字だと分かりにくい」のに「nullではわかりやすいのか?」という疑問はあるのですが。  
nullと未定義の区別の仕方については、ネットで調べるとすぐに「確かにそうすれば出来るけど…」と言うのは見つかったんですが、あまり紹介したくなるやり方ではなかったので、ここには挙げずにおきます。  
基本的には変数の未定義状態を積極的に状態の一部として使うのはどうかと思う(「値の設定漏れ」と「未定義」の区別がつかなくなる)のですが、issetでnullと未定義を区別できないphpでそんなことに拘る意味があるのかどうかはなんとも言えません。


CC BY-SA 3.0
2016-02-06T09:46:22.830
21774
2016-02-06T09:46:22.830
13972
21770
answer


直接の回答ではなく別解として。最終的な目的が

> 3つの状態をフラグのように変数で管理したい

ということであるのなら、その三種の状態を表すクラスを定義して const で定義値を持たせる方式もあります。  
例えば次のようなクラスを作っておけば

[code]

    /**
     * 性別
     */
    class Gender
    {
        const UNKNOWN = 0;
        const MALE = 1;
        const FEMALE = 2;
    }
    
[/code]

次のような分岐をさせることができます。

[code]

    public function foo($gender)
    {
        switch ($gender) {
            case Gender::MALE:
                break;
            case Gender::FEMALE:
                break;
            case Gender::UNKNOWN:
            default:
                break;
        }     
    }
    
[/code]

この方式の利点としては：

  * 明示的に状態の意味合いを表す名前を付けることによって、マジックナンバーを避け、可読性を上げることができる
  * 仕様変更でステータスが4つ以上に増えても追随できる

逆に欠点としては：

  * タイプ量が増える

なおタイプ量については今どきのIDEを使っているならコード補完が効くのでさほど問題にはならないという見方もできます。  
一方で、クラス化したところで、比較するものは所詮ただのスカラー値でしかなく `Gender::MALE == Paid::YES`
などといった無意味な比較もできてしまうため、さしてタイプセーフ性は望めません（PHPにまともな列挙型があればよかったのですが……）。

このようにメリット・デメリットがあるので、単なる boolean
値で保持するのか、あるいは状態クラスを定義するのかは、そのときの開発規模等との兼ね合いで考えるべきだと思われます。


CC BY-SA 3.0
2016-02-07T16:54:30.883
21820
2016-02-07T16:54:30.883
10492
21770
answer


NULLのように真でも偽でもない状態を持つ論理は3値論理と呼ばれます。この界隈ではSQLの3値論理が有名です。

言語仕様によってNULLは想定外の挙動をするときがあります。例えば、SQLではNULLはたとえNULLとの比較であっても真にも偽にもなりません。`SELECT
* FROM column != NULL`とかやってしまうのは典型的なミスです。

PHPでも、例えばこんなコード

[code]

    if($x===false) { ...
    
[/code]

が、

[code]

    if(!$x) { ...
    
[/code]

と書き換えてはいけないコードであることを誤解の余地無く認識できるでしょうか。

このようにややこしいことになるので、TRUE/FALSEと混ぜて3値論理として使うのは全くおすすめ出来ません。

> 変数に数字を入れようと思ったのですが、数字だと分かりにくい

数字の方が遙かにましで、確実にバグの種になります。


CC BY-SA 3.0
2016-02-08T05:43:55.537
21835
2016-02-08T05:43:55.537
5793
21770
answer