Carsten_R: Superglobale Variablen selber definieren?

Hallo,

ich stehe vor folgendem Problem:
Ich habe ein objektorientiertes Programm in PHP was auf dem Templatesystem smarty beruht. Jetzt möchte ich aber in jeder Klasse und jeder Funktion ohne "global" auf das smarty-Objekt zugreifen können.
Desweiteren brauche ich eine neue superglobale Variable die $_SETTINGS heißt worin dann meine Programmeinstellungen gespeichert sein sollen. Die will ich auch nicht immer mit global einbinden müssen.

Gibt es daher die Möglichkeit superglobale Variablen wie $_GET oder $_SESSION selber zu erstellen? Wenn nein, wie kann ich das anders realisieren?

Danke für Antwort
Carsten

  1. Hi Carsten_R,

    Gibt es daher die Möglichkeit superglobale Variablen wie $_GET oder $_SESSION selber zu erstellen? Wenn nein, wie kann ich das anders realisieren?

    So etwas geht meines Wissens nicht, halte ich auch nicht für besonders sinnvoll. In so einem Fall verwendet man normalerweise eine Singleton-Klasse, diese könnte beim erstmaligen Initialisieren beispielsweise die Konfigurationen aus einer INI-Datei einlesen und dann per Eigenschafts-Überladung bequem zur Verfügung stellen.

    Ach ja, geht in der Form natürlich nur in PHP5, aber dass man PHP4 nicht mehr verwenden sollte, hatten wir ja neulich schon mal.

    Viele Grüße,
      ~ Dennis.

    1. Hi,

      So etwas geht meines Wissens nicht, halte ich auch nicht für besonders sinnvoll. In so einem Fall verwendet man normalerweise eine Singleton-Klasse, diese könnte beim erstmaligen Initialisieren beispielsweise die Konfigurationen aus einer INI-Datei einlesen und dann per Eigenschafts-Überladung bequem zur Verfügung stellen.

      Gibt es da denn keinen einfacheren Weg? Ich verstehe das mit dem überladen nämlich noch nicht so ganz...  ich brauche nen Weg wie ich einfach in einer Unterklasse statt $GLOBALS['smarty']->assign() $smarty->assign() schreiben kann am besten ohne in den einzelnen Klassen noch einen Zusatz zu schreiben. Diese Klassen existieren nämlich eigentlich schon.

      Carsten

      1. Moin!

        Gibt es da denn keinen einfacheren Weg? Ich verstehe das mit dem überladen nämlich noch nicht so ganz...  ich brauche nen Weg wie ich einfach in einer Unterklasse statt $GLOBALS['smarty']->assign() $smarty->assign() schreiben kann am besten ohne in den einzelnen Klassen noch einen Zusatz zu schreiben. Diese Klassen existieren nämlich eigentlich schon.

        Die übliche Vorgehensweise wäre dann, dem Konstruktor der Unterklasse eine Referenz auf die benötigten, bereits existierenden Objekte zu übergeben, die dieser lokal speichert und dadurch den Methoden verfügbar macht.

        Globale Variablen sind böse! Extrem BÖSE! Insbesondere weil du dadurch deine Klassen nicht mehr vernünftig automatisiert testen lassen kannst (z.B. mit SimpleTest et al).

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
      2. Hello,

        Gibt es da denn keinen einfacheren Weg?

        Wie wäre es denn mit einer Funktion?

        Ob Du nun schreibst $smarty->assign() oder smarty('assign', ...), das ist doch kaum ein Unterschied. :-)

        Harzliche Grüße vom Berg
        http://bergpost.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        1. Hi Tom,

          Wie wäre es denn mit einer Funktion?

          Und woher soll diese Funktion dann wiederum die Instanz der Klasse kriegen?

          Du siehst, eine Funktion ist nur eine Verlagerung des Problems in einen anderen Bereich des Quellcodes. Weil in einer Funktion müsstest du dann auch wieder $GLOBALS benutzen um Zugriff auf das Objekt zu erhalten, oder das von mir und Christian propagierte Singleton-Muster verwenden.

          Egal wofür du dich entscheidest (hoffentlich Singleton), du kannst dies auch direkt an der Originalstelle tuen ohne es in eine Funktion zu verlagern. [1]

          Viele Grüße,
            ~ Dennis.

          [1] Mir ist bewusst, dass eine Funktion weniger Tipparbeit gegenüber $GLOBALS bedeutet und die Wartbarkeit erhöht, falls jemand die globale Variable umbenennen will. Aber diese Argumentation hebt sich bei der Nutzung einer Singleton-Klasse auf.

          1. Hello,

            [1] Mir ist bewusst, dass eine Funktion weniger Tipparbeit gegenüber $GLOBALS bedeutet und die Wartbarkeit erhöht, falls jemand die globale Variable umbenennen will. Aber diese Argumentation hebt sich bei der Nutzung einer Singleton-Klasse auf.

            Da mag ich Dir auch überhaupt nicht widersprechen.
            Aber Du weißt ja, das meine PHP-Ideen teilweise noch aus der Zeit von PHP 2.x stammen.
            Sowas setzt sich einfach fest *gg*

            Harzliche Grüße vom Berg
            http://bergpost.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
            Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

            1. Hi,

              danke an euch, ihr seid wirklich super... werde das dann jetzt mit einer singleton-klasse machen =)

              bis denne
              Carsten

      3. Hi Carsten_R,

        Gibt es da denn keinen einfacheren Weg? Ich verstehe das mit dem überladen nämlich noch nicht so ganz...

        Keiner zwingt dich dazu, die Überladungen zu nutzen, du kannst auch herkömmliche Get/Set-Methoden nehmen ;-)

        define('CARSTEN_CONFIG_FILE', '/pfad/zur/config.ini');  
          
        class Carten_Config {  
          private static $instance = NULL;  
          private $config = array();  
          
          private function __construct() {  
            // hier musst du die Konfigurationen einlesen  
            // z.B. so:  
            $this->config = parse_ini_file(CARSTEN_CONFIG_FILE);  
          }  
          
          public static function getInstance() {  
            if (self::$instance === NULL) {  
              self::$instance = new Singleton;  
            }  
            return self::$instance;  
          }  
          
          private function __clone() {}  
          
          public function get($value) {  
            if(!isset($this->config[$value]))  
              throw new Exception('Config entry ' . $value . ' not found.');  
            return $this->config[$value];  
          }  
        }  
          
        // Aufruf wie folgt:  
        $config = Carsten_Config::getInstance();  
        echo $config->get('ini_eintrag');  
        // oder:  
        echo Carsten_Config::getInstance()->get('ini_eintrag');
        

        Das dürfte als funktionierendes Beispiel schon reichen. Wenn man es ganz sauber objektorientiert programmieren will, sollte man sich vielleicht noch was anderes überlegen, anstatt der Konstante mit dem Pfad zur INI-Datei.

        Wenn du dann das jetzt hast, kannst du dir überlegen, ob du die Eigenschaften überladen willst - ist nicht schwer, du musst für deinen Fall eigentlich nur eine Methode hinzufügen, ganz ähnlich wie es im PHP-Manual steht. Letzendlich hast du dann direkten Zugriff auf die Einstellungen der INI über

        $config = Carsten_Config::getInstance();  
        echo $config->ini_eintrag();
        

        Spart etwas Tiparbeit ;-)

        ich brauche nen Weg wie ich einfach in einer Unterklasse statt $GLOBALS['smarty']->assign() $smarty->assign() schreiben kann am besten ohne in den einzelnen Klassen noch einen Zusatz zu schreiben. Diese Klassen existieren nämlich eigentlich schon.

        Sven hat dir ja schon erklärt, wie ein geeignetes Vorgehen hierfür aussieht. Du übergibst entweder dem Konstruktor der Klasse eine Referenz auf deine Config-Klasse, oder die Klasse holt sich im Konstruktor (oder an den Stellen wo du es benötigst) selber eine Referenz auf deine Config-Klasse, was dank Singleton ja problemlos möglich ist.

        Obiges Beispiel war jetzt für eine Klasse, welche eine INI-Datei einliest, weil du im Ausgangsposting von $SETTINGS sprachst, welches du gerne hättest ;-)

        Natürlich kannst du auch eine Smarty-Singleton-Klasse erstellen, du musst nur bedenken, dass du dann immmer dasselbe Smarty-Objekt hast und wenn du bereits zugewiesene Variablen löschen willst, dies explizit machen musst.

        Ich habe so etwas ähnlich schon mal in einem Projekt verwendet, hier ein Auszug aus meinem damaligen Quellcode, angepasst auf dich:

        define('CARSTEN_TEMPLATE_PATH', '/pfad/zu/smarty/templates');  
        define('CARSTEN_TMP_PATH', '/pfad/zum/tmp/order/deines/projekts');  
        define('CARSTEN_CONFIG_PATH', '/pfad/zum/config/order');  
          
        class Carsten_Smarty extends Smarty {  
          
          static private $instance = null;  
          
          static public function getInstance() {  
            if(self::$instance == NULL) {  
             $c = __CLASS__;  
              self::$instance = new $c;  
            }  
            return self::$instance;  
          }  
          
          private function __construct() {  
            $this->template_dir = CARSTEN_TEMPLATE_PATH;  
            $this->compile_dir  = CARSTEN_TMP_PATH . 'smarty_c';  
            $this->cache_dir    = CARSTEN_TMP_PATH . 'smarty';  
            $this->config_dir   = CARSTEN_CONFIG_PATH . 'smarty';  
          }  
        }
        

        Hiermit kannst du dir deine Smarty-Instanz jederzeit über

        $smarty = Carsten_Smarty::getInstance();

        holen und damit arbeiten. In dem Konstruktor obiger Klasse werden die Pfade aus (globalen) Konstanten gelesen. Das ist im Sinne von OOP natürlich nicht unbedingt so schön, eine Alternative wäre die Verwendung unserer obigen Config-Klasse:

        private function __construct() {  
          $config = Carsten_Config::getInstance();  
          $this->template_dir = $config->get('smarty_template_dir');  
          $this->compile_dir = $config->get('smarty_compile_dir');  
          $this->cache_dir = $config->get('smarty_cache_dir');  
          $this->config_dir = $config->get('smarty_config_dir');  
        }
        

        Dazu bastelst du dir dann einfach noch eine passende INI-Datei :-)

        Viele Grüße,
          ~ Dennis.

        --
        Mein SelfCode: [link:http://www.peter.in-berlin.de/projekte/selfcode/?code=ie%3A%7B+fl%3A%28+br%3A%3E+va%3A%29+ls%3A%5B+fo%3A%29+rl%3A%28+n4%3A%23+ss%3A%29+de%3A%5D+js%3A%7C+ch%3A%7B+sh%3A%7C+mo%3A%7D+zu%3A%7C@title=ie:{ fl:( br:> va:) ls:[ fo:) rl:( n4:# ss:) de:] js:| ch:{ sh:| mo:} zu:|
  2. Hallo Carsten,

    Gibt es daher die Möglichkeit superglobale Variablen wie $_GET oder $_SESSION selber zu erstellen? Wenn nein, wie kann ich das anders realisieren?

    Die Runkit-C-Erweiterung bietet sowas an - Du musst allerdings VOR (!) dem Scriptstart einige ini-Einstellungen korrekt setzen (entweder in der php.ini oder in der Serverkonfiguration / .htaccess falls PHP als Apache-Modul geladen ist). Und Runkit muss natürlich installiert sein.

    Ansonsten: Nein, geht nicht.

    Ich würde Dennis Singleton-Vorschlag nutzen wollen.

    Viele Grüße,
    Christian

  3. Hellihello,

    was ist denn mit

      
    class My_Global {  
       public static $my_var;  
       public static function initialize() {  
         self::$my_var="Globaler Inhalt";  
       }  
    }  
      
    My_Global::initialize();  
    echo My_Global::$my_var;  
    //ungetestet  
    
    

    Das Problem mit globalen Vars wie Sven schrub ist damit nicht aus der Welt.

    Dank und Gruß,

    frankx