2010-07-21 12 views
14

Esto es lo que tengo: todos los objetos que pueden persistir en la base de datos extienden la clase abstracta de DatabaseObject, que tiene todo el código lógico para vigilar realmente los cambios de atributos y ejecutar las consultas de databas.¿Cómo anular una propiedad estática de un objeto primario y dejar que el objeto padre acceda al nuevo valor en PHP?

Estoy usando dos variables estáticas para definir detalles específicos del objeto. Los defino genéricamente en la clase base, y supuestamente los sobrescribo en los objetos reales de la base de datos.

El problema es que: cuando el código en la clase principal se ejecuta realmente, usa el antiguo valor padre en lugar del valor del objeto actual.

Aquí está el código para la clase 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; 
    } 
} 

Y aquí está el código para uno de los objetos que sobresalen de la clase base anterior:

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é estoy haciendo mal aquí? ¿Hay alguna otra forma en que pueda lograr el mismo resultado?

Breve adición: Declaro los atributos en el cuerpo de la clase principalmente para que pueda ser visto por la función de autocompletar de NetBeans.

+1

posible duplicado de [herencia de clase en PHP 5.2: anulación de la variable estática en la clase de extensión?] (Http://stackoverflow.com/questions/3017777/class-inheritance-in -php-5-2-overriding-static-variable-in-extension-class) – outis

+0

Esta es una pregunta legítima en php, que tiene una implementación bastante confusa, pero la pregunta realmente podría ser reducida para que sea más genérica y accesible para que otras personas se beneficien. –

Respuesta

41

Está buscando Late Static Binding.

Así que hay que utilizar:

static::$databaseTable 

en lugar de

self::$databaseTable 

Esta función está disponible a partir de PHP 5.3. Simular esto en PHP 5.2 es muy difícil, debido a dos razones: get_called_class está disponible solo desde PHP 5.3, también. Por lo tanto, también se debe simular usando debug_backtrace. El segundo problema es que si tiene la clase llamada, todavía no puede usar $calledClass::$property porque esta es una característica de PHP 5.3 también. Aquí debe usar eval o Reflection. Así que espero que tengas PHP 5.3;)

+0

Desafortunadamente, no puedo actualizar mi versión de PHP. El servidor ejecuta Plesk 9.5, que solo admite hasta 5.2.13; Me temo que actualizarlo manualmente podría romper ciertas aplicaciones. Veré si puedo idear una forma alternativa de hacer la misma tarea. – DfKimera

+0

Muchas gracias por este consejo, ¡tuve exactamente el mismo problema! –

+0

La mejor manera es pasar la clase como primer parámetro a cualquier método que necesite acceder a estas propiedades. De esta forma, puede buscar esa clase directamente para una anulación. Si no se encuentra, puede subir a la escalera principal hasta que encuentre el campo. –

Cuestiones relacionadas