PHP
CakePHP
プロパティ
ローカル変数

CakePHPのプロパティとローカル変数の見分け方。

More than 1 year has passed since last update.

CakePHPのソースコードを読んでいたら、プロパティの記法が面白かったので、tipとして書こうと思います。

    protected $_config;

以上のような宣言により、プロパティを宣言することができます。重要なのは、$の後に_(アンダースコア)を入れることです。このようにすることにより、アクセス修飾子ごとの違いが記述できます。
ちなみに、PHPでは、ローカル変数はvarなどで型定義されることなくいきなり使われています。僕は最初、ローカル変数とプロパティを区別するためにアンダースコアを入れていると思ったんですよね。

    public function getUser(ServerRequest $request)
    {
        $digest = $this->_getDigest($request);
        if (empty($digest)) {
            return false;
        }

        $user = $this->_findUser($digest['username']);
        if (empty($user)) {
            return false;
        }

        if (!$this->validNonce($digest['nonce'])) {
            return false;
        }

        $field = $this->_config['fields']['password'];
        $password = $user[$field];
        unset($user[$field]);

        $hash = $this->generateResponseHash($digest, $password, $request->env('ORIGINAL_REQUEST_METHOD'));
        if ($digest['response'] === $hash) {
            return $user;
        }

        return false;
    }

上のソースコードをみてください。DigestAuthenticate.phpの一部です。$digestはいきなり使われていますが、これはクラスのプロパティではありません。$user$field$hashも同じです。プロパティは以下のように参照されます。

$this->_compiledGroupNames

では、(_)アンダースコアは、なぜ存在するのでしょうか?
では、実験的に以下のコードを作ってみました。

<?php
// Here your code !

class TestClass{
     private $_property1;
     public function method1()
     {
         $this->_property1 = 1;
     }
     public function method2()
     {
         return $this->_property1;
     }
}
$test = new  TestClass;
$test->method1();
echo $test->method2()

この場合、プロパティを参照する、$this->_property1;においての、$this-> は省略が不可能でした。つまり、アンダースコアを、プロパティと、ローカル変数を区別するために付加しているという仮説は消えました。
では、なぜ(アンダースコアをつけているのか。
public $OptionParser; このように、publicにはアンダースコアを入れないようです。
ちょっと謎ですが、PHPの場合、protectedのアクセス修飾子の場合は、アンダースコアを頭につけるということです。
ちなみに、privateの場合は、(__)アンダースコア二つです。
ちょっと人に聞いてみると、private、protected、publicなどのアクセス修飾子がPHPになかった頃に、それぞれを区別するためにつけられていたもののようです。
それがアクセス修飾子が使われるようになった今でも残っているようです。
いきなり切り替えると、色々支障があるため、「キーボードはQWERTY」とか、「車は左側通行」と同じような問題だと推測できます。

(追記)
ちなみに、protectedのメンバ関数も、アンダースコアをつけます。

    protected function _query($username)
    {
        $config = $this->_config;
        $table = TableRegistry::get($config['userModel']);

        $options = [
            'conditions' => [$table->aliasField($config['fields']['username']) => $username]
        ];

(追記)
ちなみに、Laravelのソースコードを調べると、protectedのプロパティにもアンダースコアは入っていませんでした。物によって違うんですね。

PHPのslackの皆さん助言ありがとうございます。
http://www.msng.info/archives/2016/02/phpusers-ja-on-slack.php