ソムリエでエンジニアのブログ

ワインの事も書きたいけど基本エンジニア用

PHPのアクセス修飾子 ~public, protected, privateを感覚で使ってませんか?~

はじめに

未経験からwebエンジニアに転職し、最初の案件でPHPを利用したサービスを担当しました。
その際、プロパティやメソッドのアクセス修飾子を全く意識せずコードを書いていたことに対してレビューで指摘が、、、
レビューいただいてた先輩には感謝しかありません。。。ありがとう先輩。
当時を振り返り、再度整理する意味も含めて本記事を書くことにしました。

記事の目的

開発の際に正しいアクセス修飾子を利用できるようになる事で、
改修し易く、バグを生みにくいコードを実装できるようになることが目的です。
 

対象

・日頃メソッド・プロパティを意識せずコーディングを行なっている方
・アクセス修飾子を感覚で利用していた方

アクセス修飾子

アクセス修飾子とは、プロパティやメソッドにどこからアクセスできるかを指定するものです。
指定には「public」「private」「protected」の3つのどれかを指定します。
※アクセス権を明示せずに宣言したメソッドは、 publicとして扱われます。

各アクセス修飾子の違い

public

publicで宣言されたプロパティ・メソッドはどこからでもアクセスする事が可能になります。

<?php
class Animal
{
    public $type = 'mammalian';
}

$animal = new Animal();
echo $animal->type;
?>

→ mammalian

publicで宣言した場合は、上記のサンプルのようにどこからでも対象のプロパティ・メソッドにアクセス可能です。

protected

protectedで宣言されたプロパティ・メソッドは宣言されたそのクラス自身と親子関係にあるクラス内でアクセスする事が可能になります。

<?php
class Animal
{
    protected $type = 'mammalian';
}

$animal = new Animal();
echo $animal->type;

?>

→ PHP Fatal error:  Uncaught Error: Cannot access protected property Animal::$type in /workspace/Main.php:8

protectedで宣言した場合$typeはクラス外から利用する事はできません。
しかし以下のように親子関係のあるクラスからは呼び出しが可能となります。

<?php
class Animal
{
    protected string $parentType = "mammalian";
}

class Human extends Animal
{
    public function getType(): void
    {
        echo $this->parentType;
    }
}

$human = new Human;
$human->getType();

→ mammalian

HumanクラスはAnimalクラスを継承しています。(extendsが継承を示す)
Humanクラス内では親クラスでprotected定義されているプロパティを参照する事が可能です。

private

privateで宣言されたプロパティ・メソッドは宣言されたクラス内でアクセスする事が可能になります。

<?php
class Animal
{
    private $type = 'mammalian';
}

$animal = new Animal();
echo $animal->type;

?>

→  PHP Fatal error:  Uncaught Error: Cannot access private property Animal::$type in /workspace/Main.php:8

privateで宣言した場合$typeはAnimalクラス内のみで利用可能プロパティとなります。

どのアクセス修飾子を使えばいいのか、、、

一見アクセス権の範囲が広ければ広いほど便利に思えるかもしれません。
しかし、影響範囲の大きさから改変がしにくくなる不便さがあり、余計なアクセス権は想定外の場所の不具合を生む原因にもなりかねます。
例えば、publicで宣言されているプロパティはどこからでもアクセスできてしまうのでソースコードの至る所でそのプロパティが使用されている可能性があり、影響範囲を特定する事が難しくなります。
一方、privateで宣言されているプロパティ・メソッドであれば影響範囲はそのクラス内にとどまる為、改修などの影響範囲を特定しやすくなります。
その為、プログラムの安全性を高めるためにも、privateにできるものはprivateにし、できるだけ狭い範囲で作れるように考えていくべきです。

まとめ

アクセス修飾子を適切に指定することで、予期せぬバグが混入するリスクを減らしていきましょう。

参考

www.php.net