Alternate 1

PHP Typehinting

Tion1392

Lt. Junior Grade
Registriert
Apr. 2010
Beiträge
387
Huhu Liebe Community :)

Ich bin derzeit ein wenig am verzweifeln ;)

Ich programmier derzeit ein etwas größeres Projekt. Als IDE setze ich Phpstorm ein.
Mein Problem ist die Autocompletion. Jedoch nicht die normale, die funktioniert ohne Probleme. Das Problem tritt auf, wenn ich innerhalb einer Klasse eine weitere Klasse instanziere (nicht via extends, sondern indem ich einen Autoloader für Klassen geschrieben habe) und diese Funktion dann aus einer anderen Klasse heraus aufrufe. Um das mal zu verdeutlichen, hier ein kleines Beispiel:

PHP:
file1.php:
class A {
  public function Afunc() {
    //Do some Stuff here
   require_once(file2.php);
   $test = new B();
  }
}

file2.php:
class B {
  public function Bfunc() {
    //Do some magic Stuff here
  }
}

file3.php:
require_once('file2.php');
$test = new A();
$test->Afunc-> //hier sollte jetzt die Autocompletion von der Class B kommen, tut er jedoch nicht

So ;) hoffentlich erkennt ihr, was ich meine.
Wenn ich das bisher im Inet richtig verstanden habe, muss ich hingehen und irgend ein magic Typehinting betreiben, jedoch habe ich dazu nicht gefunden, was ihc da genau type hinten muss.

Könnt ihr mir vll. ein wenig helfen?

Viele Grüße,
Flo
 
Du 'requirest' file2.php und willst A instanziieren? Da sollte dir PHP um die Ohren fliegen.

Ansonsten: wie wäre es, wenn du in den DocTags entsprechend den Rückgabewert der Funtkion angibst und auch was zurückgibst?

PHP:
/**
 *@return A
 */
  public function Afunc() {
    //Do some Stuff here
   require_once('file2.php');
   $test = new B();
   return $test;
  }
 
sry, natürlich muss da File1 requierd werden.

Das Ding ist nicht die Funktionalität. Ich kann die Funktionen ansprechen, sie tun was sie sollen etc.
Mir geht es um die Autocompletion. Die will ums verrecken nicht funktionieren.
 
Hey,

Ja das habe ich schon gemacht, jedoch bringt mich das nur bedingt weiter.

Hier mal die original-Funktion:

PHP:
/**
		 *
		 * @param string $className
		 * @param string $mode
		 *
		 * @return bool
		 */
		public static function makeSysInstance($className, $mode = 'class') {
			if(file_exists('sys/' . $mode . '/' . $mode . '.' . $className . '.php')){
				@include_once('sys/' . $mode . '/' . $mode . '.' . $className . '.php');
				$result = new $className();
			} else {
				print ('bcError 1: Sys-Class "' . $className . '" could not load!');
				self::$error['makeSysInstance'][] = 'bcError 1: Sys-Class "' . $className . '" could not load!';
				$result = FALSE;
			}
			return $result;
		}
Der Gedanke ist ja, dass man damit variabel die Klassen instanzieren kann. Daher funktioniert das an dieser stelle nur so gesehen mit der Klasse A aber mit Klasse xyz würde es nicht gehen.
 
Und woher soll Phpstorm wissen, was du zur Laufzeit generierst? Das wird nicht funktionieren, da PHPstorm keine Information hat, was du da instanziiert hast.

Und warum dokumentierst du einen Bool-Rückgabewert, wenn du da ne Instanz zurückgibst?

Mal davon abgesehen, dass das schlechter Programmierstil ist ;)
 
Der Bool wert ist einer der zwei möglichen Fälle, die eintreten können.

Es ist mir bewusst, dass das ganze zur Laufzeit erst generiert wird. Jedoch habe ich irgendwo in meinem Hinterkopf gemeint, ne Lösung davon mal gesehen zu haben. Ich mein das war via nem Doktype bei der Funktion.

Könnte es alternativ so funktionieren, dass ich bei der deklaration der variable, in der ich das ganze Speicher da einen doctype der klasse angebe?
 
Nein das funktioniert so nicht. Entweder musst du die Methode so deklarieren, dass eine Klasse zurückgegeben wird, dann geht das Typehinting immer (auch wenn false zurückkommt) oder du nimmst eben Boolean und es geht nicht.

Was du vor hast ist sowieso grob fahrlässig. Denn wenn du makeSysInstance('A')->machwas() aufrufst, und die Methode gibt nen false zurück gibt es sofort einen Abbruch die PHP Engine da du versuchst ne Methode auf false aufzurufen: Error!

Eine Methode hat einen Rückgabetyp, einen! In seltenen Ausnahmen kann man das mal anpassen (z.B. mysql_fetch_* bei false wenn keine Daten mehr da sind), aber sicherlich nicht Klasse oder primitiver Datentyp. Und das die Methode direkt Text ausgibt, ist genauso falsch...
Du solltest mal einen Blick auf Exceptions werden, den das löst a) dein Problem automatisch und b) ist es der korrekte Weg für dein Beispiel.
 
Wenn die Klassen die jeweils gleiche Methode implementieren, könntest du es mit einem Interface probieren. Dann würde PHPStorm das korrekt auflösen.

Eine Alternative wäre:
@return A|B|C|D|E

Aber auch das macht nicht wirklich Sinn, zumindest wenn die Klassen nicht alle die gleichen Methoden implementieren.

In dem Zusammenhang haut vermutlich deine Programmarchitektur nicht so hin, wie du es brauchst.

Versuch es mal mit einem ServiceLocator (so macht das z.B. ZF2) - der könnte dir da ggf. weiterhelfen und das Problem sauberer lösen. Aber einfach mal raten, ob's die Klasse gibt und wenn es sie gibt, sie zu instanzieren, ist nicht wirklich sauber. Überdenk das lieber nochmal.
 
Der ServiceLocator ausm ZF3 wird ihm da aber auch nicht helfen oder? Wenn ich mich recht entsinne ist das ja auch eine generische Methode, die bei einem übergebenen String irgendetwas zurückgibt -> somit hat die IDE wieder keine Ahnung was man da gerade nutzt.
 
Die letzte Aussage bezog sich im allgemeinen auf die Architektur seines Programmes :)

Ansonsten: für jede Klasse, die du dir holen willst, einfach einen Getter im entsprechenden ServiceLocator implementieren.
Wenn er unbedingt die Autocompletion braucht, muss er es wohl so machen. Alternativ kannst du auch im DocBlock über der Methode den Typ einer Variable bestimmen.

Schreib z.B. über die Methode, die das hier macht:
PHP:
/**
 * @var A
 */
protected $_foo;

public function bla() {
    $this->_foo = Bar::makeSysInstance('A');
}
 
Zurück
Oben