getter, setterマジックメソッド__get, __setの変な挙動

PHP

09:26:38, by dozo Email , 452 words, 5189 views   Japanese (JP) del.icio.us

オブジェクト指向言語では当たり前なのか、
PHPの言語仕様が変なのか、
私の感覚がハズレまくっているのか、
その辺は解らないが、ちょっとハマッたのでメモ書きしておこう。

(ノ・・)ン。。。。。。(((●コロコロッ

PHP5にはマジックメソッド(Magic Method)なるメソッドが存在する。
クラスを作成するとあらかじめ引っ付いているメソッドのことだ。
種類は
  • __construct
  • __destruct
  • __call
  • __get
  • __set
  • __isset
  • __unset
  • __sleep
  • __wakeup
  • __toString
  • __set_state
  • __clone
  • __autoload


例えばgetter, setterに当たる__get, __setメソッド。
PHP4の場合、ゲッターやセッターは自前で用意でもしない限り存在しないが、
PHP5ではクラスを定義した時点で、
特別記述しなくても__set, __getが定義されている。
使用するときも特別メソッドを呼び出すわけではなく、
プロパティに値を格納したり、
プロパティの値を参照したりした時点で、
マジックメソッドが動き出す。

拡張したいときは、
マジックメソッドをオーバーロード(オーバーライドではない)する。
これによってかなり柔軟なクラス定義が可能になる。



しかし、このマジックメソッド。
いや、getter(ゲッター)、setter(セッター)に限ってかもしれないが。
思わぬ落とし穴があった。

それは、先の文章を引用すると
プロパティに値を格納したり、
プロパティの値を参照したりした時点で、
マジックメソッドが必ず動き出すとはかぎらない


ようだ。


具体的にいうと、
プロパティのアクセス権によってgetterとsetterが利用されない

場合があるということ。

[More:]


こんなサンプルプログラムを用意してみた。
概要をいうと、
  1. 三種類のアクセス権(private, protected, public)のプロパティを用意。
  2. 自動でプロパティを作成するものも一つ用意
  3. そこに1という値を格納する。
  4. setterとgetterが起動するかどうかをみる。

といったところか。
setter(セッター)が起動すると、
__set() start
getter(ゲッター)が起動すると、
__get() start
と表示される。
<?php
    class magicMethod
    {
        private $private;
        protected $protect;
        public $public;
        public function __set( $key, $value )
        {
            echo "__set() start\n";
            $this->$key = $value;
        }
        
        public function __get( $key )
        {
            echo "__get() start\n";
            return $this->$key;
        }
    }
    
    $magicMethodObj = new magicMethod();

    echo "private value ---\n";
    $magicMethodObj->private = 1;
    echo $magicMethodObj->private;
    echo "\n\n";
    
    echo "protected value ---\n";
    $magicMethodObj->protect = 1;
    echo $magicMethodObj->protect;
    echo "\n\n";
    
    echo "public value ---\n";
    $magicMethodObj->public = 1;
    echo $magicMethodObj->public;
    echo "\n\n";
    
    echo "free value ---\n";
    $magicMethodObj->free = 1;
    echo $magicMethodObj->free;
    
?>


さて、想像してみてくれ。
これらはすべて全く同じ動きをするはず。
少なくとも私の感覚では。


結果は
private value ---
__set() start
__get() start
1

protected value ---
__set() start
__get() start
1

public value ---
1

free value ---
__set() start
1


public valueのところをみてもらうと解ると思うが、
__get, __setのかけらも見あたらない。
setter, getterを用意し、
簡単な処理を追加してプロパティをセットしたくても、
publicでは利用できないのだ。
(PHPってほとんどpublicじゃないのか?)


さらに、これがPDOを利用したときに、
もっとおかしな事が起こる。
PDOでfetchクラスを用いてオブジェクトに値を格納するときは、
public扱いになる。
仮にprotectedとしてカラム用のプロパティを定義していたとしても、
値を格納するときはpublic扱いになるようだ。(・ω・`)
つまり

PDOのFETCHで使用すると__setは起動しない



なので、
PDOでマジックメソッドを使用するときは、
protected(またはprivate)でカラムを定義し、
getter(__get)で値を調整する
ことになる。




微妙…。(・ω・`)


Trackback address for this post:

http://hain.jp/htsrv/trackback.php/93

Comments, Trackbacks:

Comment from: Kenji [Visitor]
この説明は誤解に基づいていますね。

__get()、__set()は、定義されているプロパティにアクセスできません。
PermalinkPermalink 2008/12/16 @ 17:42
Comment from: Kenji [Visitor]
昨日コメントしたように思いますが、私のコメントも誤解に基づいていました。

アクセス不能なメンバーの場合も、オーバーロードされますね。

訂正させていただきます。
PermalinkPermalink 2008/12/17 @ 13:30

Leave a comment:

Your email address will not be displayed on this site.
Your URL will be displayed.

Allowed XHTML tags: <p, ul, ol, li, dl, dt, dd, address, blockquote, ins, del, span, bdo, br, em, strong, dfn, code, samp, kdb, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small>
(Line breaks become <br />)
(Set cookies for name, email and url)
(Allow users to contact you through a message form (your email will NOT be displayed.))
This is a captcha-picture. It is used to prevent mass-access by robots.

Please enter the characters from the image above. (case insensitive)

powered by b2evolution

shinobi

Neighbors
Relative
Favorites
PR

極論istの技術屋を始めて早幾年。 流れの速い業界の波にもまれながらも精一杯生きている様をとくとごらんあれ。

Archives
スポンサー

Latest bookmark
Search

Categories

Who's Online?
Misc
Syndicate this blog XML

Valid XHTML 1.0! Valid CSS! Valid RSS 2.0! Valid Atom 1.0!