__set

PHP erlaubt die spontane Erzeugung von Instanzvariablen in einem Objekt zur Laufzeit, ohne dass diese vorher deklariert werden müssen. Diese Instanzvariablen sind implizit public. Mit Hilfe der Methoden __get($memberName) und __set($memberName, $value) kann dieses Verhalten angepasst und so genannte virtuelle Instanzvariablen realisiert werden.

Die Klasse VirtualMembers aus Beispiel 2.4 setzt das Standardverhalten beim Zugriff auf nicht deklarierte Instanzvariablen für ihre Objekte außer Kraft. Sie speichert den Inhalt dieser Variablen in einem Array, das in einer als private deklarierten Instanzvariablen liegt.

Beispiel 2.4: Implementierung von virtuellen Instanzvariablen

<?php
class VirtualMembers {
  private $virtualMembers = array();
 
  public function __get($memberName) {
    @return $this->virtualMembers[$memberName];
  }
 
  public function __set($memberName, $value) {
    $this->virtualMembers[$memberName] = $value;
  }
}
?>


Beispiel 2.5 zeigt mit der Klasse Person einen möglichen Verwendungszweck für virtuelle Instanzvariablen. Die Klasse Person kapselt Personeninformationen, die in einer Tabelle personen in einer Datenbank abgelegt sind. Eine Zeile dieser Tabelle entspricht einer Person, die Spalte id identifiziert jede Person eindeutig (Primärschlüssel). Durch Verwendung von virtuellen Instanzvariablen erlaubt diese Klasse transparenten Schreib-/Lesezugriff auf die Personentabelle über ein Personenobjekt.

Beispiel 2.5: Virtuelle Instanzvariablen im Einsatz

<?php
require_once 'MyProject_DB.php';
 
class Person {
  private $db;
  private $id;
  private $cache = array();
  private $fields = array('name');
 
  public function __construct($id) {
    $this->db = new MyProject_DB;
    $this->id = $id;
  }
 
  public function __get($memberName) {
    if (!in_array($memberName, $this->fields)) {
      return;
    }
 
    if (!isset($this->cache[$memberName])) {
      $this->db->query(
        sprintf(
          "SELECT %s
             FROM personen
            WHERE id = '%d';",
 
          $memberName,
          $this->id
        )
      );
 
      if ($row = $mysql->fetchRow()) {
        $this->cache[$memberName] = $row['name'];
      }
    }
 
    return $this->cache[$memberName];
  }
 
  public function __set($memberName, $value) {
    if (!in_array($memberName, $this->fields)) {
      return;
    }
 
    $this->db->query(
      sprintf(
        "REPLACE INTO personen
                 (id, %s)
          VALUES ('%d', '%s');",
 
        $memberName,
        $this->id,
        $value
      )
    );
 
    $this->cache[$memberName] = $value;
  }
}
?>