Globale Objekte in einer Klasse als Klassen-Member nutzen

NetBull

Erfahrenes Mitglied
Hi,

ich komm hier nicht weiter. Wohl ein Denkfehler,...

Ich habe ein Programm vor, wo etliche Objekte gemeinsam genutzt werden. Damit die Objekte nicht in jeder Klasse neu übergeben werden müssen, wollte ich die Objekte als global definieren und dann in den entsprechenden Klassen als Referenz weiter verwenden.

Klasse a soll der globalen Klasse lediglich einen String erweitern
Code:
class aClass
	{
		private $globalObj;
		
		function __construct()
		{
			global $gGlobal;
			$this->globalObj = &$gGlobal;
			$this->globalObj->test .= "2";
		}
	}

ebenso die klasse b
Code:
class bClass
	{
		private $globalObj;
		
		function __construct()
		{
			global $gGlobal;
			$this->globalObj = &$gGlobal;
			$this->globalObj->test .= "3";
		}
	}

so sieht dann die globale klasse aus:
Code:
class gGlobalObj
	{
		public $test;
		
		function __construct()
		{			
			$this->test = "1";
		}
	}

und hier nun der Aufruf:
Code:
global $gGlobaObj;
	$gGlobaObj = new gGlobalObj();
	echo "vorher: ".$gGlobaObj->test;
	
	$aobj = new aClass();
	$bobj = new bClass();
	
	echo "nachher: ".$gGlobaObj->test;

An dieser Stelle würde ich erwarten das 123 ausgegeben wird. Stattdessen bekomme ich aber nur 1 ausgegeben. Also keine Referenz sondern eine Kopie des Objektes.

Was mache ich falsch oder geht das in PHP generell nicht und ich muss den umständlichen Weg über den Konstruktor gehen? Wichtig ist das nachher alle Klassen mit dem gleichen Objekt arbeiten und dieses noch beeinflussen können.

cu S00n
deAndro!
 
Die Zahl der Member ist recht umfangreich. Ich möchte die nicht bei jeder Deklaration von Child-Klassen neu übergeben müssen. Dabei war die Methode mit den Globalen Objekten die schönste Lösung. Aber ich kann in der Klasse die Member auf ein globales Objekt zeigen lassen. Mittlerweile übergebe ich die versuchtsweise als array, was mir weniger gefällt....
 
Das Zauberwort heißt Singleton:
PHP:
class GlobalObject
{
  private static $instance = null;
  public         $test     = '';
  
  public static function getInstance ()
  {
    if (self::$instance === null)
    {
      self::$instance = new self;
    }
    
    return self::$instance;
  }
  
  private function __construct ()
  {
    $this->test = '1';
  }
  
  private function __clone ()
  {
  }
}

class A
{
  private $global = null;
  
  public function __construct ()
  {
    $this->global = GlobalObject::getInstance();
    $this->global->test .= '2';
  }
}

class B
{
  private $global = null;
  
  public function __construct ()
  {
    $this->global = GlobalObject::getInstance();
    $this->global->test .= '3';
  }
}

$global = GlobalObject::getInstance();

echo 'before: ' . $global->test; # => '1'
$a = new A;
$b = new B;
echo 'after: ' . $global->test; # => '123';
 
Globale Variablen sind niemals die schönste Lösung. Vielleicht die einfachste, aber auch die fehleranfälligste. Du kannst neben dem Singleton auch eine flache Klasse (in Java nennt man das Pojo, in PHP kenn ich die Bezeichnung nicht - Popo klingt jetzt eher lächerlich) verwenden:

PHP:
class MyGlobals
{
  /**
   * Eine Variable für Zahlen
   * @var int
   */
  private static $_var1;

  /**
   * Eine Variable für Zeichenketten
   * @var string
   */
  private static $_var2;

  /**
   * Variable 1 abholen
   * @return int
   */
  public static function getVar1()
  {
    return self::$var_1;
  }

  /**
   * Variable 2 abholen
   * @return string
   */
  public static function getVar2()
  {
    return self::$var_2;
  }

  /**
   * Variable 1 überschreiben
   * @param int
   */
  public static function setVar1($var)
  {
    self::$_var1 = (int)$var;
  }

  /**
   * Variable 2 überschreiben
   * @param string
   */
  public static function setVar2($var)
  {
    self::$_var2 = (string)$var;
  }
}

Diese Variante hat den enormen Vorzug, das du die volle Kontrolle über die Variablen hast, sei es, was den Inhalt angeht, und auch den Zugriff. Wenn du bspw. eine Variable hast, die nur ein einziges Mal gesetzt werden soll, lässt du den Setter einfach weg - und schützt damit den schreibenden Zugriff.

Was ich sehr bedauere, ist, das es für statische Member keine __getStatic und __setStatic Magic Methods gibt. Allerdings gibt's dafür einen Patch: https://bugs.php.net/bug.php?id=45002

Ich spiele bei den ganzen Unzulänglichkeiten von PHP langsam echt mit dem Gedanken, einen Fork zu machen ;-)
 
Danke das war alles sehr hilfreich, ...

Code:
class RefTest
{	
	public $test;
	private static $cInstance = null;
	public static function getInstance ()
	{	
		if (self::$cInstance === null)
			self::$cInstance = new self;
		return self::$cInstance;
	}
}

$a = RefTest::getInstance();
$a->test = 1;
$b = RefTest::getInstance();
echo $b->test;

gibt mir 1 aus. Cool.

Aber wenn ich nun den Namen einer Klasse dynamisch angebe?
Beispiel:
Code:
public function getContentObject()
{
	if( $this->classExists( $this->cCurrentPage ) )
	{
		return (new $this->cCurrentPage());
	}
	else
	{
		$eErrorPage = new errorPage();
		$eErrorPage->appendError("Could not find the requested page \"$this->cCurrentPage\"");
		return $eErrorPage;
	}	
}

anstatt
Code:
return (new $this->cCurrentPage());
würde ich gerne so was einsetzen
Code:
return ($this->cCurrentPage::getInstance());
leider fehlt mir die Syntax und ich finde keinen Weg das um zu setzen.

Weis hier wer wie das geht?

LG deAndro
 
Nimm zuerst den Klassennamen in eine Variable die nur in der Funktion Gültigkeit hat

PHP:
$cCurrentPage = $this->cCurrentPage;
return $cCurrentPage::getInstance();
 
Nachtrag:

Der Fehler liegt bei Eclipse
Das geht:
Code:
$c = "RefTest2";
	
	$a = $c::getInstance();
	$a->test = 1;
	$b = $c::getInstance();
	echo $b->test;

Aber Eclipse meckert hier wegen :: ...
und ich werd die warnung nicht los?
jemand eine Idee?

Und wenn ich das in mein Projekt einbaue... .
dann sieht das so aus:
Code:
$mClassInstance = $this->cCurrentPage; 
				return $mClassInstance::getInstance();
und funktioniert, abgesehen davon, das eclipse nun keine Dateien mehr schliessen möchte weil es noch "Probleme" geben soll. Die Probleme sind dann genau diese eine Zeile:
Code:
return $mClassInstance::getInstance();

und eigentlich würde ich gerne direkt ohne zusätzliche Variable arbeiten, also so:
Code:
return $this->cCurrentPage::getInstance();
was dazu führt das ich einen fehler bekomme für den ich hebräisch lernen muss.

irgendwelche Ideen?

cu s00n, deAndro
 
Yaslaw: Nimm zuerst den Klassennamen in eine Variable die nur in der Funktion Gültigkeit hat
Die Idee hatte ich soweit auch schon. Aber wie ich im folgenden noch bemerke,... hat ECLIPSE ein Problem mit der Schreibweise und markiert mir "return $cCurrentPage::getInstance();" als Fehler. Und der stört den Interpreter dann erheblich.
 
Zuletzt bearbeitet von einem Moderator:
Mein Eclipse intepretiert es nicht als Fehler...

Aber du kannst es auch über call_user_func() machen. Die aufzurufende Methode ist ein in dem Fall ein Array:
array(className, staticFunctionName);
PHP:
return call_user_func(array($this->cCurrentPage, 'getInstance()'));
 

Neue Beiträge

Zurück