Ankündigung

Einklappen
Keine Ankündigung bisher.

class not found singleton

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • class not found singleton

    Hi,
    ich hab grad meine DB Connection ausgelagert als singleton, bin aber in der oop in php noch nicht so geübt. Deswegen stoße ich auf folgendes Problem:

    habe eine class config:

    PHP-Code:
    namespace database;

    class 
    Config
    {
        static 
    $confArray;

        public static function 
    read($name)
        {
            return 
    self::$confArray[$name];
        }

        public static function 
    write($name$value)
        {
            
    self::$confArray[$name] = $value;
        }

    }

    // db
    Config::write('db.host''127.0.0.1');
    Config::write('db.port''3306');
    Config::write('db.basename''testdb');
    Config::write('db.user''root');
    Config::write('db.password'''); 

    Eine Class Core:
    PHP-Code:
    namespace database;


    class 
    Core
    {
        public 
    $dbh// handle of the db connexion
        
    private static $instance;

        private function 
    __construct()
        {
            
    // building data source name from config
            
    $dsn 'mysql:host=' Config::read('db.host') .
                
    ';dbname='    Config::read('db.basename') .
                
    ';port='      Config::read('db.port') .
                
    ';connect_timeout=15';
            
    // getting DB user from config
            
    $user Config::read('db.user');
            
    // getting DB password from config
            
    $password Config::read('db.password');

            
    $this->dbh = new PDO($dsn$user$password);
        }

        public static function 
    getInstance()
        {
            if (!isset(
    self::$instance))
            {
                
    $object __CLASS__;
                
    self::$instance = new $object;
            }
            return 
    self::$instance;
        }

        
    // others global functions

    Und eine Klasse class_Account, in wessen Konstruktor ich die Instanz Core erzeugen und nutzen möchte:

    PHP-Code:
    namespace account;
    use \
    database;

    class 
    class_Account {

       
    // Konstruktor
        
    function __construct() {
       
    // ...
           
    $core =  Core::getInstance();
            
    $stmt $core->dbh->prepare($sql);
            
    $stmt->bindParam(":id",$this->accountIdPDO::PARAM_INT);
            
    $stmt->execute();
       }

    Ordnerstruktur ist die Folgende:

    PHP-Code:
    classes
        
    -> account
           
    ->-> class_Account.php
        
    -> database
           
    ->-> Config.php
           
    ->-> Core.php 
    Fehler:
    Fatal error: Class 'account\Core' not found

    in der Zeile:
    PHP-Code:
    $core =  Core::getInstance(); 
    Regards,
    Sakron
    No Sacrifice , no Glory--


  • #2
    "database" ist ein Namespace, den kannst du nicht einfach mit "use" importieren. (Codeblock #3) Du siehst ja, das die Klasse im falschen Namespace gesucht wird (account statt database).
    Sieh dir nochmal das Importieren aus Namespaces an: http://php.net/manual/de/language.na....importing.php

    Kommentar


    • #3
      hab da alles durchprobiert nun, kriege immer wieder die Meldung - entweder:
      account\Core not found , oder database\Core not found , oder Core not found .. -.*

      Letzter Versuch war:
      PHP-Code:
      use database/Core as Class1// hier statt slash ein backslash, das kickt es mir aber bei dem post immer raus. 
      und instanziierung:

      PHP-Code:
      $core =  Class1::getInstance(); 
      Fehler: : Class 'database\Core' not found
      No Sacrifice , no Glory--

      Kommentar


      • #4
        Das du dennoch ein include bzw. einen Autoloader brauchst ist dir aber schon bewusst, oder? account\Core ist falsch, weil dort die Klasse ja nicht liegt. database\Core ist richtig, und wenn die Klasse dann immer noch nicht gefunden wird, dann fehlt da eben etwas.

        Beispiel:
        core.php
        PHP-Code:
        <?php
        namespace database;

        class 
        Core {
            public static function 
        init() {
                echo 
        "ok";
            }
        }
        index.php
        Code:
        <?php
        namespace foo;
        use database\Core;
        
        require("core.php");
        
        Core::init();

        Kommentar


        • #5
          Ja, natürlich hab ich um die Uhrzeit vergessen.
          Ist das so der effektivste Weg mit dem Autoloader ?

          PHP-Code:
          function generierterAutoloader($klassenname) {
            static 
          $klassen = array ('Foo' => 'classes/Helden/Foo.php',
                                     
          'Kastanie' => 'classes/Baeume/Kastanie.php',
                                     
          'AlternativerDateiname' => 'classes/alternativ.class.php');
           
            if (!isset(
          $klassen[$klassenname])) return false;
           
            require_once 
          $klassen[$klassenname];

          Quelle: http://de.wikibooks.org/wiki/Website...P:_Autoloading

          Oder ist die hier besser:

          PHP-Code:
          namespace org\wikibooks\de\PHP;
           
          function 
          pfadImNamespace($klassenname) {
            if (
          !== strpos($klassenname__NAMESPACE__)) {
              
          // Dieser Autoloader ist für diesen Namespace nicht zuständig
              
          return false;
            }
           
            
          $sub_namespace substr($klassennamestrlen(__NAMESPACE__));
           
            
          $teile explode('\\'$sub_namespace);
           
            
          $pfad implode(DIRECTORY_SEPARATOR$teile) . '.php';
           
            if (
          file_exists($pfad)) {
              require_once 
          $pfad;
            } else {
              return 
          false;
            }

          Edit:
          Muss ich den dann überall neu anlegen oder wie läuft das?
          No Sacrifice , no Glory--

          Kommentar


          • #6
            So, ich habe nun folgendes angelegt:

            Verzeichnisstruktur nochmals:
            PHP-Code:
            classes
               
            -> account
                  
            ->-> class_Account.php
               
            -> database
                  
            ->-> Config.php
                  
            ->-> Core.php
            -> NamespaceAutoloader.php 
            Der NamespaceAutoloader ist direkt im Verzeichnis "classes". Er sieht folgendermaßen aus:
            PHP-Code:
            class NamespaceAutoloader {
                const 
            BASE_DIR __DIR__;
                const 
            FILE_EXTENSION '.php';

                public static function 
            autoload($className) {
                    
            $className str_replace('\\'DIRECTORY_SEPARATOR$className);
                    
            $filePath NamespaceAutoloader::BASE_DIR DIRECTORY_SEPARATOR $className NamespaceAutoloader::FILE_EXTENSION;
                    if (
            file_exists($filePath)) {
                        
            // Datei zur Klasse includen, falls sie denn existiert
                        
            include_once($filePath);
                    }
                }

            In meiner Klasse class_Account rufe ich ihn nun so auf:

            PHP-Code:
            namespace account;
            use 
            database\Core;

            // Autoloader includen und registrieren
            include_once($_SERVER['DOCUMENT_ROOT']. "/test/de/classes/NamespaceAutoloader.php");
            spl_autoload_register(array('NamespaceAutoloader''autoload')); 
            Jetzt hab ich ein paar Fragen:
            1) Ist das so korrekt, oder keine gute Lösung ?
            2) Er includet mir alle Dateien bis auf die Klasse "PDO", die findet er nicht. Diese ist aber in der php ini enabled und außerhalb der Klasse (in einer normalen .php Datei) findet er sie wieder.
            (Fatal error: Class 'database\PDO' not found in Core.php)
            3) Wieso muss ich den Autoloader mit einem absoluten Pfad angeben und weshalb findet er ihn nicht mit:
            PHP-Code:
            include_once("../NamespaceAutoloader.php"); 
            ?
            4) Wo muss ich überall den Autoloader registrieren?

            Regards.
            No Sacrifice , no Glory--

            Kommentar


            • #7
              Was ist schon eine gute Lösung? Man ist eifnach dazu übergegangen, gewissen Konventionen umzusetzen, sodass man eben nicht jede Klasse einzeln einbinden muss, sondern der Autoloader selber über den Namespace den Pfad zur Klasse(ndatei) sozusagen erraten kann. Das ist z.B hier definiert: http://www.php-fig.org/psr/psr-4/

              Nen Autoloader registierst du im Normalfall genau einmal. Irgendwo im bootstrap Vorgang. Es sollte so mit das erste sein, was deine Applikation macht

              Kommentar


              • #8
                Am besten gewöhnst du dich gleich an den PSR-4 Standard und nutzt auch gleich den Composer-Autoloader, welcher mit PSR-4 zurecht kommt. Beim PSR-4 bildest du den Namespace auf eine Ordnerstruktur ab, allerdings ist beim PSR-4 hinzugekommen, dass du nichtmehr den kompletten Namespace nachbauen musst.

                Beispiel:
                Du hast eine Klasse \Sakron\database\Core wobei Sakron für den "Vendor" steht, dann könntest du mit PSR-4 den Namespace \Sakron registrieren und auf "classes/" zeigen lassen. Der endgültige Pfad zur Datei müsste dann "classes/database/Core.php" sein, nicht mehr wie beim PSR-2 wo er noch classes/Sakron/database/Core.php hätte lauten müssen.


                Um noch deine Fragen zu Beantworten:
                #1: Das wäre PSR-2, siehe oben

                #2: database\PDO gibt es ja auch nicht. Entweder vermerkst du PDO in den uses
                PHP-Code:
                use PDO
                oder du nimmst den Absoluten Namespace
                PHP-Code:
                $pdo = \PDO();
                      ^
                      |
                    
                //Hier sollte ein Backslash sein,
                    //welches php.de mir freundlicherweise entfernt... 
                #3: Bist im falschen Working-Dir

                #4: Im Bootstrap
                Zitat von nikosch
                Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                Kommentar


                • #9
                  Danke für eure Hilfe
                  Das mit dem Composer mache ich, sobald ich das hier fertig habe (Zum Verständnis möchte ich den AutoLoader erstmal zum laufen kriegen).

                  Nochmal zum Bootstrap:

                  Ich registriere in der äußersten index.php (die auf den de/ Ordner umleitet) den Autoloader mit:

                  PHP-Code:
                  // Autoloader includen und registrieren
                  include_once($_SERVER['DOCUMENT_ROOT']. "/test/de/classes/NamespaceAutoloader.php");
                  spl_autoload_register(array('NamespaceAutoloader''autoload')); 
                  Ist das so richtig ? Was muss dann in die Klasse class_Account.php noch rein? Da findet er nämlich die Klasse core wieder nicht, sprich der Autoloader ist irgendwie nicht richtig registriert worden von mir.
                  Regards
                  No Sacrifice , no Glory--

                  Kommentar


                  • #10
                    Zitat von Sakron Beitrag anzeigen
                    Was muss dann in die Klasse class_Account.php noch rein? Da findet er nämlich die Klasse core wieder nicht, sprich der Autoloader ist irgendwie nicht richtig registriert worden von mir.
                    Regards
                    Genauer? Fehlermeldung und Codezeile bitte.
                    Zitat von nikosch
                    Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                    Kommentar


                    • #11
                      Also ich habe in der äußeren index.php meinen Autoloader registriert mit:

                      PHP-Code:
                      // Autoloader includen und registrieren
                      include_once($_SERVER['DOCUMENT_ROOT']. "/test/de/classes/NamespaceAutoloader.php");
                      spl_autoload_register(array('NamespaceAutoloader''autoload')); 
                      (Das glaube ich ist schonmal nicht der richtige "bootstrap", denn wenn jemand die url direkt in die Adresszeile eingibt wird der Autoloader nie registriert)

                      Aus meiner class_Account.php habe ich den Autoloader nun rausgestrichen und über der Klassendefinition steht nurnoch:

                      PHP-Code:
                      namespace account;
                      use 
                      database\Core;
                      use 
                      PDO;

                      class 
                      class_Account
                      Fehler tritt hier auf:
                      PHP-Code:
                      function __construct() {
                      $core =  Core::getInstance();

                      Fatal error: Class 'database\Core' not found

                      Regards
                      No Sacrifice , no Glory--

                      Kommentar


                      • #12
                        Dann mach mal ein paar Debug-Ausgaben im autoloader, vorallem welche Klassen dem übergeben werden und welche Datei dann gesucht wird.
                        Zitat von nikosch
                        Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                        Kommentar


                        • #13
                          Der geht garnie in die Methode autoload() rein, den Autoloader registriert er, aber aufgerufen wird die autoload Methode nie.

                          Hab ich in der class_Account.php was vergessen? Und in welchem File registriere ich denn den autoloader? Die index.php kann ja übersprungen werden.

                          Edit:
                          Wenn ich das direkt in die class_Account.php einbinde dann gibt er mir die richtigen Pfade aus..
                          No Sacrifice , no Glory--

                          Kommentar


                          • #14
                            Wieso kann die index.php übersprungen werden? Den Autoloader bindest du in einer Bootstrap-Datei ein, welche auf jeden Fall bei jedem Request einmalig ausgeführt wird.
                            Zitat von nikosch
                            Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                            Kommentar


                            • #15
                              Ahh, ok jetzt verstehe ich. Gut sorry ich hatte das so verstanden, dass man den Auto loader nur einmal pro session registrieren muss und nicht bei jedem request.

                              Zur Index: wenn jmd manuell die URL eingibt und die Index somit überspringt wird die nicht aufgerufen.
                              No Sacrifice , no Glory--

                              Kommentar

                              Lädt...
                              X