Re: Klasse auf Basisklasse oder Interface überprüfen (Bestimmt wieder Trivial ^^)

Christoph Herrmann schrieb:
> Habe mit Reflektion noch nie gearbeitet. Instanziert werden die Objekte
> derzeit über "$object = $classname();". Wobei die Prüfung mit Reflection
> ähnlich aussehen würde. Da bekomme ich auch ein Array mit den
> Basisklassen bzw. Interfaces.

Falls es jemand benötigt:

/**
* Gibt ein Objekt der uebergebenen Klasse zurueck
*
* Die Methode ist fuer den sicheren Umgang mit der Instanzierung einer
* Klasse zustaendig, von welcher nur der Klassenname bekannt ist. Dabei
* kann der Name einer Basisklasse oder Interface uebergeben werden, auf
* welche die zu instanzierende Klasse ueberprueft wird sowie Parameter.
* Ist die Klasse nicht abgeleitet, implementiert nicht das Interface oder
* ist nicht instanzierbar wird eine "SystemcoreException" geworfen
*
* [at] author Christoph Herrmann
* [at] version 18.12.2007
* [at] since 18.12.2007
*
* [at] param string $classname Der Name, der zu instanzierenden Klasse
* [at] param string $instanceof Der Name des Interface oder der Basisklasse
* [at] param mixed $argument Einzelner Parameter fuer den Konstruktor
* [at] return Object Das instanzierte Objekt der gewuenschten Klasse
*/
public function getObject($classname, $instanceof = null, $argument = null)
{
$reflection = new ReflectionClass($classname);

/*
* Es wird ueberprueft, ob die Klasse das Interface implementiert oder
* von der Basisklasse erbt, wenn der Parameter uebergeben wurde
*/
if(isset($instanceof))
{
if(in_array($instanceof, $reflection->getInterfaces()) == false
&&
$reflection->isSubclassOf($instanceof) == false)
{
/*
* Die gewuenschte Klasse implementiert nicht das geforderte
* Interface und ist nicht von der Basisklasse abgeleitet
*/
throw new SystemcoreException(0, array('classname' => $classname,
'instanceof' =>
$instanceof));
}
}

/*
* Es wird ueberprueft, ob die Klasse instanziert werden kann, sprich
* nicht abstrakt ist oder einen geschuetzten Konstruktor besitzt
*/
if($reflection->isInstantiable() == false)
{
/*
* Die Klasse, welche instanziert werden soll, ist abstrakt oder
* besitzt einen geschuetzten Konstruktor
*/
throw new SystemcoreException(0, array('classname' => $classname,
'instanceof' => $instanceof));
}

return $reflection->newInstance($argument);
}

Wer die Methode verwenden will kann dies gerne tun, es muss nur das
Werfen der Exceptions angepasst werden. Habs grob getestet und sollte
von daher auch so funktionieren.

--
Mit freundlichen Grüßen,
Christoph Herrmann

http://dragonprojects.de/
Christoph Herrmann [ Di, 18 Dezember 2007 18:46 ] [ ID #1889490 ]

Re: Klasse auf Basisklasse oder Interface überprüfen (Bestimmt wieder Trivial ^^)

Christoph Herrmann schrieb:
> if(in_array($instanceof, $reflection->getInterfaces()) == false
> &&
> $reflection->isSubclassOf($instanceof) == false)

Kann es sein, dass die Methode "isSubclassOf()" auch True ergibt, wenn
die Klasse ein Interface implement? Daher die Abfrage obendrüber auf das
Interface unnötig ist?

--
Mit freundlichen Grüßen,
Christoph Herrmann

http://dragonprojects.de/
Christoph Herrmann [ Di, 18 Dezember 2007 19:40 ] [ ID #1889495 ]

Re: Klasse auf Basisklasse oder Interface überprüfen (Bestimmt wieder Trivial ^^)

Christoph Herrmann wrote:
> Christoph Herrmann schrieb:
>> if(in_array($instanceof, $reflection->getInterfaces()) == false
>> &&
>> $reflection->isSubclassOf($instanceof) == false)

Wenn es im ein Interface geht sollte man halt auch die Passende Funktion
nehmen:
public bool implementsInterface(string $name)

Und die prüfung == false ist absolut sinnfrei. in_array() liefert genau
wie isSubclassOf() einen bolleanschen wert zurück. Also ist da
!in_array() wesentlich sauberer und beschränkt sich aus wesentliche.

> Kann es sein, dass die Methode "isSubclassOf()" auch True ergibt, wenn
> die Klasse ein Interface implement?

Wenn Du gegen das Interface prüfst klar. Das wurde auch in dem anderen
Beitrag schon angesprochen.

Wenn Du isSubClassOf() verwendest solltest Du ja eh ein Objekt vom Type
ReflectionClass übergeben. Da ist es doch vorher ein leichtes mit
isInterface() zu prüfen ob es sich dabei um ein Interface handelt.

Ich bin zu faul mir Deinen ganzen Code anzusehen...

MfG, Ulf

--
_,
_(_p> Ulf [Kado] Kadner
\<_)
^^
Ulf Kadner [ Di, 18 Dezember 2007 21:22 ] [ ID #1890710 ]

Re: Klasse auf Basisklasse oder Interface überprüfen (Bestimmt wieder Trivial ^^)

Ulf Kadner schrieb:
> Und die prüfung == false ist absolut sinnfrei. in_array() liefert genau
> wie isSubclassOf() einen bolleanschen wert zurück. Also ist da
> !in_array() wesentlich sauberer und beschränkt sich aus wesentliche.

I know. Allerdings übersieht man ein "!" sehr leicht und ich mache es
gern eindeutig durch " == false". Wäre nicht das erste mal, dass ich
sowas übersehe und dadurch Probleme habe. :)

> Wenn Du gegen das Interface prüfst klar. Das wurde auch in dem anderen
> Beitrag schon angesprochen.
>
> Wenn Du isSubClassOf() verwendest solltest Du ja eh ein Objekt vom Type
> ReflectionClass übergeben. Da ist es doch vorher ein leichtes mit
> isInterface() zu prüfen ob es sich dabei um ein Interface handelt.

Habe es gerade schnell getestet mit:

interface A {}
class B implements A {}
$ref = new ReflectionClass('B');
print $ref->isSubclassOf('A');

Daher muss man nicht zusätzlich auf Interface abprüfen.

> Ich bin zu faul mir Deinen ganzen Code anzusehen...

Habe ja nicht gesagt, dass es jemand kontrollieren soll. ;) Dachte nur
wenn jemand das gleiche Problem hat kann er die Methode gerne nehmen. So
als Dank für die Hilfe. :)

--
Mit freundlichen Grüßen,
Christoph Herrmann

http://dragonprojects.de/
Christoph Herrmann [ Di, 18 Dezember 2007 22:06 ] [ ID #1890716 ]
PHP » de.comp.lang.php.misc » Re: Klasse auf Basisklasse oder Interface überprüfen (Bestimmt wieder Trivial ^^)

Vorheriges Thema: Problem gelöst(was: PHP-Seiten ohne Inhalt:-()
Nächstes Thema: Re: IP von Zugreifern loggen! Wie?