mmofacts.com

Autoloader Klasse

gepostet vor 14 Jahre, 9 Monate von BlackScorp

Hallo Leute,

ich kennt doch sicherlich das Problem beim Autoloader mit langen kalssen namen etwa so:

$beispiel = new pfad_zur_klasse_in_einem_ordner_testklasse();

mich hat halt das ganze ein wenig gestört und ich habe eine klasse geschrieben mit der ich die Ordner vorher definiere und danach include. Das ganze sieht dann so aus:

PHP:

class AutoLoader {
    private static $includeDir;
    private static $includeFile;
    public static function import($dir) {
        self::$includeDir[] = $dir;
    }
    public static function load($className) {
        foreach(self::$includeDir as $directories) {
            if(file_exists($directories.$className.'.class.php')) {
                self::$includeFile = $directories.$className.'.class.php';
            }
        }
        return self::$includeFile;
    }
}
?>

und die Anwendung funktioniert so:

PHP:

// autoloader klasse inlcude
  require_once 'pfad/zur/autoloader/AutoLoader.class.php';
//Bestimmen in welchen Ordnern sich meine klassen befinden
        AutoLoader::import('../../foo/');
        AutoLoader::import('../../bar/foo2/');
//Autoload function anwenden

        function __autoload($className) {
            require_once AutoLoader::load($className);
        }
$foo = new Foo();
echo $foo->methode();

 Somit brauche ich nicht mehr den pfad in dem klassen namen mit anzugeben. nun meine Frage wäre ob es denn nicht zu viel ressourcen verbraucht, denn jedes mal beim aufruf einer klasse werden alle zu includenden ordner durchsucht ob da eine klassen datei exestiert und wenn die exestiert, wird die included.

ich schätze mal bei sagen wir 10 ordnern muss es doch lange dauern bis eine klasse included wird oder?

ich habe das bis jetzt getestet aber meine klassen waren auch klein und immer nur mit test ausgaben desswegen kann ich das von vornerein nicht beurteilen aber ihr habt da bestimmt mehr erfahrung

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Schön du hast die Funktionalität des "include_path" nachgebaut, wenn ich es beim überfliegen richtig verstanden habe. ;)

Ich finde längere Klassennamen nicht schlimm, wenn diese Sinn ergeben. Ich würde dir vielleicht mal empfehlen die Struktur vom Zend Framework anzuschauen. Da gibt es dann Namen wie "Zend_Db_Table_Abstract". Da weiß man genau es gehört zum Paket "Zend_Db", hat etwas mit Tabellen zu tun und ist eine abstrakte Klasse von der ich ableiten muss.

In PHP 5.3 kommen dann Namespaces hinzu mit dessen Hilfe du dir die Klasse ebenfalls sparen kannst, Beispiel (nur ganz grob, ich kenne die Syntax noch nicht genau):

PHP:

ordner/klasse.php:
namespace ordner;
class klasse {}
Irgendeine Datei:
using ordner;
new klasse();

Brauchst dann nur einen Autoloader der die Namespacestruktur auf die Ordnerstruktur abbildet. Im übrigen solltest die Funktion "__autoload()" nicht mehr einsetzen, in der SPL gibt es dafür etwas neues, was es auch erlaubt dass mehrere Bibliotheken einen Autoloader definieren -> "spl_autoload_register()".

gepostet vor 14 Jahre, 9 Monate von BlackScorp

Original von DrakeL

Schön du hast die Funktionalität des "include_path" nachgebaut, wenn ich es beim überfliegen richtig verstanden habe. ;)

Naja nicht ganz. include_path wird ja in der php.ini definiert:D

ich habe quasi sowas wie c++ verweis #include nachgebaut

Ich finde längere Klassennamen nicht schlimm, wenn diese Sinn ergeben. Ich würde dir vielleicht mal empfehlen die Struktur vom Zend Framework anzuschauen. Da gibt es dann Namen wie "Zend_Db_Table_Abstract". Da weiß man genau es gehört zum Paket "Zend_Db", hat etwas mit Tabellen zu tun und ist eine abstrakte Klasse von der ich ableiten muss.

naja man kennt dadurch die struktur aber dennoch ist es nicht besonders gut wenn ich sowas habe

$bsp = new KategorieName_PackageName_SubPackageName_ClassName();

sieht nicht schön aus

In PHP 5.3 kommen dann Namespaces hinzu mit dessen Hilfe du dir die Klasse ebenfalls sparen kannst, Beispiel (nur ganz grob, ich kenne die Syntax noch nicht genau):

PHP:

ordner/klasse.php:
namespace ordner;
class klasse {}
Irgendeine Datei:
using ordner;
new klasse();

Brauchst dann nur einen Autoloader der die Namespacestruktur auf die Ordnerstruktur abbildet. Im übrigen solltest die Funktion "__autoload()" nicht mehr einsetzen, in der SPL gibt es dafür etwas neues, was es auch erlaubt dass mehrere Bibliotheken einen Autoloader definieren -> "spl_autoload_register()".

 Naja gut diese funktion kannte ich nicht. habe autoloader in google eingegeben und da kamen mehrere beispiele wie man in der autoload klasse den klassen namen aufspaltet und die  _ mit / ersetzt von der spl_autoload_register() war nirgendwo die rede. ich denke ich werde noch meine klasse benutzen bis php 5.3 rauskommt. danke für die infos

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

Naja nicht ganz. include_path wird ja in der php.ini definiert:D

Nicht zwingenderweise, ich setze ihn in der "index.php".

naja man kennt dadurch die struktur aber dennoch ist es nicht besonders gut wenn ich sowas habe

$bsp = new KategorieName_PackageName_SubPackageName_ClassName();

sieht nicht schön aus

Ich finde es sieht schön aus, weil man genau erkennt was die Klasse tun soll bzw. woher diese kommt. Zumal es ausgeschlossen ist, dass mehrere Klassen mit dem selben Namen existieren, was bei dir durchaus vorkommen kann.

Naja gut diese funktion kannte ich nicht. habe autoloader in google eingegeben und da kamen mehrere beispiele wie man in der autoload klasse den klassen namen aufspaltet und die  _ mit / ersetzt von der spl_autoload_register() war nirgendwo die rede. ich denke ich werde noch meine klasse benutzen bis php 5.3 rauskommt. danke für die infos

PHP 5.3 ist schon draussen, war vielleicht etwas unglücklich formuliert von mir: http://www.php.net/archive/2009.php#id2009-06-30-1

Deine Klasse verschleiert halt den gesamten Präfix, nicht mehr und nicht weniger. Es gehen dir Informationen verloren, im Gegensatz dazu hast du weniger Schreibarbeit. Ich finde die Informationen sind wichtiger und die Schreibarbeit ist meist gering wenn man sich mal an Auto Vervollständigung gewöhnt hat. Ab PHP 5.3 hast die Informationen am Anfang der Datei und weniger Schreibarbeit dazu. Man muss nur aufpassen, dass man keine zwei Namensräume nutzt, die die gleiche Klasse implementiert, denn dann gibt es wieder Namenskonflikte bei der Benutzung.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

aww nice. dann brauche ich meine autoload klasse nicht.

habe das gleich mal ausprobiert aber ich kriege es nicht hin. ich mache ja normalerweise

require_once '../../core/'.$className.'.class.php';

aber wie kann ich im namespace sagen dass die klasse sich nicht in dem ordner befinden wo ich meine datei erstelle sondern ein paar ordnern davor? also quasi brauche ich sowas:

namespace ..\..\core

da gibts ein syntax error. und bei

namespace core

sagt er dann class core/DataBase cannot found vllt kennste da ein trick? oder weis von welcher ordner ebene namespace die ordner durchsucht.also quasi

-core

-- Class1.class.php

-- Class2.class.php

-prjects

--project1

---index.php

und ich möchte halt von der index.php auf core datein zugreifen

MFG

EDIT:

Bitte korriegiert mich wenn ich was falsch verstanden habe.

namespace ist nicht das selbe wie autoload

namescapes sind dazu da um einer datei zu sagen hier du gehört zu dem namespace und du zu dem anderen damit kann ich dann merhere gleichnamige klassen includen und es gibt kein error mit cannot rediclare klass. foraussetzung dafür ist dass die gleichnamigen klassen sich in unterschiedlichen namespaces befinden. d.h ich kann zb zend framework und ein anderes framework gleichzeitig nutzen wenn ich den beiden unterschiedliche namespaces zuweise. und wenn die beiden framworks gleiche klassen namen haben , gibt es kein konflikt zwischen den klassen.

also brauche ich die autoload klasse doch. habe ich das richtig verstanden?

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

also brauche ich die autoload klasse doch. habe ich das richtig verstanden?

Einen Autoloader brauchst du ja.

In diesem musst dann die Trennzeichen zwischen Namespaces bzw. Namespace und Klassenname umwandeln in Verzeichnistrennzeichen (Also soweit ich grad weiss "::" ersetzen mit "/" oder der Kontante). Es spart dir halt das Laden/Registrieren der Verzeichnisse, da anhand von Namespace genau sagen kannst in welchem Verzeichnis sich die Klasse befindet. Von der Theorie her also das gleiche wie die langen Klassennamen, nur dass Namespaces durch "using " nicht immer wieder schreiben musst bei jeder Klasse.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

hm.. ich denke ich brauche da etwas hilfe.
also ich habe folgende datei struktur:
main
-core
--class1.class.php
--class2.class.php
//usw
-project
--acp
---classes
---- seite1.class.php
---- seite2.class.php
---index.php
--start
//genau so wie in ACP
also ich habe meine Klassen welche mir Methoden liefern im Core drin
und in projects/acp habe ich klassen welche die methoden aus core benutzen und vews erstellen
praktisch im browser wird aufgerufen http://url.de/projects/acp/index.php
so habe in dem verzeichniss core bei jeder klasse in der ersten zeile folgendes reingeschrieben:
namespace core;
//hier kommt die klasse danach
und in der projects/acp/index.php habe ich folgendes reingeschrieben:
namespace projects\acp;
use core;
wie soll nun die autoload klasse aussehen? weil ständig kommt bei mir der fehler
Fatal error: Class 'core\AutoLoader' not found in \projects\acp\index.php on line 9
MFG

gepostet vor 14 Jahre, 9 Monate von knalli

Ich kenne PHPs geniale Umsetzung noch nicht praktisch, aber: Ist deine Autoloader-Klasse denn korrekt eingebunden (sprich: normales Include)? Und hat sie selber auch eine Konfiguration, das sie im core-Paket liegt?

Bei der Konfiguration von Packages (Namespaces) und Klassen könnte man sich ja an Standards wie in Java orientieren: Jedes Package ist ein Ordner, wobei die Delimiter (Java ., in PHP halt \) einfach nur eine weitere Ebene bedeutet. Wenn man so will, eine abzulesende Pfadangabe. 

gepostet vor 14 Jahre, 9 Monate von BlackScorp

also ich habe damit rumgespielt und habe es zum laufen gekriegt es geht folgendermaßen:

irgendeineKlasse.class.php erhält ein namenspace

namespace core;

die datei, welche diese klasse aufruft benutzt

use core/Klassenname;

dennoch benötige ich ein require_once pfad_zur_datei;

also ohne autoloader würde das ganze so aussehen:

use core/DataBase;

use core/Template;

use core/usw

und jedes mal zu der klasse ein requer once. ich verstehe dann den vorteil darin nicht. ich habe mehr quellcode und doppelte klassen in unterschiedlichen namespaces funktionieren nicht. ich habe mir 2 test klassen angelegt so sehen die aus:

ordner1/test1.class.php

namespace test1

class test1

public function methode1()

{}

ordner2/test1.class.php

namespace test2

class test1

public function methode1()

{}

index.php

use ordner1\test1;

requiere_once 'ordnder1/test1.class.php';

use ordner2\test1;

requiere_once 'ordnder2/test1.class.php';

$test1a = new ordner1\test1();

$test1b = new ordner2\test2();

und dann kam die meldung cannot rediclare. ledeglich wenn ich die funktion spl_autoload_register() benutze und in der funktion alle methoden einer klasse einfüge(spl_autoload_register(__NAMESPACE__.'\test1->methode1'); )

dann gibts kein konfilikt zwischen den klassen. entweder verstehe ich nicht den sinn von namespaces in php oder ich wende es falsch an. was sagt ihr dazu?

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

use core/DataBase;

use core/Template;

use core/usw

und jedes mal zu der klasse ein requer once. ich verstehe dann den vorteil darin nicht. ich habe mehr quellcode und doppelte klassen in unterschiedlichen namespaces funktionieren nicht. ich habe mir 2 test klassen angelegt so sehen die aus:

Natürlich funktionieren doppelte Klassen nicht wenn beide Namespace per use einbindest, welche Klasse soll er denn nehmen? Statt dem use kannst den Namespace auch vor die Klasse schreiben (wie es in Java auch der Fall ist).

index.php

use ordner1\test1;

requiere_once 'ordnder1/test1.class.php';

use ordner2\test1;

requiere_once 'ordnder2/test1.class.php';

$test1a = new ordner1\test1();

$test1b = new ordner2\test2();

und dann kam die meldung cannot rediclare.

Wie oben geschrieben, wenn den gleichen Klassennamen in mehreren Namespaces verwendest, darfst diese nicht zusammen mit use einbinden, da nicht mehr eindeutig ist, welche Klasse du verwenden willst. Und wenn du wie hier im Beispiel den vollqualifizierten Namen (mit Namespaceangabe beim new) verwendest, kannst die use Sachen auch weglassen. Das use ist nur dazu da, dass die Namespaceangaben weglassen kannst, also weniger Schreibarbeit.

ledeglich wenn ich die funktion spl_autoload_register() benutze und in der funktion alle methoden einer klasse einfüge(spl_autoload_register(__NAMESPACE__.'\test1->methode1'); )

"spl_autoload_register()" verlangt den Namen einer Callback Methode die als Autoloader funktioniert (einfach deine vorherige "__autoload()" Methode umbenennen und den Namen der "spl..." Funktion als String mitgeben sollte gehen).

dann gibts kein konfilikt zwischen den klassen. entweder verstehe ich nicht den sinn von namespaces in php oder ich wende es falsch an. was sagt ihr dazu?

Beides würde ich behaupten, wüsste allerdings nicht wie ich es dir in ein paar Sätzen erklären sollte noch dazu habe ich die Namespaces in PHP bisher nur in der Theorie gelesen und noch nicht praktisch verwendet (stimmt zum Beispiel das Trennzeichen "\", dachte das wurde geändert auf "::" oder anders herum?).

gepostet vor 14 Jahre, 9 Monate von knalli

Nein, der Unsinn ist tatsächlich so richtig - soweit bin ich mit meiner PHP-Theorie auch schon. Das andere war den Parser-Jungs angeblich zu schwierig ;)

Zum Thema: Vielleicht mal das Java-Package-System verinnerlichen, dann wird es klarer.

gepostet vor 14 Jahre, 9 Monate von TheUndeadable

Mit ordentlichen Namespaces ersparst du dir die unsäglichen Präfixe der einzelnen Klassen.

Gerade PHP ist so unglaublich inkonsequent mit Präfixen behaftet (mysql_, str_, etc). Sehe einfach die Namespaces als Ordnungselement für Klassenbibliothen und für größere Projekte sind diese einfach unschlagbar praktisch. Sie haben keine semantische Bedeutung, nur eine syntaktische.

http://en.wikipedia.org/wiki/Namespace_(computer_science)

gepostet vor 14 Jahre, 9 Monate von BlackScorp

ok habe die __autoload funktion weggelassen und einiges verändert. eigentlich sollte ich von der Syntax her die namespaces nun richtig verwenden, dennoch gibt es probleme. und zwar dass wenn ich in einem namespace ein anderen namespace verwenden will, kommt eine meldung

Permission denied , require_once() [function.require]: Failed opening required ''

eventuell könnt ihr mir sagen woran das liegen kann?. also mal kurz meine Ordner Struktur:

Kurze erklärung:

core ordner enthält Klassen welche Methoden zur verwendung bereitstellen.

Porojects/acp/classes benutzen die Methoden aus core und geben ein vew and die index.php,welche dann ein Layout im Browser erstellt.

----------------------------------------------------------------------------------------------------------

ich habe nun die AutoLoader.class.php ins namespace se\core\al reingelegt und die DataBase.class.php in se\core\db

die index.php in projects/acp ist im namespace se\projects\acp

das ganze sieh dann so aus:

DataBase.class.php:

http://pastebin.com/m43c1a666

AutoLoader.class.php:

http://pastebin.com/m7fe0fcc9

index.php aus Projects/acp:

http://pastebin.com/m1edb8358

und als Fehlermeldung kommt dann:

Warning: require_once(C:\xampp\xampp\htdocs\share\scorpengine\projects\acp) [function.require-once]: failed to open stream: Permission denied in C:\xampp\xampp\htdocs\share\scorpengine\core\AutoLoader.class.php on line 18
Fatal error: require_once() [function.require]: Failed opening required '' (include_path='.;C:\xampp\xampp\php\PEAR') in C:\xampp\xampp\htdocs\share\scorpengine\core\AutoLoader.class.php on line 18

hoffe ihr wisst woran es liegen kann

MFG

gepostet vor 14 Jahre, 9 Monate von Amun Ra

Also ich seh den Sinn deiner class AutoLoader gerade überhaupt nicht.
Sie macht auch nicht wirklich das was der Name vermuten lässt.
Du emulierst eigentlich nur set_include_path().
Aber Hauptsache erstmal alles schön in eine Klasse verpacken...

gepostet vor 14 Jahre, 9 Monate von BlackScorp

Der sinn der autoloadklasse ist folgender:
wenn ich use foo\bar benutze, muss ich dennoch den pfad angeben wo sich die datei befindet mit dem namespace.
also müsste ich unter JEDEM
use foo\bar;
ein
include 'foo/bar.class.php';
reinschreiben. und die Autoloader klasse entinmmt mir das. ich include mit der klasse alle Datein aus den ordnern,
welche ich durch import methode angegeben habe. Das ist der Sinn der Klasse.

Dazu wird dann nicht IMMER irgendwas included sondern nur wenn es benötigt wird(habe irgendwo mal hier im forum gelesen dass es sinnvoller wäre alles nur dann includen wenn es benötigt wird anstatt von vornerein alles mögliche zu includen)

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

Der sinn der autoloadklasse ist folgender:

Eines AutoLoaders ja, aber dein Autoloader macht dies falsch. Du musst aufpassen, im Klassennamen den der Autoloader als Parameter übergeben bekommt ist der Namespacename dabei, also wenn du folgendes schreibst:

PHP:

use Namespace;
$object = new Example();

Dann bekommt der Autloader "Namespace\Example" übergeben unabhängig davon ob du use benutzt oder nicht (ich hoffe ich laber gerade kein mist, ich hab beim testen noch kein use benutzt, ohne gehts auf jeden Fall so, aber mit use weiss er ja eigentlich gar nicht welchen Namespace er übergeben soll weil er die Klasse noch nicht kennt, weiß das gerade jemand?).

Wenn du nun den Namespace als Verzeichnisstruktur nimmst (Klasse Example ist im Ordner Namespace). Dann kannst die Namespacetrennzeichen einfach durch Verzeichnistrennzeichen ersetzen und includieren.

PHP:

function autoload($classname)
{
if (is_file($path = str_replace('\', DIRECTORY_SEPARATOR, $classname))) {
  require $path;
}
}

Auf diese Weise ersparst dir das emulieren oder setzen des include_path für alle Verzeichnisse in denen sich Klassen befinden. Und anhand des Namespaces und Klassennamens weißt du auch genau in welcher Datei welches Verzeichnisses du nach der Klasse suchen musst.

Achtung: Ich hab die Sachen praktisch noch nicht ausprobiert, bin derzeit noch auf dem Stand von Zend mit Unterstrichen statt Namespaces. :)

gepostet vor 14 Jahre, 9 Monate von BlackScorp

ok das ist verständlich aber mein Problem ist halt dass sich meine Core klassen nicht im unterverzeichniss sind, sondern 2 ebenen höher.

und sowas kann ich ja nicht verwenden:

use ..\..\core\

$foo = new Foo();

anscheinend funktioniert das ganze NUR wenn die klassen sich im unterordnern befinden. ich denke ich muss meine Ordnerstruktur überarbeiten(und die autoload sowieso:D)

gepostet vor 14 Jahre, 9 Monate von DrakeL

Schau dir die Ordnerstruktur von Zend an. Es gibt den Ordner Zend in dem die komplette Bibliothek liegt. Und alle Klassennamen sind auf die Verzeichnisstruktur abgebildet, zum Beispiel die Klasse "Zend_Db_Table_Abstract" befindet sich in der Datei Abstract.php im Verzeichnis Zend/Db/Table.

Bei dir scheint es einfach 2 Ordner zu geben die darauf zutreffen. Core und Rest, also müsstest du beide Ordner in den include_path aufnehmen und darin dann jeweils die Klassenstruktur abbilden. Aber include_path hat nichts mit dem Autoloader zu tun, da solltest dich noch einlesen was es ist.

gepostet vor 14 Jahre, 9 Monate von Nuky

wieso nicht einfach 

function __autoload($class_name)

  if($class_name == "eine_core_klasse") require_once(CORE_HOME."/class_corezeug.php");

  if($class_name == "so_eine_andere") require_once(OTHER_HOME."/class_andere.php");

und die defines in ne zentrale config packen, die dich dann schön unabhängig macht..?

define("CORE_HOME", "/home/verzeichnis/vom/core");

define("OTHER_HOME", "/home/verzeichnis/vom/anderen/zeug");

klssen sind toll, wenn man weiß wozu sie nützlich sind. ich glaube hier sind sie mehr klotz am bein als sonst was.

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von Nuky

wieso nicht einfach[...]

Dann müsstest du ja Whitelisten pflegen in welche Gruppe die jeweilige Klasse gehört bzw. die Gurppen und die darin liegenden Klassen eher.

Zusätzlicher manueller Aufwand der minimal bessere Performance bringt im Gegensatz zum include_path erweitern.

klssen sind toll, wenn man weiß wozu sie nützlich sind. ich glaube hier sind sie mehr klotz am bein als sonst was.

Es geht hier ja nicht direkt um die Klassen, sondern um die Struktur des Projektes. Gleiches Problem hättest du wohl auch wenn du Funktionen auslagern willst in einzelne Dateien (wobei es hierfür nichtmal ein Autoload Mechanismus gibt).

gepostet vor 14 Jahre, 9 Monate von BlackScorp

es geht mir auch darum die namespaces richtig zu verwenden damit ich nicht immer dieses

$class = new Package_subPackage_KlassName() verwenden muss.

BTW: ich habe meine AutLoadKlasse verändert:

PHP:

namespace scorpengine\core{
    class AutoLoader {
        public static function load($className) {
            $path = str_replace('\\','/','\\share\\'.$className.'.class.php');
            if(is_file($path)&& file_exists($path)) {
                require $path; 
            }
            echo $path.'
';
        }
    }
}
 

 und die index.php sieht nun so aus:

PHP:

namespace scorpengine\projects\acp\classes{
    use scorpengine\core as seCore;
    require_once '../../core/AutoLoader.class.php';
    spl_autoload_register('scorpengine\core\AutoLoader::load');
   
    class Programm {
        public function __construct() {
            $this->init();
        }
        private function init() {
            $this->connectDataBase();
            $this->setDefaultRights();
        }
        private function setDefaultRights() {
            $_SESSION['rights'] = Defines::$defaultRights;
        }
        private function connectDataBase() {
            seCore\DataBase::getInstance()->connect(
            Defines::$mySqlServer,
            Defines::$mySqlUserName,
            Defines::$mySqlPassword,
            Defines::$mySqlDataBase);
        }
        public function start() {
            $stream = new seCore\Stream();
            return $stream->out('layout');
        }
    }
    $programm = new Programm();
    print $programm->start();
}
?>

 wenn ich nun in der autoload klasse den pfad anzeigen lasse dann kommt folgender link:

/share/scorpengine/core/DataBase.class.php

der pfad ist richtig ich kann die DataBase.class.php sehen wenn ich http://localhost/share/scorpengine/core/ aufrufe. Nur wird die Datei nicht inlcuded es kommt immer eine Fehlermeldung:

Fatal error: Class 'scorpengine\core\DataBase' not found in C:\xampp\xampp\htdocs\share\scorpengine\projects\acp\index.php on line 21

ich vestehe es überhaupt nicht denn die Autoloader klasse wird ja aufgerufen, also gehe ich davon aus dass ich die Namespaces richtig eingesetzt habe. Vllt wisst ihr ja woran es liegen könnte oder habe ich wieder meine "AutoLoad" klasse total falsch erstellt?

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

BTW: ich habe meine AutLoadKlasse verändert:

PHP:

namespace scorpengine\core{
    class AutoLoader {
        public static function load($className) {
            $path = str_replace('\\','/','\\share\\'.$className.'.class.php');
            if(is_file($path)&& file_exists($path)) {
                require $path; 
            }
            echo $path.'
';
        }
    }
}
 

Wenn du einfache Anführungszeichen verwendest brauchst glaub gar kein doppelten Backslash, oder irre ich mich grad? Die Konstante DIRECTORY_SEPARATOR wäre hier interessant für dich. Des Weiteren muss eine Datei existieren um eine Datei sein zu können, also bringt die "file_exists()" Prüfung nie etwas.

 wenn ich nun in der autoload klasse den pfad anzeigen lasse dann kommt folgender link:

/share/scorpengine/core/DataBase.class.php

Das heißt du hast ein print/echo in den Autoloader gemacht bevor die Datei includet wird und hast diese Ausgabe bekommen? Hast den Pfad überprüft indem einfach statt den Autoloader zu registreiren einfach selbst ein require mit dem Pfad machst? Funktioniert dieses? Irgendwas ist falsch an den Stellen.

Ich sehe grad du hast ein print unterhalb der Selektion, ich behaupte der Programmfluss geht nie in die Selektion rein, prüfe das am besten.

Daher prüfe was genau versucht wird zu includen (print $path vor dem require) und versuche dies selbst zu includen mit dem Pfad den dort ausgegeben wird. Ich denke der Pfad stimmt hier nicht.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

hattest recht, es lag echt an dem pfad. habe nun document_root drangehängt#

PHP:

namespace scorpengine\core{
    class AutoLoader {
        public static function load($className) {
            $path = str_replace('\\',DIRECTORY_SEPARATOR,$_SERVER['DOCUMENT_ROOT'].'\\share\\'.$className.'.class.php');
            if(is_file($path)) {
                require $path; 
            }
        }
    }
}

 und nun wenn ich im meinen klassen(project/acp/classes) eine der Core Klassen verwenden will, muss ich nur unter dem namespace

use scorpengine\core as core;

hinschreiben und die klassen so ansprechen

$testClass = new core\TestClass();

$testClass->method();

nun funktioniert es . Muss aber viele einstellungen im Script vornehmen

vielen dank für eure Hilfen

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

nun funktioniert es . Muss aber viele einstellungen im Script vornehmen

Was für Einstellungen? ist ja nur der include_path der fehlt, alles andere sollte ja ohne irgendwas einzustellen funktionieren.

vielen dank für eure Hilfen

Gern geschehen.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

naja mit den einstellungen meine ich die Projekt einstellungen.

es ist so:

ich habe in Projects ordner mehrere Projekte(sprich ACP,Server1,Server2 usw)

mein Ziel ist es alle PHP datein auf einem Server zu behalten, jedoch auf unterschiedliche Datenbanken zugreifen, die nicht umbedingt localhost sind.

jeder dieser Projekte hat andere Datenbankverbindung, eine andere ProjektId. In jedem Projekt ordner habe ich eine Defines klasse und der Inhalt sieht dann so aus:

namespace scorpengine\projects\acp\classes {
class Defines
{
    public static $mySqlServer = 'irgendeinserver';
    public static $mySqlUserName = 'xxx';
    public static $mySqlPassword = 'xxx';
    public static $mySqlDataBase = 'server1';
    public static $defaultLanguageId = 1;
    public static $tablePrefix = 'bsp_';
    public static $projectSalt = 'bsp';
    public static $userNameLenght = array(3,16);
    public static $passwordLenght = array(6,20);
    public static $refreshTime = 2;
    public static $projectId = 1;
    public static $defaultRights = array('0');
    public static $templateName = 'layout/default/';
    public static $defaultPage = 'home';
}
}

diese Defines habe ich immer in Core Klassen verwendet.

zb in Code/Template.class.php hatte ich ein TemplatePath definiert, der Templatepath steht in Defines drin utner Defines::$templateName.

Ich fand diese Define Klasse praktisch da ich in NetBeans einfach nur Defines:: eingeben musste und schon hatte ich eine auswahl an meinen Settingsvariablen.

Nun musst ich wohl oder übel diese Define klasse löschen und irgendwie mit define(CONSTANT,'wert'); deklarieren. Oder hättet ihr da ein besseren vorschlag? wollte eigentlich nicht mehr constanten in der Form benutzen

 ich habe mir gedacht alle diese constanten and sessions zu übergeben, aber habe irgendwo mal gelesen dass es nur eine begrenzte anzahl an sessions exestiert, oder waren das cookies?

MFg

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

Nun musst ich wohl oder übel diese Define klasse löschen und irgendwie mit define(CONSTANT,'wert'); deklarieren. Oder hättet ihr da ein besseren vorschlag? wollte eigentlich nicht mehr constanten in der Form benutzen

ich nutze dafür PHP Dateien die ein Array zurückliefern, es muss nicht alles in Klassen verpackt sein :). Hier ein Beispiel anhand der Datenbankeinstellungen:

PHP:

//settings/database.php:
return array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'localhost',
'username' => '',
'password' => '',
'dbname' => ''
));
//Verwendung:
$adapter = Zend_Db::factory(new Zend_Config(require 'settings/database.php'));
gepostet vor 14 Jahre, 9 Monate von BlackScorp

naja das problem dabei ist, du musst dann den genauen pfad angeben woher du deine datein nimmst,

diese settings datei befindet sich aber je nach dem was gerade offen ist in anderen ordnern.

dh:

projects/acp/classes/Defines.class.php

server = xxx1

username = xxx1

usw.

project/server1/classes/Defines.class.php

server=xxx2

username = xxx2

usw.

also die settings die ich benötige stehen immer wo anders:D

das bedeutet dass diese werte überall sichtbar sein müssen. mit sessions würde man es realisieren können aber ich habe aktuell nur 10 globale variablen eventuell kommen weitere dazu. kann man es denn mit session realiesieren? oder bessere gefragt, darf man es?

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

also die settings die ich benötige stehen immer wo anders:D

Irgendwo muss bekannt sein wo diese stehen. Wenn du es per Klasse machst weißt du da wo du die Einstellungen brauchst auch genau wie sie stehen, denn du gibst mit Hilfe des Namespace die Verzeichnisstruktur an.

Wenn es Modular machst kannst es auch per Dateipfad machen, Verzeichnisstruktur (die - sind jeweils die Verzeichnisebenen, weiss gerade nicht wie eine verschachtelte Liste geht):

- a

-- settings

--- database.php

-- a.php

- b

-- settings

--- database.php

-- b.php

Und in "a.php" oder "b.php" kannst jeweils folgendes schreiben:

PHP:

$database = require __DIRNAME__ . '/settings/database.php';

Dann beziehst du dich immer auf die Einstellungsdatei innerhalb deines jetzigen Modules. Soweit ich weiß ist die Konstante direkt, kann aber sein dass kein Slash mehr brauchst oder so, weiß ich gerade gar nicht auswendig (Copy&Paste geschädigt, sowas schreibt man selten ^^).

das bedeutet dass diese werte überall sichtbar sein müssen. mit sessions würde man es realisieren können aber ich habe aktuell nur 10 globale variablen eventuell kommen weitere dazu. kann man es denn mit session realiesieren? oder bessere gefragt, darf man es?

Wenn sie überall sichtbar sein sollen mach doch ein großes Array und auf erster Ebene als Schlüssel ein Bezeichner welche Datenbank oder Modul sich die Einstellungen darunter beziehen. Das Ganze kannst dann als globale Variable oder Zend like in einem Registryobjekt ablegen.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

habe das nun so gelöst:

Defines.php

$_SESSION['defines'] = array(
    'mySqlServer' => 'localhost',
    'mySqlUsername'=>'xxxx',
    'mySqlPassword'=>'xxx',
    'mySqlDataBase'=>'xxx',
    'defaultLanguageId' => '1',
    'tablePrefix' => 'bsp_',
    'refreshTime'=>'2',
    'projectId'=>'1',
    'templateName'=>'layout/default/',
    'defaultPage'=>'home',
    'defaultRights'=>array('0')
);

somit muss ich nur in der index.php(in deinem beispiel wäre es a.php) require 'classes/Defines.php'; einfügen und das wars. Oder ist irgendwas an dieser methode auszusetzen? wenn ja werde ich es ändern

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

somit muss ich nur in der index.php(in deinem beispiel wäre es a.php) require 'classes/Defines.php'; einfügen und das wars. Oder ist irgendwas an dieser methode auszusetzen? wenn ja werde ich es ändern

Und wenn es Leute gibt die direkt eine Unterseite aufrufen? Oder wird jede Anfrage über die "index.php" geleitet, egal welchen link man anklickt? Ersteres ist problematisch weil die Daten dann nicht existieren, bei letzterem wäre die Session unnötig und du kannst es auch in den Global Scope packen.

gepostet vor 14 Jahre, 9 Monate von BlackScorp

naja unterseiten werden bei mir über index.php aufgerufen also index.php?site=xxx

hm.. die session wäre dann ungültig?

das problem ist, __DIRNAME__ ist eine leere konstante desswegen kann ich dein vorschlag von vorhin nicht nehmen(wobei der eigentlich ganz gut ist). habe gegoogled und basename(__FILE__) gefunden jedoch zeigt es mir die gesamte url an

MFG

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von BlackScorp

naja unterseiten werden bei mir über index.php aufgerufen also index.php?site=xxx

hm.. die session wäre dann ungültig?

Nö es würde funktionieren, aber die Einstellungen werden bei jedem Seitenaufruf in die Session gespeichert, was ich unsinnig finde. Also entweder abprüfen, dass die Einstellungen nur gesetzt werden wenn diese noch nicht in der Session existieren (ein Application Scope fehlt PHP dafür ja leider, Memcache wäre auch eine Möglichkeit, aber wenn die Einstellungen hardgecodet vorliegen dürfte es eher nachteilig sein von der Performance) oder in den Global Scope packen bei jeden Seitenaufruf.

Letzteres finde ich schöner, weil die Einstelungen wenig mit der Session eines Benutzers zu tun haben. Also statt $_SESSION lieber $_GLOBALS oder eine ganz normale globale Variable (ich weiss nur grad nicht ob die Daten aus $_REQUEST auch in $_GLOBALS drin sind).

das problem ist, __DIRNAME__ ist eine leere konstante desswegen kann ich dein vorschlag von vorhin nicht nehmen(wobei der eigentlich ganz gut ist). habe gegoogled und basename(__FILE__) gefunden jedoch zeigt es mir die gesamte url an

Es gab ne alte Variante mit "dirname(__FILE__)" glaube ich und es gibt bei ab PHP 5.3 eine neue Konstante die als Alternative genommen wird, aber genau das gleiche enthält.

gepostet vor 14 Jahre, 9 Monate von Amun Ra

Also Konfiguration in die Session da bluten mir die Augen.

Überdenke mal deine ganze Architektur nochmal würde ich sagen... 

gepostet vor 14 Jahre, 9 Monate von BlackScorp

Original von Amun Ra

Also Konfiguration in die Session da bluten mir die Augen.

Überdenke mal deine ganze Architektur nochmal würde ich sagen... 

 bin gerade dabei;)

ich glaube ich werde ganz einfach

define(_mySqlServer_,'localhost');

etc.. nehmen

gepostet vor 14 Jahre, 9 Monate von BlackScorp

habe das jetzt mit $globals gelöst.(vorübergehend) habe so die klasse mit ihren funktionalitäten überflogen und ich finde es sieht sehr gut aus ich werde sowas ähnliches mal nachbauen

MFG

EDIT:

mal so zur verständniss der configure klasse.

also ich brauche eine datei in meinem projekte ordner welche Configure::write(irgendwas); macht. Dann brauche ich eine klasse im core welches mir Configure zur verfügung stellt und die klassen im Core die erstmal Configure::load(dateivomProjekt) lädt und dann mit Configure::load(irgendwas) mir das array ausliest.

Was macht denn write genau? schreibt er den config array in eine datei rein? oder in cashe? weil wenn ich es in eine datei reinschreibe muss ich ja vor jedem schreiben prüfen ob das array element exestiert und wenn er exestiert dann soll er überschrieben werden, sonst einen neuen element anlegen. macht die configure klasse von Cake etwa das so wie ich es beschrieben habe?

gepostet vor 14 Jahre, 9 Monate von knalli

Configure ist nach aussen hin nur ein großer Key/Value-Store, aka eine große Map, aka ein assoziatives Array. Mittels load kannst du natürlich auch machen, die Alternative wäre einfach eine config.php, die (nur) Configure::write(key, value)-Anweisungen hat. Nicht mehr, nicht weniger. Simpel halten.

gepostet vor 14 Jahre, 9 Monate von DrakeL

Original von knalli

Configure ist nach aussen hin nur ein großer Key/Value-Store, aka eine große Map, aka ein assoziatives Array. Mittels load kannst du natürlich auch machen, die Alternative wäre einfach eine config.php, die (nur) Configure::write(key, value)-Anweisungen hat. Nicht mehr, nicht weniger. Simpel halten.

Hört sich nach viel Overhead an wenn dort 100 mal die Methode aufgerufen wird. Falls es auch eine Möglichkeit gibt ein komplettes assoziatives Array zu übergeben ist es wohl sinnvoller. :)

Aber im Endeffekt ist es also wie bei Zend_Registry einfach eine Möglichkeit globale Daten in Klassen gekapselt abzulegen.

gepostet vor 14 Jahre, 9 Monate von knalli

Dann gibt es zwei Möglichkeiten: Entweder das Eingabe-Array wird intern foreach-mäßig verwurschtelt (wo ist da also die Verbesserung) oder aber direkt abgesetzt: das geht aber in PHP auch nur, weil Arrays keine Objekte sind und stellt die Anforderung, dass die interne Struktur nach aussen sowohl verfügbar als auch sichergestellt ist.

gepostet vor 14 Jahre, 8 Monate von DrakeL

Original von knalli

Dann gibt es zwei Möglichkeiten: Entweder das Eingabe-Array wird intern foreach-mäßig verwurschtelt (wo ist da also die Verbesserung) oder aber direkt abgesetzt: das geht aber in PHP auch nur, weil Arrays keine Objekte sind und stellt die Anforderung, dass die interne Struktur nach aussen sowohl verfügbar als auch sichergestellt ist.

"$array1 + $array2" ginge auch. Ob das technisch optimierter umgesetzt ist als eine foreach Schleife mit n Methodenaufrufen/Zuweisungen weiß ich natürlich nicht. :)

gepostet vor 14 Jahre, 8 Monate von knalli

Original von DrakeL

Original von knalli

Dann gibt es zwei Möglichkeiten: Entweder das Eingabe-Array wird intern foreach-mäßig verwurschtelt (wo ist da also die Verbesserung) oder aber direkt abgesetzt: das geht aber in PHP auch nur, weil Arrays keine Objekte sind und stellt die Anforderung, dass die interne Struktur nach aussen sowohl verfügbar als auch sichergestellt ist.

"$array1 + $array2" ginge auch. Ob das technisch optimierter umgesetzt ist als eine foreach Schleife mit n Methodenaufrufen/Zuweisungen weiß ich natürlich nicht. :)

Du hast nicht wirklich verstanden, dass mein Beitrag auf Komponentenarchitektur bzw. vielmehr das Geheimnisprinzip zielte? Und seit wann kann man in PHP denn Arrays addieren? Meinst du einen Merge?

gepostet vor 14 Jahre, 8 Monate von DrakeL

Original von knalli

Du hast nicht wirklich verstanden, dass mein Beitrag auf Komponentenarchitektur bzw. vielmehr das Geheimnisprinzip zielte? Und seit wann kann man in PHP denn Arrays addieren? Meinst du einen Merge?

Es ging doch darum, dass es wohl sinnvoller ist ein Array zu übergeben statt die Methode zum Setzen X mal aufzurufen (allein schon der Übersicht halber, nichtmal so sehr wegen der Performance).

Was das mit dem Geheimnisprinzip zu tun hat keine Ahnung, klär mich mal auf. Für mich ist es von außen ein Geheimnis, ich gebe dem Objekt eine Menge an Eigenschaften zum Setzen. Wie diese gesetzt werden interessiert mich nicht ob durch Mengenoperation oder durch Schleifen.

Und ja eine Addition geht auch bei Arrays, wie lange schon weiß ich nicht, aber auf jeden Fall nicht erst seit PHP 5. Das Array auf der linken Seite wird um alle Key/Value Paare des Arrays der rechten Seite ergänzt, Überschreibbungen finden nicht statt.

Ein Merge hat glaube ich noch andere Effekte wenn Keys schon belegt sind oder sich das Array um ein numerisches Array handelt.

gepostet vor 14 Jahre, 8 Monate von knalli

Okay, dann liegt das an mir: So undurchsichtige Operatoren (was passiert, wenn eins von beiden kein Array ist?) mag mir irgendwie nicht gefallen.. daher muss ich diese Variante wohl (erfolgreich) verdrängt haben. :)

Btw: array_merge überschreibt immer nach links, bspw. $settings = array_merge($defaults, $options). Laut Dokumentation ist dies beim +-Operator genau umgekehrt (erster hat Vorrang), und es wird im Gegensatz zu merge kein Renumbering gemacht. Insofern aber irrelevant, weil wie für einen Key/Value-Store arbeiten.

Es ging doch darum, dass es wohl sinnvoller ist ein Array zu übergeben statt die Methode zum Setzen X mal aufzurufen (allein schon der Übersicht halber, nichtmal so sehr wegen der Performance).

Wegen der Übersicht? So kam das bei mir aber nicht an: Dafür sei gesagt: Klar, warum nicht? Wenn man sich die CakePHP-Api angeguckt hat (um das Beispiel fortzuführen), so ist das Interface für Arrays und/oder Punkt-separierte Strings geeignet. Damit hat man auch das Problem aus der Welt geschafft, was mit verschachtelten Arrays passiert - dies sind nämlich nicht so einfach zu mergen.

Wobei ich es auch diskussionswürdig erhalte, ob man wirklich einen kompletten Configurationsdump per Array einladen sollte, nur weil es kürzer ist. Dokumentation, Begründung?

Anders sieht es aus, wenn es um die Performanz ging (und das hatte ich so verstanden): Ich habe das so verstanden, dass deswegen ein Array genutzt werden soll, weil man das ja "prima" intern weiter verwenden kann. Und das widerspricht eben dem so genannten Geheimnisprinzip: Der Aussenstehende soll keine Kenntnisse zum Innenleben haben.

Wenn es im Endeffekt nur um die popeiligen Aufrufe der Methode geht (meine Güte, daran wird keine Applikation zu Grunde gehen), dann kann man dies ja zur Laufzeit immer noch schön serialisieren/cachen.. unabhängig davon, wie man jetzt seine Konfiguration macht. Nur warum soll die Api darunter leiden? Das ist total triviales Szenario (OO, statische/dynamische Konfiguration), aber ein gutes Beispiel, wie die seltsamsten Implementierungen zu Stande kommen.

gepostet vor 14 Jahre, 8 Monate von DrakeL

Original von knalli

Anders sieht es aus, wenn es um die Performanz ging (und das hatte ich so verstanden): Ich habe das so verstanden, dass deswegen ein Array genutzt werden soll, weil man das ja "prima" intern weiter verwenden kann. Und das widerspricht eben dem so genannten Geheimnisprinzip: Der Aussenstehende soll keine Kenntnisse zum Innenleben haben.

PHP:

//Variante a)
public function setDatas(array $datas)
{
$this->datas += $datas;
}
$example->setDatas(array('a' => 'b', 'c' => 'd'));
//Variante b)
public function setDatas(array $datas)
{
foreach ($datas as $key => $value)
$this->datas[$key] = $value;
}
$example->setDatas(array('a' => 'b', 'c' => 'd'));

Wo hier jetzt das Geheimnisprinzip verletzt oder was daran seltsam sein sollte ist mir ein Rätsel... Aber da die Implementierung des Setzens der Einstellungen eigentlich irrelevant ist welche Variante genommen wird würde ich sagen wir lassen die Diskussion auf sich beruhen bzw. verschieben es auf PM. :)

Ob Addition der Mengen oder einem Merge ist bei assoziativen Arrays egal gebe ich dir Recht. Aber man muss halt immer aufpassen ob es wirklich ein solches ist oder doch ein assoziatives Array was aber Nummern als Keys hat. Daher finde ich die Addition angenehmer, da sie keine Fallunterscheidungen hat.

gepostet vor 14 Jahre, 8 Monate von knalli

Wo hier jetzt das Geheimnisprinzip verletzt oder was daran seltsam sein sollte ist mir ein Rätsel... 

Wie gesagt: Meine "Kritik" bezog sich auf den Punkt Performance und die - von mir implizite - Begründung, das durch einen Array-Parameter zu nutzen. Ohne Frage ist dein erstes Beispiel schneller als das zweite..

Das Geheimnisprinzip wäre verletzt, wenn der Aufrufer "weiß", das er in das interne Array schreiben würde (deswegen das Array als Argument). Es ging mir nicht um die Sache selbst, sondern um die Intention bzw. den Entstehungsverlauf dieser Idee.

Aber Recht hast du auch: Es war einmal ein Thread, der ging um 'ne Autoloaderklasse..

Auf diese Diskussion antworten