2010-07-21 2 views
14

C'est ce que j'ai: Tous les objets qui peuvent être persistaient sur la base de données étendent la classe abstraite DatabaseObject, qui a tout le code logique de regarder en fait des changements d'attributs et exécuter les requêtes Databas.Comment remplacer une propriété statique d'un objet parent et laisser l'objet parent accéder à la nouvelle valeur dans PHP?

J'utilise deux variables statiques pour définir les détails spécifiques à l'objet. Je les définis génériquement dans la classe de base, puis je les écrase dans les objets de la base de données.

Le problème est le suivant: Lorsque le code dans la classe parente est effectivement exécuté, il utilise l'ancienne valeur parent au lieu de la valeur de l'objet en cours.

Voici le code pour la classe de base:

abstract class DatabaseObject { 

    public $id; 

    private static $databaseTable = NULL; 
    private static $databaseFields = array(); 

    private $data = array(); 
    private $changedFields = array(); 

    public function IDatabaseObject($id) { 
    $this->id = $id; 
    $this->data = Database::GetSingle(self::$databaseTable, $id); 

    Utils::copyToObject($this, $this->data, self::$databaseFields); 
    } 

    public static function Load($id) { 
    return new self($userID); 
    } 

    public static function Create($data) { 

    $id = Database::Insert(self::$databaseTable, $data); 

    return new self($id); 
    } 

    public function Save() { 
    $data = Utils::copyFromObject($this, $this->changedFields); 

    Database::Update(self::$databaseTable, $data, $this->id); 

    } 

    public function __constructor() { 
    // We do this to allow __get and __set to be called on public vars 
    foreach(self::$databaseFields as $field) { 
     unset($this->$field); 
    } 
    } 

    public function __get($variableName) { 
    return $this->$variableName; 
    } 

    public function __set($variableName, $variableValue) { 
    // We only want to update what has been changed 
    if(!in_array($variableName, $this->changedFields) && in_array($variableName, self::$databaseFields)) { 
     array_push($this->changedFields, $variableName); 
    } 

    $this->$variableName = $variableValue; 
    } 
} 

Et voici le code pour l'un des objets étendant la classe de base ci-dessus:

class Client extends DatabaseObject { 

    public static $databaseTable = "clients"; 
    public static $databaseFields = array("name","contactName","primaryUserID","email","is_active","rg","cpf","cnpj","ie","addrType","addrName","addrNumber","addrComplement","addrPostalCode","addrNeighborhood","addrCity","addrState","addrCountry","phoneLandline","phoneFax","phoneMobile"); 

    public $name; 
    public $contactName; 

    public $primaryUserID; 
    public $email; 

    public $is_active; 

    public $rg; 
    public $cpf; 
    public $cnpj; 
    public $ie; 

    public $addrType; 
    public $addrName; 
    public $addrNumber; 
    public $addrComplement; 
    public $addrPostalCode; 
    public $addrNeighborhood; 
    public $addrCity; 
    public $addrState; 
    public $addrCountry; 

    public $phoneLandline; 
    public $phoneFax; 
    public $phoneMobile; 

    public static function Load($id) { 
return new Client($id); 
    } 

} 

Qu'est-ce que je fais mal ici? Existe-t-il un autre moyen de parvenir au même résultat?

Un bref addendum: Je déclare les attributs dans le corps de la classe principalement laissait voir par la fonctionnalité complète-automatique de NetBeans.

+1

double possible de [l'héritage de classe en PHP 5.2: variable statique Redéfinition en classe d'extension] (http://stackoverflow.com/questions/3017777/class-inheritance-in -php-5-2-overriding-static-variable-in-extension-class) – outis

+0

Il s'agit d'une question légitime en PHP, qui a une implémentation assez confuse, mais la question pourrait vraiment être réduite pour la rendre plus générique et accessible pour que d'autres puissent en bénéficier. –

Répondre

41

Vous cherchez Late Static Binding.

Vous devez utiliser:

static::$databaseTable 

au lieu de

self::$databaseTable 

Cette fonction est disponible depuis PHP 5.3. Simuler cela en PHP 5.2 est très difficile, pour deux raisons: get_called_class n'est disponible que depuis PHP 5.3 aussi. Par conséquent, il doit être simulé, aussi, en utilisant debug_backtrace. Le deuxième problème est que si vous avez la classe appelée, vous ne pouvez toujours pas utiliser $calledClass::$property car c'est aussi une fonctionnalité de PHP 5.3. Ici, vous devez utiliser eval ou Reflection. J'espère donc que vous avez PHP 5.3;)

+0

Malheureusement, je ne peux pas mettre à jour ma version de PHP. Le serveur exécute Plesk 9.5, qui ne prend en charge que jusqu'à 5.2.13; Je crains que la mise à jour manuelle ne puisse briser certaines applciations. Je vais voir si je peux concevoir une autre façon de faire la même chose. – DfKimera

+0

Merci beaucoup pour cette astuce, j'ai eu exactement le même problème! –

+0

La meilleure façon consiste à passer la classe en tant que premier paramètre à toute méthode qui doit accéder à ces propriétés. De cette façon, vous pouvez rechercher cette classe directement pour un remplacement. Si vous ne le trouvez pas, vous pouvez remonter l'échelle des parents jusqu'à ce que vous trouviez le champ. –

Questions connexes