0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[PHP]親クラスのプロパティを取得する

Posted at

親クラスのプロパティの値を参照したいことがある。
特に、デフォルトの設定値をクラスごとに設定する場合など。

<?php

class A
{
    public $config = ['prop1' => 'A', 'prop2' => 'A', 'prop3' => 'A', 'prop4' => 'A'];
}

class B extends A
{
    public $config = ['prop1' => 'B', 'prop2' => 'B', 'prop3' => 'B'];
}

class C extends B
{
    public $config = ['prop1' => 'C', 'prop2' => 'C'];
}

class D extends C
{
    public $config = ['prop1' => 'D'];
}

$d = new D();
var_dump($d->config);

実行結果

array(1) {
  ["prop1"]=>
  string(1) "D"
}

親クラスに ['prop2' => 'C'] が設定されてようがされてなかろうが、
class D に書かれた$configしか参照できない。

それでは困るので、解決策。

<?php

class A
{
    public $config = ['prop1' => 'A', 'prop2' => 'A', 'prop3' => 'A', 'prop4' => 'A'];
}

class B extends A
{
    public $config = ['prop1' => 'B', 'prop2' => 'B', 'prop3' => 'B'];
}

class C extends B
{
    public $config = ['prop1' => 'C', 'prop2' => 'C'];
}

class D extends C
{
    public $config = ['prop1' => 'D'];
}

$d = new D();

// 現在のクラス名を取得
$class = get_class($d);

while (true) {
    $parent = get_parent_class($class);
    echo $parent."\n"; // 親クラスの名前
    if (!$parent) {
        break;
    }
    $parents[] = $parent;
    $class = $parent;
}
foreach ($parents as $parent) {
    $vars = get_class_vars($parent);
    var_dump($vars); // 結果を出力
}

結果がこちら。

array(1) {
  ["config"]=>
  array(2) {
    ["prop1"]=>
    string(1) "C"
    ["prop2"]=>
    string(1) "C"
  }
}
array(1) {
  ["config"]=>
  array(3) {
    ["prop1"]=>
    string(1) "B"
    ["prop2"]=>
    string(1) "B"
    ["prop3"]=>
    string(1) "B"
  }
}
array(1) {
  ["config"]=>
  array(4) {
    ["prop1"]=>
    string(1) "A"
    ["prop2"]=>
    string(1) "A"
    ["prop3"]=>
    string(1) "A"
    ["prop4"]=>
    string(1) "A"
  }
}

これで取得できる!
ただし、merge された状態での取得はできない。

ということで、何も考えずに勝手にconfig がマージされるtrait を作ってみた。

<?php

trait configMerger
{
    public function __construct()
    {
        $class = get_class($this);
        $classes[] = $class;
        while (true) {
            $parent = get_parent_class($class);
            if (!$parent) {
                break;
            }
            $classes[] = $parent;
            $class = $parent;
        }
        foreach ($classes as $class) {
            $vars = get_class_vars($class);
            $this->config += $vars['config'];
        }
    }
}

class A
{
    use configMerger;
    public $config = ['prop1' => 'A', 'prop2' => 'A', 'prop3' => 'A', 'prop4' => 'A'];
}

class B extends A
{
    public $config = ['prop1' => 'B', 'prop2' => 'B', 'prop3' => 'B'];
}

class C extends B
{
    public $config = ['prop1' => 'C', 'prop2' => 'C'];
}

class D extends C
{
    public $config = ['prop1' => 'D'];
}

$d = new D();
var_dump($d->config);


結果は、

array(4) {
  ["prop1"]=>
  string(1) "D"
  ["prop2"]=>
  string(1) "C"
  ["prop3"]=>
  string(1) "B"
  ["prop4"]=>
  string(1) "A"
}

となり、ちゃんとマージされたconfigが取得できた。

ちなみに、この例では、 classA の中で use configMerger; を書いているが、
class Aがライブラリのコードで触ることができない場合、
class Duse configMerger;を書いても同じ挙動を期待できる。

あまり使う機会はないかと思うが、古いライブラリとかを使う時に知っておくと便利かもしれないtipsでした。

0
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?