【PHP】アクセス修飾子とは? – プロパティやメソッドのアクセスを制限する方法

クラスにはアクセス修飾子と呼ばれる仕組みがあります。

アクセス修飾子はクラスのプロパティやメソッドへのアクセスを制限する方法です。

ここではアクセス修飾子について初心者向けに解説します。

★ 目的

  • アクセス修飾子を理解する。
  • アクセス修飾子を使えるようになる。

アクセス修飾子とは

アクセス修飾子はクラスのプロパティやメソッドへのアクセスを制限する仕組みです。

一般的にクラスへのアクセスはクラス自身、サブクラス、クラス利用元の3種類あります。

アクセス修飾子の基本構文

アクセス修飾子の基本構文は次のようになります。

class クラス名 {
    // クラス定数
    アクセス修飾子 クラス定数;
    // クラス変数
    アクセス修飾子 static クラス変数;
    // クラスメソッド
    アクセス修飾子 static function メソッド名() {
    }
    // メンバ変数
    アクセス修飾子 プロパティ名;
    // メンバメソッド
    アクセス修飾子 function メソッド名() {
    }
}

アクセス修飾子はクラス定数・クラス変数・クラスメソッドやメンバ変数・メンバメソッドの定義の先頭に記述します。

アクセス修飾子の種類

アクセス修飾子はpublic、protected、privateの3種類あります。

それぞれのアクセスの制限は次のようになります。

アクセス元publicprotectedprivate
クラス自身
サブクラス×
クラス利用元××

検証コード

上記表のアクセスを実際のプログラムで確認しましょう。

先ずは次の検証コードをご覧ください。

ソースコード

<?php

// クラス定義
class AccessTest {

    /*
    * クラス定数
    *****************************************************/
    // public
    public const CONST_PUBLIC = 'SUCCESS!';
    // protected
    protected const CONST_PROTECTED = 'SUCCESS!';
    // private
    private const CONST_PRIVATE = 'SUCCESS!';

    /*
    * クラス変数
    *****************************************************/
    // public
    public static $class_variable_public = 'SUCCESS!';
    // protected
    protected static $class_variable_protected = 'SUCCESS!';
    // private
    private static $class_variable_private = 'SUCCESS!';

    /*
    * クラスメソッド
    *****************************************************/
    // public
    public static function class_method_public() {
        echo "class_method_public: SUCCESS!\n";
    }
    // protected
    protected static function class_method_protected() {
        echo "class_method_protected: SUCCESS!\n";
    }
    // private
    private static function class_method_private() {
        echo "class_method_private: SUCCESS!\n";
    }

    /*
    * メンバー変数
    *****************************************************/
    // public
    public $member_variable_public = 'SUCCESS!';
    // protected
    protected $member_variable_protected = 'SUCCESS!';
    // private
    private $member_variable_private = 'SUCCESS!';

    /*
    * メンバーメソッド
    *****************************************************/
    // public
    public function member_method_public() {
        echo "member_method_public: SUCCESS!\n";
    }
    // protected
    protected function member_method_protected() {
        echo "member_method_protected: SUCCESS!\n";
    }
    // private
    private function member_method_private() {
        echo "member_method_private: SUCCESS!\n";
    }
    
}

?>

AccessTestクラスを定義しており、3つのアクセス修飾子(public/protected/private)について、クラス定数・クラス変数・クラスメソッド・メンバー変数・メンバーメソッドのそれぞれ用意しています。

このクラスを使ってアクセス修飾子の動作を確認します。

クラス自身からのアクセス

クラス自身から定数・変数・メソッドにアクセスするため、executeメソッドを定義し、呼び出します。

ソースコード

<?php

// クラス定義
class AccessTest {

    /*
    * クラス定数
    *****************************************************/
    // public
    public const CONST_PUBLIC = 'SUCCESS!';
    // protected
    protected const CONST_PROTECTED = 'SUCCESS!';
    // private
    private const CONST_PRIVATE = 'SUCCESS!';

    /*
    * クラス変数
    *****************************************************/
    // public
    public static $class_variable_public = 'SUCCESS!';
    // protected
    protected static $class_variable_protected = 'SUCCESS!';
    // private
    private static $class_variable_private = 'SUCCESS!';

    /*
    * クラスメソッド
    *****************************************************/
    // public
    public static function class_method_public() {
        echo "class_method_public: SUCCESS!\n";
    }
    // protected
    protected static function class_method_protected() {
        echo "class_method_protected: SUCCESS!\n";
    }
    // private
    private static function class_method_private() {
        echo "class_method_private: SUCCESS!\n";
    }

    /*
    * メンバー変数
    *****************************************************/
    // public
    public $member_variable_public = 'SUCCESS!';
    // protected
    protected $member_variable_protected = 'SUCCESS!';
    // private
    private $member_variable_private = 'SUCCESS!';

    /*
    * メンバーメソッド
    *****************************************************/
    // public
    public function member_method_public() {
        echo "member_method_public: SUCCESS!\n";
    }
    // protected
    protected function member_method_protected() {
        echo "member_method_protected: SUCCESS!\n";
    }
    // private
    private function member_method_private() {
        echo "member_method_private: SUCCESS!\n";
    }
    
    /**************************************************************
    * クラス自身
    ***************************************************************/
    public function execute() {
        
        /*
        * クラス定数
        *****************************************************/
        echo "CONST_PUBLIC: ".self::CONST_PUBLIC."\n";
        echo "CONST_PROTECTED: ".self::CONST_PROTECTED."\n";
        echo "CONST_PRIVATE: ".self::CONST_PRIVATE."\n";

        /*
        * クラス変数
        *****************************************************/
        echo "class_variable_public: ".self::$class_variable_public."\n";
        echo "class_variable_protected: ".self::$class_variable_protected."\n";
        echo "class_variable_private: ".self::$class_variable_private."\n";

        /*
        * クラスメソッド
        *****************************************************/
        self::class_method_public();
        self::class_method_protected();
        self::class_method_private();

        /*
        * メンバー変数
        *****************************************************/
        echo "member_variable_public: ".$this->member_variable_public."\n";
        echo "member_variable_protected: ".$this->member_variable_protected."\n";
        echo "member_variable_private: ".$this->member_variable_private."\n";

        /*
        * メンバーメソッド
        *****************************************************/
        $this->member_method_public();
        $this->member_method_protected();
        $this->member_method_private();
        
    }
    
}

$access_test = new AccessTest();
$access_test->execute();

?>

実行結果

CONST_PUBLIC: SUCCESS!
CONST_PROTECTED: SUCCESS!
CONST_PRIVATE: SUCCESS!
class_variable_public: SUCCESS!
class_variable_protected: SUCCESS!
class_variable_private: SUCCESS!
class_method_public: SUCCESS!
class_method_protected: SUCCESS!
class_method_private: SUCCESS!
member_variable_public: SUCCESS!
member_variable_protected: SUCCESS!
member_variable_private: SUCCESS!
member_method_public: SUCCESS!
member_method_protected: SUCCESS!
member_method_private: SUCCESS!

実行結果から全てアクセスできていることが分かります。

サブクラスからのアクセス

AccessTestクラスを継承したSubAccessTestクラスを定義します。
※ executeメソッドはSubAccessTestクラスのみ。

ソースコード

<?php

// クラス定義
class AccessTest {

    /*
    * クラス定数
    *****************************************************/
    // public
    public const CONST_PUBLIC = 'SUCCESS!';
    // protected
    protected const CONST_PROTECTED = 'SUCCESS!';
    // private
    private const CONST_PRIVATE = 'SUCCESS!';

    /*
    * クラス変数
    *****************************************************/
    // public
    public static $class_variable_public = 'SUCCESS!';
    // protected
    protected static $class_variable_protected = 'SUCCESS!';
    // private
    private static $class_variable_private = 'SUCCESS!';

    /*
    * クラスメソッド
    *****************************************************/
    // public
    public static function class_method_public() {
        echo "class_method_public: SUCCESS!\n";
    }
    // protected
    protected static function class_method_protected() {
        echo "class_method_protected: SUCCESS!\n";
    }
    // private
    private static function class_method_private() {
        echo "class_method_private: SUCCESS!\n";
    }

    /*
    * メンバー変数
    *****************************************************/
    // public
    public $member_variable_public = 'SUCCESS!';
    // protected
    protected $member_variable_protected = 'SUCCESS!';
    // private
    private $member_variable_private = 'SUCCESS!';

    /*
    * メンバーメソッド
    *****************************************************/
    // public
    public function member_method_public() {
        echo "member_method_public: SUCCESS!\n";
    }
    // protected
    protected function member_method_protected() {
        echo "member_method_protected: SUCCESS!\n";
    }
    // private
    private function member_method_private() {
        echo "member_method_private: SUCCESS!\n";
    }
    
}

// クラス定義
class SubAccessTest extends AccessTest {
    
    /**************************************************************
    * サブクラス
    ***************************************************************/
    public function execute() {
        
        /*
        * クラス定数
        *****************************************************/
        echo "CONST_PUBLIC: ".self::CONST_PUBLIC."\n";
        echo "CONST_PROTECTED: ".self::CONST_PROTECTED."\n";
        echo "CONST_PRIVATE: ".self::CONST_PRIVATE."\n";

        /*
        * クラス変数
        *****************************************************/
        echo "class_variable_public: ".self::$class_variable_public."\n";
        echo "class_variable_protected: ".self::$class_variable_protected."\n";
        echo "class_variable_private: ".self::$class_variable_private."\n";

        /*
        * クラスメソッド
        *****************************************************/
        self::class_method_public();
        self::class_method_protected();
        self::class_method_private();

        /*
        * メンバー変数
        *****************************************************/
        echo "member_variable_public: ".$this->member_variable_public."\n";
        echo "member_variable_protected: ".$this->member_variable_protected."\n";
        echo "member_variable_private: ".$this->member_variable_private."\n";

        /*
        * メンバーメソッド
        *****************************************************/
        $this->member_method_public();
        $this->member_method_protected();
        $this->member_method_private();
        
    }
    
}

$access_test = new SubAccessTest();
$access_test->execute();

?>

実行結果

CONST_PUBLIC: SUCCESS!
CONST_PROTECTED: SUCCESS!
PHP Fatal error:  Uncaught Error: Undefined constant SubAccessTest::CONST_PRIVATE in /source-code/sample.php:143
Stack trace:
#0 /source-code/sample.php(256): SubAccessTest->execute()
#1 {main}
  thrown in /source-code/sample.php on line 143

Fatal error: Uncaught Error: Undefined constant SubAccessTest::CONST_PRIVATE in /source-code/sample.php:143
Stack trace:
#0 /source-code/sample.php(256): SubAccessTest->execute()
#1 {main}
  thrown in /source-code/sample.php on line 143

実行結果の途中でエラーが出力されています。

これはprivateな定数にアクセスしようとして出力されているエラーです。privateな変数・メソッドにアクセスしようとした場合も同様のエラーが出力されます。

それでは正常に動作させるため、上記コードから下記のprivateへのアクセスを削除して実行してみましょう。

echo "CONST_PRIVATE: ".self::CONST_PRIVATE."\n";
echo "class_variable_private: ".self::$class_variable_private."\n";
self::class_method_private();
echo "member_variable_private: ".$this->member_variable_private."\n";
$this->member_method_private();

実行結果

CONST_PUBLIC: SUCCESS!
CONST_PROTECTED: SUCCESS!
class_variable_public: SUCCESS!
class_variable_protected: SUCCESS!
sub class_method_public: SUCCESS!
sub class_method_protected: SUCCESS!
member_variable_public: SUCCESS!
member_variable_protected: SUCCESS!
sub member_method_public: SUCCESS!
sub member_method_protected: SUCCESS!

正常に実行されました。この結果からサブクラスではpublicとprotectedにはアクセスできることが分かります。

クラス利用元からのアクセス

AccessTestクラスについて外部(クラス自身でもサブクラスでもないところ)からアクセスしてみましょう。

ソースコード

<?php

// クラス定義
class AccessTest {

    /*
    * クラス定数
    *****************************************************/
    // public
    public const CONST_PUBLIC = 'SUCCESS!';
    // protected
    protected const CONST_PROTECTED = 'SUCCESS!';
    // private
    private const CONST_PRIVATE = 'SUCCESS!';

    /*
    * クラス変数
    *****************************************************/
    // public
    public static $class_variable_public = 'SUCCESS!';
    // protected
    protected static $class_variable_protected = 'SUCCESS!';
    // private
    private static $class_variable_private = 'SUCCESS!';

    /*
    * クラスメソッド
    *****************************************************/
    // public
    public static function class_method_public() {
        echo "class_method_public: SUCCESS!\n";
    }
    // protected
    protected static function class_method_protected() {
        echo "class_method_protected: SUCCESS!\n";
    }
    // private
    private static function class_method_private() {
        echo "class_method_private: SUCCESS!\n";
    }

    /*
    * メンバー変数
    *****************************************************/
    // public
    public $member_variable_public = 'SUCCESS!';
    // protected
    protected $member_variable_protected = 'SUCCESS!';
    // private
    private $member_variable_private = 'SUCCESS!';

    /*
    * メンバーメソッド
    *****************************************************/
    // public
    public function member_method_public() {
        echo "member_method_public: SUCCESS!\n";
    }
    // protected
    protected function member_method_protected() {
        echo "member_method_protected: SUCCESS!\n";
    }
    // private
    private function member_method_private() {
        echo "member_method_private: SUCCESS!\n";
    }
   
}

/**************************************************************
* クラス利用元
***************************************************************/
$access_test = new AccessTest();

/*
* クラス定数
*****************************************************/
echo "CONST_PUBLIC: ".AccessTest::CONST_PUBLIC."\n";
echo "CONST_PROTECTED: ".AccessTest::CONST_PROTECTED."\n";
echo "CONST_PRIVATE: ".AccessTest::CONST_PRIVATE."\n";

/*
* クラス変数
*****************************************************/
echo "class_variable_public: ".AccessTest::$class_variable_public."\n";
echo "class_variable_protected: ".AccessTest::$class_variable_protected."\n";
echo "class_variable_private: ".AccessTest::$class_variable_private."\n";

/*
* クラスメソッド
*****************************************************/
AccessTest::class_method_public();
AccessTest::class_method_protected();
AccessTest::class_method_private();

/*
* メンバー変数
*****************************************************/
echo "member_variable_public: ".$access_test->member_variable_public."\n";
echo "member_variable_protected: ".$access_test->member_variable_protected."\n";
echo "member_variable_private: ".$access_test->member_variable_private."\n";

/*
* メンバーメソッド
*****************************************************/
$access_test->member_method_public();
$access_test->member_method_protected();
$access_test->member_method_private();

?>

実行結果

CONST_PUBLIC: SUCCESS!
PHP Fatal error:  Uncaught Error: Cannot access protected constant AccessTest::CONST_PROTECTED in /source-code/sample.php:218
Stack trace:
#0 {main}
  thrown in /source-code/sample.php on line 218

Fatal error: Uncaught Error: Cannot access protected constant AccessTest::CONST_PROTECTED in /source-code/sample.php:218
Stack trace:
#0 {main}
  thrown in /source-code/sample.php on line 218

実行結果の途中でエラーが出力されています。

これはprotectedな定数にアクセスしようとして出力されているエラーです。protectedな変数・メソッドにアクセスしようとした場合も同様のエラーが出力されます。

それでは下記のprotectedへアクセスの部分を削除して、実行するとどうなるでしょうか?

echo "CONST_PROTECTED: ".AccessTest::CONST_PROTECTED."\n";
echo "class_variable_protected: ".AccessTest::$class_variable_protected."\n";
AccessTest::class_method_protected();
echo "member_variable_protected: ".$access_test->member_variable_protected."\n";
$access_test->member_method_protected();

実行結果

CONST_PUBLIC: SUCCESS!
PHP Fatal error:  Uncaught Error: Cannot access private constant AccessTest::CONST_PRIVATE in /source-code/sample.php:219
Stack trace:
#0 {main}
  thrown in /source-code/sample.php on line 219

Fatal error: Uncaught Error: Cannot access private constant AccessTest::CONST_PRIVATE in /source-code/sample.php:219
Stack trace:
#0 {main}
  thrown in /source-code/sample.php on line 219

次はprivateへのアクセスをしようとしてエラーになります。

こちらも下記のprivateへのアクセスを削除し、実行してみましょう。

echo "CONST_PRIVATE: ".AccessTest::CONST_PRIVATE."\n";
echo "class_variable_private: ".AccessTest::$class_variable_private."\n";
AccessTest::class_method_private();
echo "member_variable_private: ".$access_test->member_variable_private."\n";
$access_test->member_method_private();

実行結果

CONST_PUBLIC: SUCCESS!
class_variable_public: SUCCESS!
class_method_public: SUCCESS!
member_variable_public: SUCCESS!
member_method_public: SUCCESS!

正常に動作しました。これらの結果から外部(クラス利用元)からはpublicにしかアクセスできないことが分かります。

まとめ

アクセス修飾子はクラスへのアクセスを制限する仕組みです。

アクセス修飾子はアプリケーション設計で重要な役割を果たします。設計の知識がないと利用目的が分からないと感じるかもしれませんが、初めはコードを読めるようになるためにアクセス修飾子とその動作について覚えておきましょう。