【PHP】public, private, protected の違い

# はじめに
最近PHPを触り始めまして、今更ですがタイトルにあるpublic, private, protectedの違い
と使い方について自分の備忘録としてまとめました。

## 記事の目的
public, private, protected の使い方をPHP初心者向けに解説します。

## 目次
* [public, private, protected とは](#public-private-protectedとは)
* [public](#public)
* [protected](#protected)
* [private](#private)


# public, private, protectedとは

これらはアクセス修飾子と呼ばれるもので、
クラスの中で宣言される、プロパティ・メソッドの"扱い"を決めるのに用いられます。

扱いというのは、クラスを起点としてそのプロパティ・メソッドをどこで呼び出していいか、を指します。

では、具体的にそれぞれの使い方を説明していきます。

## public

**public** はどこからでもプロパティ・メソッドを呼び出すことができるようになります。
以下の例では、プロパティ($hoge)とメソッド(fuga())をclass TestA 内で宣言しています。
TestAのインスタンスを生成して、クラス外からプロパティとメソッドを呼び出して両方とも正常に呼び出すことができます。

```php
class TestA
{
    public $hoge = "ほげ";
    
    public function fuga()
    {
        echo "ふが";
        echo $this->hoge;
    }
}

$test = new TestA;
echo $test->hoge; // ほげ
$test->fuga(); // ふがほげ
```

## protected

**protected** は宣言したプロパティとメソッドが宣言された**同一クラス内からのみ**呼び出すことができる修飾子です。
そのため、生成したインスタンスからprotectedを直接呼び出した場合エラーになります。
protectedのものを呼び出したい場合はpublicなgetterメソッドを用意することで、
間接的にprotectedのプロパティもしくはメソッドを呼び出すことができます。
(サンプルコードではTestBのgetterHogeメソッド)

```php
class TestB
{
    protected $hoge = "ほげ";
    
    protected function fuga()
    {
        echo "ふが";
        echo $this->hoge;
    }
    
    public function getterHoge()
    {
        echo $this->hoge;
    }
}

$test = new TestB;
echo $test->hoge; // PHP Fatal error:  Uncaught Error: Cannot access protected property TestB::$hoge
echo $test->fuga(); // PHP Fatal error:  Uncaught Error: Call to protected method TestB::fuga() from global scope
echo $test->getterHoge(); // "ほげ"
```

また、継承した子クラスから呼び出すこともできます。
以下の例では、TestBをTestCに継承しています。
TestCのインスタンスを生成し、publicであるgetParentHogeメソッドを実行することで
継承したgetterHogeメソッドを呼び出しています。
さらに、protectedなfugaメソッドもprotecedFuncメソッドを介して呼び出せています。

```php
class TestC extends TestB
{
    public function getParentHoge()
    {
        $this->getterHoge();
    }
    
    public function protecedFunc()
    {
        $this->fuga();
    }
}

$test = new TestC;
echo $test->getParentHoge(); // "ほげ"
echo $test->protecedFunc(); // "ふがほげ"
```

## private

**private**は一番アクセス制限が厳しい修飾子で、クラス内でのみしか呼び出すことができません。
そのため継承して呼び出すこともできません。
基本的に意図せず外部から値を誤って呼び出し・書き換えが発生しないようにするものを対象としてprivateにします。

```php
class TestD
{
    private $hoge = "ほげ";
    
    private function fuga()
    {
        echo "ふが";
        echo $this->hoge;
    }
    
    public function getterHoge()
    {
        echo $this->hoge;
    }
    
    public function fugaFuga()
    {
        $this->fuga();
    }
    
    
}

$test = new TestD;
echo $test->hoge; // Uncaught Error: Cannot access private property TestD::$hoge
echo $test->fuga(); // Uncaught Error: Call to private method TestD::fuga() from global scope
echo $test->getterHoge(); // "ほげ"
echo $test->fugaFuga(); // "ふがほげ"
```

以下のサンプルコードでは、
TestDクラスを継承したTestEクラスのrunParentFugaメソッドを実行することで、
fugaメソッドを呼び出そうとしていますが、privateのため継承先であることからエラーが発生します。
fugaメソッドを呼び出すには、publicであるfugaFugaメソッドを介して実行する必要があります(runParentFugaFugaメソッド)。

```php
class TestE extends TestD
{
    public function runParentGetterHoge()
    {
        $this->getterHoge();
    }
    
    public function runParentFuga()
    {
        $this->fuga();
    }
    
    public function runParentFugaFuga()
    {
        $this->fugaFuga();
    }
    
}

$test = new TestE;
echo $test->runParentGetterHoge(); // ほげ
echo $test->runParentFuga(); // PHP Fatal error:  Uncaught Error: Call to private method TestD::fuga() from scope TestE
echo $test->runParentFugaFuga(); // ふがほげ
```


# おわりに
PHPの3種類のアクセス修飾子 public, protected, private についての解説でした。
本記事ではアクセス修飾子についての基本中の基本についてのみの解説でしたので、
また別な記事で使うべき具体的な場面等についての記事等も投稿したいと思います。


## 参考にしたサイト

https://uxmilk.jp/26435

https://php-junkie.net/design/visibility/