11

同様__constructの質問で について説明していますが、これを見つけた検索者のためにタイトルに残しました。

どうやら、__get と __set は、取得または設定される変数であるパラメーターを取ります。ただし、変数名を知っている必要があります (たとえば、人の年齢が $myAge ではなく $age であることを知っているなど)。したがって、変数名を知っている必要がある場合、特によく知らないコード (ライブラリなど) を操作している場合は、意味がわかりません。

__get()__set()、およびを説明しているページをいくつか見つけまし__call()たが、なぜ、いつ役立つのかはまだわかりません。

4

10 に答える 10

6

このページはきっと役に立ちます。(あなたの言うことは間違っていることに注意してください-__set()変数の名前と値の両方をパラメーターとして取ります。__get()変数の名前だけを取ります)。

__get()変数へ__set()の汎用アクセスを提供するライブラリ関数で役立ちます。たとえば、ActiveRecord クラスでは、オブジェクト プロパティとしてデータベース フィールドにアクセスできるようにする必要がある場合があります。たとえば、Kohana PHP フレームワークでは、次を使用できます。

$user = ORM::factory('user', 1);
$email = $user->email_address;

これは、 と を使用して実現され__get()ます__set()

を使用すると、同様のことが実現できます__call()。つまり、誰かが getProperty() および setProperty() を呼び出していることを検出し、それに応じて処理できます。

于 2008-10-30T15:37:39.417 に答える
5

__get()、__set()、および __call() は、PHP が「マジック メソッド」と呼ぶもので、これは少しばかげていると思います。「フック」はもう少し適切だと思います。とにかく脱線…

これらの目的は、オブジェクトで定義されていないデータメンバー (プロパティまたはメソッド)がアクセスされたときの実行ケースを提供することです。これは、変数の隠蔽、メッセージ転送など、あらゆる種類の「巧妙な」思考に使用できます。

ただし、コストがかかります。これらを呼び出す呼び出しは、定義されたデータメンバーへの呼び出しよりも約 10 倍遅くなります。

于 2008-10-30T15:41:40.517 に答える
3

__getand の再定義__setは、コア クラスで特に役立ちます。たとえば、構成を誤って上書きしたくないが、そこからデータを取得したい場合:

class Example
{
    private $config = array('password' => 'pAsSwOrD');
    public function __get($name)
    {
        return $this->config[$name];
    }
}
于 2008-10-30T15:42:47.067 に答える
2

マジック メソッドのもう 1 つの便利なアプリケーションは、特に__getand__set__toStringテンプレートです。マジック メソッドを使用する単純なアダプターを作成するだけで、テンプレート エンジンからコードを独立させることができます。別のテンプレート エンジンに移行する場合は、これらのメソッドのみを変更してください。

class View {

    public $templateFile;
    protected $properties = array();

    public function __set($property, $value) {
        $this->properties[$property] = $value;
    }

    public function __get($property) {
        return @$this->properties[$property];
    }

    public function __toString() {
        require_once 'smarty/libs/Smarty.class.php';
        $smarty = new Smarty();
        $smarty->template_dir = 'view';
        $smarty->compile_dir = 'smarty/compile';
        $smarty->config_dir = 'smarty/config';
        $smarty->cache_dir = 'smarty/cache';
        foreach ($this->properties as $property => $value) {
            $smarty->assign($property, $value);
        }
        return $smarty->fetch($this->templateFile);
    }

}

このアプローチの隠れた利点は、View オブジェクトを別のオブジェクト内にネストできることです。

$index = new View();
$index->templateFile = 'index.tpl';

$topNav = new View();
$topNav->templateFile = 'topNav.tpl';

$index->topNav = $topNav;

ではindex.tpl、ネスティングは次のようになります。

<html>
<head></head>
<body>
    {$topNav}
    Welcome to Foobar Corporation.
</body>
</html>

ネストされたすべての View オブジェクトは、すぐにその場で文字列 (正確には HTML) に変換されます。echo $index;

于 2008-10-30T15:58:34.693 に答える
1

PHP では、クラス変数を動的に作成できるため、問題が発生する可能性があります。__set および __get メソッドを使用して、この動作を制限できます..以下の例を参照してください...

class Person { 
      public $name;
      public function printProperties(){
       print_r(get_object_vars($this));
      }
}

$person = new Person();
$person->name = 'Jay'; //This is valid
$person->printProperties();
$person->age = '26';  //This shouldn't work...but it does 
$person->printProperties();

上記を防ぐために、これを行うことができます..

public function __set($name, $value){
    $classVar = get_object_vars($this);
    if(in_array($name, $classVar)){
    $this->$name = $value;
    }
}

お役に立てれば...

于 2013-02-16T05:22:48.173 に答える
0

彼らは「賢い」ことをするためのものです。

たとえば、 and を使用してデータベースと対話でき__set()ます__get()。コードは次のようになります。$myObject->foo = "bar";これにより、舞台裏でデータベース レコードが更新される可能性があります。もちろん、これにはかなり注意する必要があります。そうしないと、パフォーマンスが低下する可能性があるため、「賢い」という引用符があります:)

于 2008-10-30T15:38:00.413 に答える
0

メソッドのオーバーロードは、簡単にアクセスできる必要があるデータを含む PHP オブジェクトを操作する場合に特に便利です。__get()存在しないプロパティにアクセスするときに呼び出され、 __set()は存在しないプロパティを書き込もうとすると呼び出され、 __call()は存在しないメソッドが呼び出されるときに呼び出されます。

たとえば、構成を管理するクラスがあるとします。

class Config
{
    protected $_data = array();

    public function __set($key, $val)
    {
        $this->_data[$key] = $val;
    }

    public function __get($key)
    {
        return $this->_data[$key];
    }

    ...etc

}

これにより、オブジェクトの読み取りと書き込みが非常に簡単になり、オブジェクトの読み取りまたは書き込み時にカスタム機能を使用できるようになります。例:

$config = new Config();
$config->foo = 'bar';

echo $config->foo; // returns 'bar'
于 2008-10-30T15:39:21.580 に答える
0

それらを使用する正当な理由の 1 つは、レジストリ システムに関してです (Zend Framework はこれを Registry または Config クラス iirc として実装していると思います)。そのため、次のようなことができます。

$conf = new Config();
$conf->parent->child->grandchild = 'foo';

これらの各プロパティは、自動生成された Config オブジェクトであり、次のようなものです。

function __get($key) {
    return new Config($key);
}

明らかに $conf->parent が既に存在する場合、 __get() メソッドは呼び出されないため、これを使用して新しい変数を生成するのは良いトリックです。

引用したばかりのこのコードは機能的ではないことに注意してください。例のために簡単に書いただけです。

于 2008-10-30T15:43:06.863 に答える
0

おそらく世界で最もクリーンなデザインではありませんが、クラス内のインスタンス変数を参照しているコードがたくさんある状況がありました。

$obj->value = 'blah';
echo $obj->value;

しかし、後で、特定の状況で「値」が設定されたときに何か特別なことをしたかったので、値変数の名前を変更し、必要な変更を加えて __set() と __get() を実装しました。

コードの残りの部分では違いがわかりませんでした。

于 2008-10-30T15:47:03.827 に答える