【PHPメモ】クラス外部からクラス(インスタンス)のプロパティ・メソッド・定数にアクセスする記法のまとめ

# 目的
クラス外部から
* インスタンスのメソッド・プロパティ
* staticなメソッド・プロパティ
* クラス定数

へアクセスする際の記法をまとめる。


# テストコード
下記の① 〜 ⑤の5つの各プロパティとメソッドへのアクセス可否を検討していく。

```php5:テスト対象のNameクラス
<?php

class Name
{
    // ①インスタンスプロパティ
    private $firstName = 'foo';

    // ②staticプロパティ
    public static $lastName = 'hoge';

    // ③クラス定数
    public const MIDDLE_NAME = 'bar';

    // ④インスタンスメソッド
    public function getFirstName()
    {
        return $this->firstName;
    }

    // ⑤staticメソッド
    public static function getLastName()
    {
        return self::$lastName;
    }
}

$instance1 = new Name();
```

```php5:①インスタンスプロパティへのアクセス
// ---------------------------OKのパターン---------------------------
// 定義に則した基本形.
// $firstName自体はprivateだがpublicなgetFirstNameメソッドを介することでアクセス可能になる.
    echo $instance1->getFirstName() . PHP_EOL;

// ---------------------------NGのパターン---------------------------
// インスタンス内の$firstNameはprivate.(もしpublicであればこの記述でOK)
    echo $instance1->firstName . PHP_EOL;

// Nameクラス外に$firstNameは未定義
    echo $firstName . PHP_EOL;

// staticとしての$firstNameプロパティは存在しない（それ以前にprivateプロパティへの直接アクセスもNGである）
    echo Name::$firstName . PHP_EOL;

// クラス定数のfirstNameは未定義
// (勘違いすると書きそうだが,そもそもクラス定数は全部大文字なことからも事前に気づける)
    echo Name::firstName . PHP_EOL;
```

```php5:②staticプロパティへのアクセス
// ---------------------------OKのパターン---------------------------
// 定義に則した基本形
    echo Name::$lastName . PHP_EOL;

// 本来の定義(staticプロパティは個別のインスタンスではなく、クラスに紐づく)を考えると上記の方が望ましい
    echo $instance1::$lastName . PHP_EOL;

// ---------------------------NGのパターン---------------------------
// $lastNameはstaticプロパティなのでインスタンスから->経由でアクセス不可
    echo $instance1->lastName . PHP_EOL;

// クラス定数のlastNameは存在しない(インスタンスプロパティの際、$thisの後のプロパティ名に$が不要なことと混同して書き間違えるパターン)
    echo $instance1::lastName . PHP_EOL;

// Nameクラス外に$lastNameは未定義
    echo $lastName . PHP_EOL;
```

```php5:③クラス定数へのアクセス
// ---------------------------OKのパターン---------------------------
// 定義に則した基本形
    echo Name::MIDDLE_NAME . PHP_EOL;

// 本来の定義(クラス定数はクラスに紐づく)を考えると上記の方が望ましい
    echo $instance1::MIDDLE_NAME . PHP_EOL;

// ---------------------------NGのパターン---------------------------
// MIDDLE_NAMEはそもそもクラス定数なのでインスタンスから->経由でアクセス不可
    echo $instance1->MIDDLE_NAME . PHP_EOL;

// Nameクラス外に定数のMIDDLE_NAMEは未定義
    echo MIDDLE_NAME . PHP_EOL;
```

```php5:④インスタンスメソッドへのアクセス
// ---------------------------OKのパターン---------------------------
// 定義に則した基本形
    echo $instance1->getFirstName() . PHP_EOL;

// ---------------------------NGのパターン---------------------------
// インスタンス経由でアクセスせずクラスから->でアクセスしている
    echo Name->getFirstName() . PHP_EOL;

// getFirstNameはstaticメソッドではないのにstaticメソッドとして呼び出している例1
    echo $instance1::getFirstName() . PHP_EOL;

// getFirstNameはstaticメソッドではないのにstaticメソッドとして呼び出している例2
    echo Name::getFirstName() . PHP_EOL;

// Nameクラス外にgetFirstNameは未定義.
// publicなのでどこからでもアクセスできると勘違いするとこう書いてしまう.
    echo getFirstName() . PHP_EOL;
```

```php5:⑤staticメソッドへのアクセス
// ---------------------------OKのパターン---------------------------
// 定義に則した基本形
    echo Name::getLastName() . PHP_EOL;

// staticプロパティではインスタンスから->経由でアクセスNGだが、staticメソッドはインスタンスから->経由でアクセスできてしまう
    echo $instance1->getLastName() . PHP_EOL;

// staticメソッドはインスタンスから::経由でアクセスもできてしまう
    echo $instance1::getLastName() . PHP_EOL;

// [まとめ]　： ややこしくなるので個人的には、一番上の記法で統一したい

// ---------------------------NGのパターン---------------------------
// ->ではなく::を使用するべき
    echo Name->getLastName() . PHP_EOL;

// Nameクラス外にgetFirstNameは未定義.
// publicなのでどこからでもアクセスできると勘違いするとこう書いてしまう.
    echo getLastName() . PHP_EOL;
```

# 感想
ここでテストした以外にも様々なケースがあると思うが少しは整理できたと思う。
できるだけOKパターンの先頭に書いた記法を意識してコーディングしていきたい。

# 参考
* [PHPオブジェクト指向入門（前半）](https://qiita.com/mpyw/items/41230bec5c02142ae691#%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E6%9B%B8%E3%81%8D%E6%96%B9%E3%81%AB%E9%99%90%E5%AE%9A%E3%81%97%E3%81%9F%E5%AF%BE%E5%BF%9C%E8%A1%A8)
* [PHPマニュアル(クラスとオブジェクト)](https://www.php.net/manual/ja/language.oop5.php)