JavaScriptを有効にしてください

【PHP】柔らかいプロパティの扱い __set __get の罠

 ·   ·  ☕ 2 分で読めます

【PHP】柔らかいプロパティの扱い __set __get の罠

柔軟な PHP の柔らかいプロパティの扱いでマジックメソッド __set __get の罠があります。
PHP: マジックメソッド - Manual

確認環境

PHPはとても柔軟

PHP はとても柔軟な言語で以下のように宣言していないプロパティを実行しても柔軟に吸収をしてくれます。

1
2
3
4
5
6
7
<?php
class Hoge{
}

$hoge = new Hoge();
$hoge->piyo = 'piyo';
var_dump($hoge);

出力結果

object(Hoge)#1 (2) {
  ["piyo"]=>
  string(4) "piyo"
}

__get __setを使ってみる

マジックメソッドの __get __set を使用してみます。

  • __get はクラスにないプロパティを取得する際に呼ばれます。
  • __set はクラスにないプロパティを設定する際に呼ばれます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
class Hoge
{
    public function __set($name, $value)
    {
        $this->$name = $value;
    }
    
    public function __get($name)
    {
        if(isset($this->$name)) {
            return $this->$name;
        }
        return null;
    }
}

$hoge = new Hoge();
$hoge->piyo = 'piyo';
var_dump($hoge);

出力結果

1
2
3
4
object(Hoge)#1 (2) {
  ["piyo"]=>
  string(4) "piyo"
}

__set __get の罠

マジックメソッドの __get __set を使用はなんにも問題ないように見えますが…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Hoge
{
    public function __set($name, $value)
    {
        $this->$name = $value;
    }
    
    public function __get($name)
    {
        if(isset($this->$name)) {
            return $this->$name;
        }
        return null;
    }
}

$hoge = new Hoge();
$hoge->piyo = 'piyo';
$hoge->fuga[0] = 'test';
var_dump($hoge);

こうすると Notice が出てきます。
どこかしら不具合が出る可能性が高くなるので気をつけてください。

この場合、先に __get が動いてしまい、存在しないクラスにないプロパティ fuga の配列を見ようとしてエラーが出ます。
おそらく配列の場合は配列のキーを主体にしているためだと思います。

とても柔らかくしたい

柔軟なやり取りを行いたい場合は __get __set を使わないようするのが一番だと思われます。

1
2
3
4
5
6
7
8
9
<?php
class Hoge
{
}

$hoge = new Hoge();
$hoge->piyo = 'piyo';
$hoge->fuga[0] = 'test';
var_dump($hoge);
1
2
3
4
5
6
7
8
9
object(Hoge)#1 (2) {
  ["piyo"]=>
  string(4) "piyo"
  ["fuga"]=>
  array(1) {
    [0]=>
    string(4) "test"
  }
}
共有

こぴぺたん
著者
こぴぺたん
Copy & Paste Engineer