Newsgroup: it.comp.www.php
Titolo: funzione statica abstract

Ciao a tutti.
Ho un piccolo problema con l'implementazione di una classe. La
situazione è questa. Salvo su db i dati di diverse classi le quali
hanno tutte tre campi identici (xx, yy, zz).
Ogni classe deriva da una classe base, DBObject, che ha appunto tre
variabili xx, yy, zz.
Una cosa del tipo
abstract class DBObject {
...protected $xx="";
...protected $yy="";
...protected $zz="";
...protected abstract  static function getTableName();
...protected static getAll() {
......$db = new DB();
......$query= "select * from " . self::getTableName();
......$results = $db->getQuery( $query );
......return $results;
...}
}
class XX extends DBObject {
...protected static function getTableName() {
......return "nomeTabella";
...}
}
Il metodo statico getAll() in DBObject non funziona perché non riesce
a richiamare self::getTableName. Come posso fare?
Mattia

mi dai un esempio del codice che utilizzi per usarlo ?
per capire se istanzi e cosa istanzi...
così te lo correggo.

 così te lo correggo.
Purtroppo ora non sono più in ufficio, quindi non posso darti un
esempio del mio codice. Ti riporto un codice molto sintetizzato che da
lo stesso problema.
<?php //php vers. 5.1
abstract class Padre {
   protected abstract static function getNome();
   public static function getILMioNome() {
      $xx = self::getNome();
      echo $xx;
   }
}
class Figlio extends Padre {
   protected static function getNome() {
       return "Mattia";
   }
}
$figlio = new Figlio();
$nome = $figlio->getILMioNome();
?>
Vorrei che stampasse a video "Mattia", però a me da un errore per cui
non posso richiamare la funzione getNome() all'interno di
getILMioNome(). Il messaggio esatto è:
Fatal error: Cannot call abstract method Padre::getNome() in
/var/www/ristorante/prova.php on line 1
Magari provo a spiegare meglio di cosa ho bisogno, così che tu o altri
possiate darmi anche soluzioni alternative. Nel mio db ho diverse
tabelle tutte con tre campi uguali. Ad ogni tabella dovrà essere
associata una classe che ne mappi completamente i campi, in modo da
poter operare sugli oggetti anziché direttamente sul db. La classe
DBObject si preoccupa di ricavare dal db i valori dei tre campi comuni
a tutti gli oggetti e di valorizzare le variabili correttamente. Mi
serve inoltre un metodo statico, contenuto in DBObject, che mi
restituisca un array di oggetti corrispondenti a tutti i record di una
determinata tabella.
Non ci sarebbe alcun problema se non fosse che non posso sapere
all'interno di DBObject come si chiama la tabella da cui devo attingere
i dati. Il nome della tabella lo conosco solo all'interno della classe
oggetto che eredita da DBObject.
Il problema è appunto riuscire ad ottenere nella classe DBObject
questo valore.
Grazie mille.
Mattia

 determinata tabella.
usare propel no ?
propel.phpdb.org

ho fatot un po' di taglia e incolla ma così dovrebbe andare,
sono a casa e non gli sono stato dietro... provalo
<?php //php vers. 5.1
abstract class Padre {
   public function getILMioNome() {
      echo $this->getNome();
   }
   protected abstract function getNome();
}
class AccessoSingle {
   // Hold an instance of the class
   private static $instances;
   // A private constructor; prevents direct creation of object
   private function __construct()
   {
       echo 'I am constructed';
   }
   // The singleton method
   public static function singleton($classe)
   {
       if (!isset(self::$instances[$classe])) {
          self::$instances[$classe] = new $classe;
       }
       return self::$instances[$classe];
   }
   // Prevent users to clone the instance
   public function __clone()
   {
       trigger_error('Clone is not allowed.', E_USER_ERROR);
   }
}
class Figlio extends Padre {
   protected function getNome() {
       return "Mattia";
   }
}
echo AccessoSingle::singleton("Figlio")->getIlMioNome();
?>

 echo AccessoSingle::singleton("Figlio")->getIlMioNome();
Uhm... questo non risolvere il mio problema... Il metodo da te proposto
crea un'istanza della classe Figlio, occupandosi di impedirne
l'istanziamento multiplo. Ma non ho bisogno di mantenere un solo
oggetto Figlio, anzi ne devo creare molti. Inoltre ho bisogno di
accedere alla funzione getAll (nell'esempio era semplificata come
getILMioNome), senza creare un'istanza di alcun oggetto Figlio.
L'intenzione era quello di ottenere un array di oggetti Figlio (il
contenuto della relativa tabella nel db) richiamando Figlio.getAll().
La funzione getAll() è definita nella classe Padre, all'interno della
quale richiama il metodo getTableName() che, nella classe Padre, è
astratto. Queste funzioni devono essere static per permettermi di
richiamarle senza alcuna istanza.
Per propel ci darò un'occhiata, non ne avevo sentito parlare. Sto
imparando php da circa una settimana, quindi ancora non conosco molto
gli strumenti del mestiere ;)
Grazie mille.
Mattia

 oggetto Figlio, anzi ne devo creare molti. Inoltre ho bisogno di ...
Siamo vittime della mala gestione degli static di php, purtroppo saremo
messi cosi fino a quando non uscira la versione 6 poi vedremo.
non ti volevo far fare una porcata cosi' ma non mi lasci scelta, ti
metto un workaround...
<?php
abstract class Padre {
   public static function getILMioNome($class = null) {
      $temp = new $class();
      return $temp->getNome();
   }
   protected abstract function getNome();
}
class Figlio extends Padre {
  public static function getIlMioNome($class = null) {
    return parent::getIlMioNome(__CLASS__);
  }
  protected function getNome() {
       return "Mattia";
  }
}
echo Figlio::getIlMioNome();
?>
il problema e' che istanziamo comunque la classe figlio, se invece non
vuoi proprio che venga istanziata ci si deveragionare ancora un
pochetto...

 pochetto...
Grazie mille dell'aiuto. Mi sa che quello che volevo fare ancora non è
possibile a causa delle limitazioni di php. Volevo evitare di
istanziare un oggetto per mantenere una certa pulizia e purezza nel
codice, ma i rimedi sembrano costringermi a scrivere un codice ancora
peggiore. A questo punto tanto vale togliere lo static ed istanziare un
oggetto vuoto.
Senza fare tanti stravolgimenti potrei fare così.... In padre metto la
funzione getAll() come static abstract, ed un'altra static getAll(
$nomeTabella ). Risulterebbe una cosa del genere:
<?php
abstract class Padre {
	public $zz = 0;
	public $xx = 0;
	public $yy = 0;
  protected static function getAllFromTable( $nomeTabella ){
     // codice per ottenere il contenuto della tabella con nome
     //$nomeTabella e valorizzare i tre campi uguali.
     echo "Contenuto tabella $nomeTabella<br>";
  }
  public abstract static function getAll();
  protected abstract static function getTableName();
}
class Figlio extends Padre {
  protected static function getTableName() {
     return "nomeTabella";
  }
  public static function getAll() {
     $result = parent::getAllFromTable( self::getTableName() );
     return $result;
  }
}
   Figlio::getAll();
?>
Funziona. Risolve il problema dell'istanziamento di un oggetto per
richiamare la funzione Figlio::getAll() ed è abbastanza pulito, anche
se richiede un workaround nell'oggetto Figlio, uguale per tutte classi
che estendono Padre. Il che non è il massimo, ma non mi viene in mento
nulla di meglio ora. Quanto meno quando il problema in php sarà
risolto mi basterà poco per fare pulizia.
Grazie mille ancora.
Mattia

 risolto mi basterà poco per fare pulizia.
hai trovato un ottima soluzione.