【PHP】アクセス修飾子 - クラスのプロパティにおけるアクセス制御

【PHP】アクセス修飾子 - クラスのプロパティにおけるアクセス制御

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

アクセス修飾子を使うことで、クラスのフィールドやメソッドへのアクセスを制御することができます。/p>

ここでは、アクセス修飾子について解説します。

検証環境

アクセス修飾子

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

クラス外部・クラス内部・サブクラスからのアクセスについて、フィールドやメソッドなどに個別にアクセス権を付与して制御することができます。

種類

アクセス修飾子の種類はpublicprotectedprivateの3つです。

各アクセス修飾子とアクセス元の制限は次のようになります。

アクセス修飾子とアクセス元
アクセス元 public protected private
クラス内部
サブクラス ×
クラス外部 × ×

基本構文

class クラス名 {
    // クラス定数
    アクセス修飾子 クラス定数名;
    // クラス変数
    アクセス修飾子 static クラス変数;
    // クラスメソッド
    アクセス修飾子 static function メソッド名() {}
    // フィールド
    アクセス修飾子 フィールド名;
    // メソッド
    アクセス修飾子 function メソッド名() {}
}

アクセス修飾子はプロパティ(クラス定数やクラス変数、フィールド、メソッドなど)の定義の先頭に記述します。

アクセス修飾子の記述がないプロパティは、自動でpublicになりますが、アクセス権を明確にするため、極力明記することを推奨します。

アクセス制御の確認

次のAccessTestクラスを使って、アクセス制御を確認します。

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
}

?>

AccessTestクラスはクラス定数・クラス変数・クラスメソッド・フィールド・メソッドに対して3つのアクセス修飾子(public/protected/private)を所持します。

クラス内部からのアクセス

クラス内部からアクセスするため、executeメソッドを定義し、呼び出します。

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
    ___ih_diff_start
+    /**************************************************************
+    * クラス内部からのアクセス
+    ***************************************************************/
+    function execute() {
+        
+        /*
+        * クラス定数
+        *****************************************************/
+        echo self::CONST_PUBLIC;
+        echo self::CONST_PROTECTED;
+        echo self::CONST_PRIVATE;
+        
+        /*
+        * クラス変数
+        *****************************************************/
+        echo self::$class_variable_public;
+        echo self::$class_variable_protected;
+        echo self::$class_variable_private;
+        
+        /*
+        * クラスメソッド
+        *****************************************************/
+        self::class_method_public();
+        self::class_method_protected();
+        self::class_method_private();
+        
+        /*
+        * フィールド
+        *****************************************************/
+        echo $this->field_public;
+        echo $this->field_protected;
+        echo $this->field_private;
+        
+        /*
+        * メソッド
+        *****************************************************/
+        $this->method_public();
+        $this->method_protected();
+        $this->method_private();
+        
+    }
    ___ih_diff_end
}

___ih_diff_start
+$access_test = new AccessTest();
+$access_test->execute();
___ih_diff_end

?>
$ php sample1.php
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!
field_public             : SUCCESS!
field_protected          : SUCCESS!
field_private            : SUCCESS!
method_public            : SUCCESS!
method_protected         : SUCCESS!
method_private           : SUCCESS!

実行結果から全てのプロパティにアクセスできたことが分かります。

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

AccessTestクラスを継承したSubAccessTestクラスを定義します。

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
}

___ih_diff_start
+class SubAccessTest extends AccessTest {
+    
+    /**************************************************************
+    * サブクラス
+    ***************************************************************/
+    public function execute() {
+        
+        /*
+        * クラス定数
+        *****************************************************/
+        echo self::CONST_PUBLIC;
+        echo self::CONST_PROTECTED;
+        echo self::CONST_PRIVATE;
+        
+        /*
+        * クラス変数
+        *****************************************************/
+        echo self::$class_variable_public;
+        echo self::$class_variable_protected;
+        echo self::$class_variable_private;
+        
+        /*
+        * クラスメソッド
+        *****************************************************/
+        self::class_method_public();
+        self::class_method_protected();
+        self::class_method_private();
+        
+        /*
+        * フィールド
+        *****************************************************/
+        echo $this->field_public;
+        echo $this->field_protected;
+        echo $this->field_private;
+        
+        /*
+        * メソッド
+        *****************************************************/
+        $this->method_public();
+        $this->method_protected();
+        $this->method_private();
+        
+    }
+    
+}
___ih_diff_end

___ih_diff_start
+$access_test = new SubAccessTest();
+$access_test->execute();
___ih_diff_end

?>
$ php sample2.php
CONST_PUBLIC             : SUCCESS!
CONST_PROTECTED          : SUCCESS!
PHP Fatal error:  Uncaught Error: Undefined constant SubAccessTest::CONST_PRIVATE in sample2.php:97
Stack trace:
#0 sample.php(132): SubAccessTest->execute()
#1 {main}
  thrown in sample2.php on line 97

AccessTestクラスのプロパティにサブクラスであるSubAccessTestexecuteメソッドからアクセスするとエラーが発生します。

この原因はprivateなプロパティにアクセスしているためです。

privateなプロパティへのアクセスを削除し、改めて実行します。

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
}

class SubAccessTest extends AccessTest {
    
    /**************************************************************
    * サブクラス
    ***************************************************************/
    public function execute() {
        
        /*
        * クラス定数
        *****************************************************/
        echo self::CONST_PUBLIC;
        echo self::CONST_PROTECTED;
___ih_diff_start        
-        echo self::CONST_PRIVATE;
___ih_diff_end
        
        /*
        * クラス変数
        *****************************************************/
        echo self::$class_variable_public;
        echo self::$class_variable_protected;
___ih_diff_start        
-        echo self::$class_variable_private;
___ih_diff_end
        
        /*
        * クラスメソッド
        *****************************************************/
        self::class_method_public();
        self::class_method_protected();
___ih_diff_start        
-        self::class_method_private();
___ih_diff_end
        
        /*
        * フィールド
        *****************************************************/
        echo $this->field_public;
        echo $this->field_protected;
___ih_diff_start        
-        echo $this->field_private;
___ih_diff_end
        
        /*
        * メソッド
        *****************************************************/
        $this->method_public();
        $this->method_protected();
___ih_diff_start        
-        $this->method_private();
___ih_diff_end
        
    }
    
}
___ih_diff_end

___ih_diff_start
+$access_test = new SubAccessTest();
+$access_test->execute();
___ih_diff_end

?>
$ php sample2.php
CONST_PUBLIC             : SUCCESS!
CONST_PROTECTED          : SUCCESS!
class_variable_public    : SUCCESS!
class_variable_protected : SUCCESS!
class_method_public      : SUCCESS!
class_method_protected   : SUCCESS!
field_public             : SUCCESS!
field_protected          : SUCCESS!
method_public            : SUCCESS!
method_protected         : SUCCESS!

正常に実行されました。

この結果からサブクラスではpublicとprotectedにアクセスできることが分かります。

クラス外部からのアクセス

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

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
}

___ih_diff_start
+/**************************************************************
+* クラス外部
+***************************************************************/
+$access_test = new AccessTest();
+
+/*
+* クラス定数
+*****************************************************/
+echo AccessTest::CONST_PUBLIC;
+echo AccessTest::CONST_PROTECTED;
+echo AccessTest::CONST_PRIVATE;
+
+/*
+* クラス変数
+*****************************************************/
+echo AccessTest::$class_variable_public;
+echo AccessTest::$class_variable_protected;
+echo AccessTest::$class_variable_private;
+
+/*
+* クラスメソッド
+*****************************************************/
+AccessTest::class_method_public();
+AccessTest::class_method_protected();
+AccessTest::class_method_private();
+
+/*
+* フィールド
+*****************************************************/
+echo $access_test->field_public;
+echo $access_test->field_protected;
+echo $access_test->field_private;
+
+/*
+* メソッド
+*****************************************************/
+$access_test->method_public();
+$access_test->method_protected();
+$access_test->method_private();
___ih_diff_end

?>
$ php sample3.php
CONST_PUBLIC             : SUCCESS!
PHP Fatal error:  Uncaught Error: Cannot access protected constant AccessTest::CONST_PROTECTED in sample3.php:52
Stack trace:
#0 {main}
  thrown in sample3.php on line 52

クラス外部からアクセスするとエラーが発生します。

この原因はprotectedなプロパティにアクセスしているためで、privateなプロパティにアクセスした場合も同様のエラーが発生します。

protectedprivateなプロパティへのアクセスを削除し、改めて実行します。

<?php

// クラス
class AccessTest {
    
    /*
    * クラス定数
    *****************************************************/
    public    const CONST_PUBLIC    = "CONST_PUBLIC             : SUCCESS!\n";
    protected const CONST_PROTECTED = "CONST_PROTECTED          : SUCCESS!\n";
    private   const CONST_PRIVATE   = "CONST_PRIVATE            : SUCCESS!\n";
    
    /*
    * クラス変数
    *****************************************************/
    public     static $class_variable_public    = "class_variable_public    : SUCCESS!\n";
    protected  static $class_variable_protected = "class_variable_protected : SUCCESS!\n";
    private    static $class_variable_private   = "class_variable_private   : SUCCESS!\n";
    
    /*
    * クラスメソッド
    *****************************************************/
    public    static function class_method_public()    { echo "class_method_public      : SUCCESS!\n"; }
    protected static function class_method_protected() { echo "class_method_protected   : SUCCESS!\n"; }
    private   static function class_method_private()   { echo "class_method_private     : SUCCESS!\n"; }
    
    /*
    * フィールド
    *****************************************************/
    public    $field_public    = "field_public             : SUCCESS!\n";
    protected $field_protected = "field_protected          : SUCCESS!\n";
    private   $field_private   = "field_private            : SUCCESS!\n";
    
    /*
    * メソッド
    *****************************************************/
    public    function method_public()    { echo "method_public            : SUCCESS!\n"; }
    protected function method_protected() { echo "method_protected         : SUCCESS!\n"; }
    private   function method_private()   { echo "method_private           : SUCCESS!\n"; }
    
}

/**************************************************************
* クラス外部
***************************************************************/
$access_test = new AccessTest();

/*
* クラス定数
*****************************************************/
echo AccessTest::CONST_PUBLIC;
___ih_diff_start
-echo AccessTest::CONST_PROTECTED;
-echo AccessTest::CONST_PRIVATE;
___ih_diff_end

/*
* クラス変数
*****************************************************/
echo AccessTest::$class_variable_public;
___ih_diff_start
-echo AccessTest::$class_variable_protected;
-echo AccessTest::$class_variable_private;
___ih_diff_end

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

/*
* フィールド
*****************************************************/
echo $access_test->field_public;
___ih_diff_start
-echo $access_test->field_protected;
-echo $access_test->field_private;
___ih_diff_end

/*
* メソッド
*****************************************************/
$access_test->method_public();
___ih_diff_start
-$access_test->method_protected();
-$access_test->method_private();
___ih_diff_end

?>
$ php sample3.php
CONST_PUBLIC             : SUCCESS!
class_variable_public    : SUCCESS!
class_method_public      : SUCCESS!
field_public             : SUCCESS!
method_public            : SUCCESS!

正常に実行されました。

この結果からクラス外部からはpublicなプロパティのみアクセスできることが分かります。