PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Autoload für Klassen


urvater
07.02.2009, 22:58:09
Ich beschäftige mich nun seit ein paar Wochen mit Klassen. Dabei kommt man um eine Funktion wie ein Autoload für Klassen ja eigentlich nicht herum.
Gefunden habe ich folgendes Beispiel.
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}

$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Laut Beschreibung versucht es die jeweilige Klasse anhand des Namens zu laden.
MyClass1 müsste demnach in der Datei 'MyClass1.php' sein.
Ruft sich diese Funktion nun durch $obj = new MyClass1(); selbst auf oder fehlt mir da noch etwas?

agent47
07.02.2009, 23:08:50
wen der interpreter beim ausführe eine solchen scriptes auch eine klasse trifft die noch nicht bekannt ist, wird automatisch die autoload funktion aufgerufen und versucht die klasse nach zu laden, gelingt das wird das script ganz normal weiter verarbeitet, scheitert der versuch wird ein fehler erzeugt

cortex
07.02.2009, 23:09:11
Ruft sich diese Funktion nun durch $obj = new MyClass1(); selbst auf oder fehlt mir da noch etwas?

da fehlt nichts - durch new class wird die datei class.php geladen.

funktioniert's denn nicht?

cx

DokuLeseHemmung
08.02.2009, 00:10:38
Von __autoload halte ich nix!
Das führt zu Sorgen, wenn man weitere "Pakete" einbinden möchte.

http://www.selfphp.de/forum/showpost.php?p=122435&postcount=2

cortex
08.02.2009, 11:35:16
Von __autoload halte ich nix!

für "überschaubare" projekte völlig ausreichend...

cx

urvater
08.02.2009, 12:17:25
Danke erst einmal für die Antworten. Ich hatte es selbst noch nicht getestet ob es funktioniert, da meine Dateien zu den Klassen noch keiner gescheiten Namensgebung folgen.
Zur Zeit sind die Klassen, 4-5 Stück, noch recht überschaubar. Allerdings will ich das eine Projekt noch stark ausbauen. Es könnte also am Ende recht groß werden.

Meine eigentlich Frage ob diese automatisch aufgerufen wird ist ja beantwortet.

Den Hinweis von Docu werd ich mir aber trotzdem rein ziehen. Vielleicht kann ich so ja vermeiden später alles wieder umstellen zu müssen.

Danke allen für die Antworten.

cortex
08.02.2009, 12:25:40
mit "überschaubar" habe ich auch die struktur der anwendung gemeint. wenn ich bspw. mit einem frontcontroller arbeite, ist die logik der anwendung überschaubarer, als wenn ich mit autarken klassen (im sinne ihrer ansprechbarkeit von aussen) jongliere.

cx

urvater
08.02.2009, 13:16:27
Dann werd ich mir den Hinweis von Docu wohl noch mehr zu Gemüte ziehen müssen. Das Projekt wird hier ja von mir selbst geschrieben. Die eigentliche Bearbeitung erfolg überwiegend über meinen gewählten Editor selbst.
Frontend stehen nur die Möglichkeiten den DB Inhalt zu füllen, korrigieren oder ggf. zu löschen. Für mich ist es also entscheidend, daß ich beim Schreiben der Scripte nicht den Include vergessen kann oder durch Schreibfehler etc. auf die falsche Datei verweise.
Damit man nicht einen Include vergißt macht es ja auch keinen Sinn immer alle Klassen zu includieren. Ist ja nicht das Gelbe vom Ei, wenn man sie nicht benötigt.

Mein Hauptproblem liegt hierbei eigentlich bei dem Tool, was ich für meine Arbeit schreibe. Es ist eine Mischung aus einer Linksammlung, Abfragesystem und FAQ zu immer wieder kehrenden Problemen, die ich für den Support benötige.
Die Linksammlung ist eine Ansammlung auf "fremde" Abfragesysteme.
Die Abfragen auf meiner Seite beziehen sich auf statische und dynamische Listen, eigene Sammlungen von Meldungen, die ich als XML holen muß, und noch ein paar anderen Daten.
Die FAQ sind immer wieder kehrende Fehler, die auf Fehlern bei der Eingabe der User beruhen und alle paar Wochen gemacht werden. Somit hab ich immer die passende Antwort mit allen dafür benötigten Informationen.
Irgendwie gehört je nach Problem alles zusammen oder zumindest ein Teil der Daten wird auch an anderer Stelle benötigt.

Ich muß halt beim Erstellen dafür sorgen, was meine Kollegen versuchen könnten um an die gewünschte Information zu kommen.

Ich werd wohl noch viel lesen und testen müssen.

Zend, Ajax oder ein CMS kann ich nicht nutzen, da meistens die PHP und MySql Versionen zu veraltet sind und mir zu viele Rechte für die Installation fehlen. Die finanzielle bzw. rechtliche Seite mal aussen vor gelassen.

DokuLeseHemmung
08.02.2009, 13:31:36
mit "überschaubar" habe ich auch die struktur der anwendung gemeint. wenn ich bspw. mit einem frontcontroller arbeite, ist die logik der anwendung überschaubarer, als wenn ich mit autarken klassen (im sinne ihrer ansprechbarkeit von aussen) jongliere.

cx
Kannst du mir das mal erklären?
Tolle Worte, aber der Kern der Aussage erschließt sich mir nicht.


Einfaches Beispiel: Ich möchte fremder Leute Klassen nutzen!
Und das geht z.B. so:

require_once('path-to-doctrine/lib/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));

require_once('path-to-sensei/lib/Sensei.php');
spl_autoload_register(array('Sensei', 'autoload'));

Und schon geht nix mehr mit deiner __autoload()..

cortex
08.02.2009, 14:39:21
Tolle Worte[...]

ruhig brauner... du musst nicht gleich rumäppeln.

Einfaches Beispiel[...]

sorry, verstehe nicht, worauf du hinaus willst. meinst du das problem unterschiedlicher pfade ?

wenn ja: auch das lässt sich bewerkstelligen, wenn auch mir einigem aufwand: bsp. über eine auswertung der klassennamen und der zuweisung entsprechender pfadangaben.

darauf habe ich allerdings nicht abgezielt - ich sprach von einer "überschaubaren" app. wenn ich tausende fremd-module in höchst unterschiedlichen teilen der app benutze, empfinde ich persönlich das nicht mehr als "überschaubar". dass du das u.u. anders siehst, bleibt davon unberührt.

cx

DokuLeseHemmung
08.02.2009, 14:57:14
meinst du das problem unterschiedlicher pfade ?
Nein, ich sage, dass sich __autoload() und SPL autoload gegenseitig ausschließen.
Es darf nur eine __autoload() geben, dann aber kein SPL Autoload.
Es darf aber viele SPL Autoload nebeneinander geben, dann aber keine __autoload().

Mit etwas Weitsicht entscheidet man sich doch für den universelleren Weg, oder?
Und dass bisschen zusätzliche Komplezität macht den Braten nicht fett.

Ja, ganz subjektiv:
Der Gewinn an portabilität ist riesig und wiegt den Aufwand (er ist ja auch nur 1 mal zu machen) dick und fett auf!
Das bessere ist der Feind des guten.

cortex
08.02.2009, 15:11:22
Es darf nur eine __autoload() geben

hm, das war mir nicht bewusst - hatte die situation auch noch nicht.

Mit etwas Weitsicht entscheidet man sich doch für den universelleren Weg, oder?

stimmt.

Und dass bisschen zusätzliche Komplezität macht den Braten nicht fett.

das würde ich zumindest annehmen. die geschichte mit dem kleinvieh habe ich trotzdem immer im hinterkopf.

Das bessere ist der Feind des guten

amen, bruder .-

cx

DokuLeseHemmung
08.02.2009, 15:32:23
die geschichte mit dem kleinvieh habe ich trotzdem immer im hinterkopf.
Richtig so.
Man darf sich davon aber nicht kirre machen lassen. Portabilität und Sicherheit sind eben "teuer".
Kann einen ja auch nix davon abhalten, beide Wege bereit zu stellen und sich dann in der realen Applikation einen davon auszusuchen.



// selbst so würde es gehen:
function __autoload($class)
{
LibAutoload::autoload($class);
}

DokuLeseHemmung
08.02.2009, 17:17:25
Nachtrag
Für PHP5.3 und PHP6 empfehle ich diesen Autoloader:
spl_autoload_register
(
function ($name)
{
$dirname = dirname(__FILE__);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR,$name).'.php';
$file = $dirname.DIRECTORY_SEPARATOR.$fileName;
if (is_readable($file)) require_once $file;
}
);

stfwi
08.02.2009, 23:44:43
Hi,

kurzer Erfahrungsbericht als Bestätigung: Autoload
ist bei mir vollkommen rausgeflogen - ich arbeite
ausschließlich mit Klassen und habe mir genau den
oben beschriebenen Ärger direkt zu Beginn eingefangen -
falscher Text --> falsche Klasse, fatal error in __construct(),
weil die Argumente nicht passen.
Ich denke mittlerweile, dass gerade dann, wenn Objekte
dynamisch instantiiert werden, muss man vorher einen
Blick auf die Klasse und die Vererbungsliste / Interface-
Liste der Klasse werfen, d.h. das require_once() bzw. dann
besser include_once() mit Fehlerprüfung muss einem "new"
dann eh vorausgehen. Anscheinend bietet class_implements()
dafür auch direkt ein autoload mit default=true an ;-)


bool is_subclass_of (mixed $classNameOrInstance , string $expectedBaseClass)
array class_implements (mixed $classNameOrInstance [, bool $autoload=true ] )


Daher ist mir autoload bei new zu unsicher.
In den anderen ("statischen") Fällen sind die requires bekannt,
also auch kein autoload benötigt.

Naja, dynamische Klassen in PHP sind wohl irgendwo ein philosophisches
Thema - ob meine Ausführungen nun der ganzen und einzigen Wahrheit
entsprechen ist wohl fragwürdig, aber es ist mal eine weitere Sichtweise ...

Gruß

Stefan

DokuLeseHemmung
09.02.2009, 12:52:31
Daher ist mir autoload bei new zu unsicher.
Das "Daher" verstehe ich nicht!

Ich verstehe auch die obrigen Probleme nicht.
Die Ursache der Sorgen liegt wohl im falschen Verständnis des Autoload Vorgangs und unglücklicher Klassenbenennungen. Also ein Struktur Problem.

Wenn man mir das Problem erklärt, will ich die Angelegenheit gerne ausbreiten.

Bisher hatte ich noch keine Sorgen mit dem Autoload.


Ich denke mittlerweile, dass gerade dann, wenn Objekte
dynamisch instantiiert werden, muss man vorher einen
Blick auf die Klasse und die Vererbungsliste / Interface-
Liste der Klasse werfen,
Warum?
Man kennt die Klasse doch!
ein einfaches class_exists() reicht doch völlig-

urvater
09.02.2009, 20:00:25
Fühle mich jetzt leicht überfordert aber werde mich da schon reinwurschteln. Auch wenns nicht beabsichtigt war, eure Diskusion zeigt mir wenigstens gleich, was ich noch alles dabei beachten sollte.

Danke für die Anregungen und Darstellungen.

stfwi
09.02.2009, 22:45:23
Hi,

es läuft darauf hinaus, dass wenn ich explizit include_once() sage bekomme
ich einen abfangbaren Fehler wenn die Klasse bereits existiert, aber nicht aus
derselben Datei stammt bzw. dieselbe ist. Bei new und autoload wird die Klasse verwendet,
wenn sie da ist. In meinem Fall hatte ich im Kernscript eines klassenbasierten
Frameworks zuerst autoload verwendet. In einem der dynamischen Module wurde nun zufällig
eine Kollision der Klassennamen verursacht. Das hätte das framework abfangen
müssen, konnte es aber nicht, da die Instanz im framework erst nach dem Ausführen
des Moduls erstellt wurde - mit der falschen Klasse. Dummerweise war dann noch
Output-Buffer etc. an, so dass beim Browser nur noch eine leere Seite ankam, weil
das Script abgebrochen hat. Die Lösung war nachher einfach, aber erst mal drauf
zu kommen, dass der zufällig den selben Klassennamen verwendet hat ... ein compiler
hätte sich beschwert ;) Daher lade ich die Klassen explizit und prüfe die Schnittstellen
von dynamisch erstellten Objekten (wenn class_exists()).
Es ist wohl nicht der häufigste Anwendungsfall, aber - wie gesagt - eine Sichtweise.

Gruß

Stefan

DokuLeseHemmung
09.02.2009, 23:11:05
wie gesagt - eine Sichtweise.


Und meine Sichtweise geht so:
Man hält sich ganz ganz strickt an das Zend bzw. Pear Benennungsschema für Klassenbezeichner. Gepaart mit ein wenig Disziplin, kann es niemals passieren, dass man 2 Klassen mit dem selben Namen hat.




Hier nachzulesen:

PHP 5:
http://framework.zend.com/manual/de/coding-standard.naming-conventions.html
http://pear.php.net/manual/de/standards.naming.php

PHP >= 5.3:
http://www.php.net/manual/de/language.namespaces.php
http://pear.php.net/manual/de/pear2cs.rules.php

Also die Klasse "DLH_Db_Adapter_Mysql" steckt dann wirklich in der Datei "./lib/DLH/Db/Adapter/Mysql.php".

Kann man zu stehen, wie man möchte, aber ich habe damit gute Erfahrungen gemacht!
1. Keine Sorgen mit doppelten Bezeichnern.
2. Nirgendwo eingestreute include o.ä.
3. einfacher universeller Autoloader

urvater
24.03.2009, 23:54:19
Ich muss das Thema noch einmal aus der Versenkung holen. Der Autoload selbst funktioniert zur Zeit bei mir recht gut. Allerdings bringt das Script von Doku eine Fehlermeldung weil spl_autoload_register nicht existiert.

Theoretisch brauch ich ja nur eine neuere PHP Version aber das wird noch dauern, wenn es nicht generell unmöglich wird.

Auf Arbeit haben wir PHP in Vers. 5.0.x auf mein gemieteten Webspace hab ich leider nur Vers. 4.4.7 .
Auf Arbeit wird wohl nie eine neue Version drauf kommen, da es eher ein übrig gebliebener Server ist, bei meinem Webspace muss ich mal eine Anfrage starten ob sie den updaten.

So nun meine eigentliche Frage: Gibt es eine alternative Funktion zu spl_autoload_register?

EDIT: Ah hab gerade folgendes Gefunden: This extension is available and compiled by default in PHP 5.0.0.
Ich sehe nun zumindest für Arbeit einen Lichtblick

DokuLeseHemmung
25.03.2009, 00:56:19
Bei den 4.* Versionen, keine Chance!
Eine nicht gefundene Klasse wirft unmittelbar einen Fatal Error. Nix Autoload.

Auch deine 5.0.x ist nicht gerade frisch.
Irgendwas >= 5.2.3 wäre schöner...

urvater
25.03.2009, 01:29:16
Bei den 4.* Versionen, keine Chance!
Eine nicht gefundene Klasse wirft unmittelbar einen Fatal Error. Nix Autoload.

Auch deine 5.0.x ist nicht gerade frisch.
Irgendwas >= 5.2.3 wäre schöner...

Hab gerade bei meinem Hoster eine Anfrage gestellt. Würde ich als Neukunde Webspace mieten gibt es midestens Version 5. Welche genau steht nicht da. Ich habe also zumindest Hoffnung ab 5.0 eine Version installiert zu bekommen.

Das die 5.0.x nicht frisch sind ist mir bekannt. Leider werde ich vermutlich keine Chance haben (Provider mal ausgenommen) eine höhere Version zu bekommen. Naja muß ich halt mit leben und mit entsprechend kleinen Brötchen backen. :(

Das Problem mit Funktionen, die erst ab >5.2 existieren ist mir schon schlecht auf den Magen geschlagen. Da findet man schon eine fertige Funktion und kann sie nicht verwenden. Ok, mit etwas Aufwand konnte man eine vergleichbare Funktion auch nachbilden aber der Aufwand. :(

Danke jedenfalls für die Info

DokuLeseHemmung
25.03.2009, 01:52:52
Für deine "PHP Versorger" würde ich mal eine 48 stündige Besinnungspause auf einer handelsüblichen Streckbank vorsehen.
Die Begründung dafür können sie sich gerne bei mir Abholen...

urvater
25.03.2009, 02:17:36
Für deine "PHP Versorger" würde ich mal eine 48 stündige Besinnungspause auf einer handelsüblichen Streckbank vorsehen.
Die Begründung dafür können sie sich gerne bei mir Abholen...
Würd ich gerne veranlassen leider sind es Beamte, da ist es leichter die Zeugen davon zu überzeugen, daß Jesus nie gelebt hat.