📑

PHP勉強:アクセス権(Visibility)について

2021/09/25に公開

php オフィシャルドキュメント -> Visibility

動作環境

php 7.4.22


アクセス権(Visibility)とは?

PHPには変数や関数を定義するときにアクセス権プロパティを定義できる。
プロパティはフィールドとも呼ばれており、publicprivateprotectedの3種がある。

public $public       = 'public';
private $private     = 'private';
protected $protected = 'protected';

基本的にクラス内で使用され、外部からのアクセス範囲を設定できる。
publicはクラス外からでも呼び出すことができ、privateはそのクラス自身のみが呼び出せる。protectedはクラス自身とそれを継承したクラスならば呼び出すことができる。


Public

<?php

class Foo {
  // publicプロパティの定義
  public $public = 'Public';

  // Fooクラス内で$publicを呼び出す
  public function getPublic() {
    return $this->public.' from '.__METHOD__;
  }
}

$foo = new Foo();

// 外部からの変数呼び出し
echo $foo->public.'<br>';
// 結果:Public

// 外部からのFooクラスの関数を使っての呼び出し
echo $foo->getPublic().'<br>'; 
// 結果:Public from Foo::getPublic

PHPではプロパティを指定しない場合、すべてpublicとして扱われる。

<?php

//publicになる
$foo = 'foo'; 

//publicになる
function getFoo() { // public
  return $this->foo;
}

Private

そのクラス自身のみが呼び出すことができる。

<?php

class Foo {
  // privateプロパティの定義
  private $private = 'Private';

  // Fooクラス内で$privateを呼び出す
  public function getPrivate() {
    return $this->private.' from '.__METHOD__;
  }
}


$foo = new Foo();

// 外部からの変数呼び出し
// privateプロパティにアクセスしようとしているため、エラーとなる。
echo $foo->private.'<br>';
//結果: Fatal error: Uncaught Error: Cannot access private property

// 外部からFooクラス内の関数を使っての呼び出し
// クラスそのものの内部の関数からのアクセスなので、問題なく呼び出せる。
echo $foo->getPrivate().'<br>'; 
//結果: Private from Foo::getPrivate

Fooを継承したFooChildが親クラスであるFooのprivateプロパティにアクセスしようとしたらどうなるか?

<?php

class Foo {
  // 親側でprivateプロパティの定義
  private $private = 'Private';

  // Fooクラス内で$privateを呼び出す
  public function getPrivate() {
    return $this->private.' from '.__METHOD__;
  }
}

class FooChild extends Foo {

  // FooChildクラス内でFooの$privateを呼び出す
  public function getPrivateChild() {
    return $this->private.' from '.__METHOD__;
  }
}


$foo_child = new FooChild();

// 外部からの変数呼び出し
// 変数への直接の呼び出しになり、NULLになる。
echo $foo_child->private.'<br>';
// NULL

// 外部からFooクラス内の関数を使っての呼び出し
// Fooクラス内の関数を使っての$privateへのアクセスなので、出力される。
echo $foo_child->getPrivate().'<br>'; 
// Private from Foo::getPrivate

// 外部からFooChildクラス内の関数を使っての呼び出し
// FooChildの中で定義されている関数からの呼び出しのため、NULLとなる。
echo $foo_child->getPrivateChild().'<br>'; 
// NULL

Protected

クラスの外部からは呼び出せないけど、そのクラス自身とそのクラスを継承したクラスはアクセスできる。

<?php

class Foo {
  // protectedプロパティの定義
  protected $protected = 'Protected';

  // Fooクラス内で$protectedを呼び出す
  public function getProtected() {
    return $this->protected.' from '.__METHOD__;
  }
}

$foo = new Foo();

// 外部からの変数呼び出し
// protectedプロパティにアクセスしようとしているため、エラーとなる。
echo $foo->protected.'<br>';
// Fatal error: Uncaught Error: Cannot access protected property Foo::$protected 

// 外部からFooクラス内の関数を使っての呼び出し
// クラスそのものの内部の関数からのアクセスなので、問題なく呼び出せる。
echo $foo->getProtected().'<br>';
//Protected from Foo::getProtected

ここまではprivateとほとんど同じ挙動になるが、クラス継承をする際に違いがでる。

<?php 

class Foo {
  // 親側でprivateプロパティの定義
  protected $protected = 'Protected';

  // Fooクラス内で$protectedを呼び出す
  public function getProtected() {
    return $this->protected.' from '.__METHOD__;
  }
}

class FooChild extends Foo {
  // FooChildクラス内でFooの$protectedを呼び出す
  public function getProtectedChild() {
    return $this->protected.' from '.__METHOD__;
  }
}

$foo_child = new FooChild();

// 外部からの変数呼び出し
// 変数への直接の呼び出しになり、protectedではエラーとなる。
echo $foo_child->protected.'<br>';
// Fatal error: Uncaught Error: Cannot access protected property FooChild::$protected

// 外部からFooクラス内の関数を使っての呼び出し
// Fooクラス内の関数を使っての$protectedへのアクセスなので出力される。
echo $foo_child->getProtected().'<br>'; 
// Protected from Foo::getProtected

// 外部からFooChildクラス内の関数を使っての呼び出し
// FooChildクラス内に存在する関数から呼び出しのため出力される。
echo $foo_child->getProtectedChild().'<br>'; 
// Protected from FooChild::getProtectedChild

Discussion