Autoload Problem

Hallo zusammen! *Überschrift sollte Autoload Frage heißen *

Ich beschäftige mich eigentlich nicht mit OOP (werde aber im laufe der Zeit es zielstrebig lernen). Jetzt wollte ich meine Verzeichnisse und die Include Dateien schützen mit Autoloader.

Ich habe diese 2 Scripts gefunden:

autoloader.php

[PHP]<?php

/**

  • Defines the methods any actual locators must implement
  • @package Autoloader
  • @author Chris Corbyn
    /
    interface Locator
    {
    /
    *
    • Inform of whether or not the given class can be found
    • @param string class
    • @return bool
      /
      public function canLocate($class);
      /
      *
    • Get the path to the class
    • @param string class
    • @return string
      */
      public function getPath($class);
      }

/**

  • The main service locator.

  • Uses loosely coupled locators in order to operate

  • @package Autoloader

  • @author Chris Corbyn
    /
    class Autoloader
    {
    /
    *

    • Contains any attached service locators
    • @var array Locator
      */
      protected static $locators = array();

    /**

    • Attach a new type of locator
    • @param object Locator
    • @param string key
      /
      public static function attach(Locator $locator, $key)
      {
      self::$locators[$key] = $locator;
      }
      /
      *
    • Remove a locator that’s been added
    • @param string key
    • @return bool
      /
      public static function drop($key)
      {
      if (self::isActive($key))
      {
      unset(self::$locators[$key]);
      return true;
      }
      else return false;
      }
      /
      *
    • Check if a locator is currently loaded
    • @param string key
    • @return bool
      /
      public static function isActive($key)
      {
      return array_key_exists($key, self::$locators);
      }
      /
      *
    • Load in the required service by asking all service locators
    • @param string class
      */
      public static function load($class)
      {
      foreach (self::$locators as $key => $obj)
      {
      if ($obj->canLocate($class))
      {
      require_once $obj->getPath($class);
      if (class_exists($class)) return;
      }
      }
      }
      }

/**

  • PHPs default __autoload
  • Just a wrapper to Autoloader::load()
  • @package Autoloader
  • @author Chris Corbyn
  • @param string class
    */
    function __autoload($class)
    {
    Autoloader::load($class);
    }

?>[/PHP]

Locater.php

[PHP]
class PearLocator implements Locator
{
protected $base = ‚.‘;

public function __construct($directory='.')
{
   $this->base = (string) $directory;
}

public function canLocate($class)
{
   $path = $this->getPath($class);
    if (file_exists($path)) return true;
    else return false;
}

public function getPath($class)
{
    return $this->base . '/' . str_replace('_', '/', $class) . '.php';
}

}
[/PHP]

Nehmen wir an ich möchte in meiner Index.php Datei jetzt Sachen aufrufen, wie würde ich es dann machen müssen laut dem Code; und was müsste ich beachten?
Oder empfehlt ihr mir eine andere Methode es anders zu machen?

Frage zu OOP:
Wie es ja schon oben steht, würde ich auch OOP bzw. will ich OOP lernen. Könnt ihr mir was empfehlen (Seiten,Bücher etc)? Ich denke bestimmt das hier welche gute OOP Kenntnisse Haben und bestimmt wissen was Ihr mir zu empfehlen habt. Großes Dankeschön an die, die mir helfen können!

Dieses Autoload-Script ist schon etwas veraltet. Zum automatischen Laden von Klassen ist momentan PSR-4 Standard: http://www.php-fig.org/psr/psr-4/
Abgesehen davon macht es kaum Sinn sich mit Autoload zu beschäftigen wenn Du in Sachen OOP noch am Anfang stehst. Als Buch wäre wohl PHP Design Patterns empfehlenswert. Die Elemente von OOP (wie Classes & Interfaces) werden kurz erläutert, der Fokus liegt aber auf Softwareentwicklung mit Hilfe von OOP und Entwurfsmustern.

Auch wenn jene Autoloader-Klasse die du da ausgegraben hast möglicherweise das tut was sie soll, rate ich dir dazu - wie der Vorposter schon geschrieben hat - dich mit PSR-4 vertraut zu machen, da sich diese Empfehlung (PSR = PHP Standards Recommendations) in den größeren Frameworks (zb. Symfony, Laravel) und auch bei Composer durchgesetzt hat.

Eine Beispiel-Implementation eines PSR-4 konformen Autoloaders findest du hier: http://www.php-fig.org/psr/psr-4/examples/

Was nun deine Frage bzgl. „OOP erlernen“ angeht: OOP erlernen ist - meiner Erfahrung nach - kein Prozess der bei A anfängt und bei Z aufhört. Gefühlt wiederholt sich dieser Prozess mit jedem neuem Stück Code den man fabriziert, wobei ich jedes mal auf’s neue die Clean Code Prinzipien gedanklich durchgehe und auf meinen Code anwende. Das vom Vorposter vorgeschlagene Buch ist eine gute Referenz für Problemlösungsstrateigien die bei OOP auftreten, aber OOP umfasst - meiner Meinung nach - mehr als die blanke Anwendung von akzeptierten Design Patterns. Bevor du eventuell zum vorgeschlagenem Buch greifst, kannst du dir auch die Online-Variante davon ansehen: http://designpatternsphp.readthedocs.org/en/latest/

Auch wenn ich jetzt Gefahr laufe was falsches zu sagen, halte ich folgende Dinge in Bezug auf OOP für wichtig:

  1. Wiederhole deinen Code nicht (DRY = Don’t Repeat Yourself)
  2. Halte deinen Code möglichst einfach (KISS = Keep It simple, stupid)
  3. Trenne deinen Code möglichst klar ab (SoC = Separation Of Concerns & SRP = Single Responsibility Principle)
  4. Halte Abhängigkeiten in deinem Code möglichst klein (DI = Dependency Injection & IoC = Inversion Of Control)
  5. Verschwende keine Zeit auf Dinge die du nicht brauchst (YAGNI = You Ain’t Gonna Need It)

Die detailierte Ausführung dieser - meiner Meinung nach - wichtigen Punkte würde hier in einer Wall-Of-Text ausarten. Deshalb habe ich die englischen Schlagwörter dahinter geschrieben und ich empfehle dir selber nach Beispielen diesbezüglich zu googlen. Wenn du weitere Fragen dazu hast, dann nur zu.

Grüße

Danke für die ausführliche Erklärung und die Links noch dazu. Ich habe mich im Code rumgeschaut. Natürlich erstmal bisschen Kopfschmerzen bekommen, aber grob habe ich es verstanden was damit gemeint ist. Paar Fragen hätte ich dazu falls ihr die Beantworten möchtet.

  1. Im folgenden Link ist ein Closure Example und Class Example. Falls ich jetzt meine Datenbank Verbindung schützen möchte(Db_con.inc.php), welches Beispiel sollte ich nehmen?

  2. Class Example Namespace:
    Wozu dient Namespace? Ich meine im Code ist ein Array mit den angegebenen Pfaden und Dateien. Wieso muss er jetzt auch noch namespace zu fügen?

[PHP]
$this->loader->setFiles(array(
‚/vendor/foo.bar/src/ClassName.php‘,
‚/vendor/foo.bar/src/DoomClassName.php‘,
‚/vendor/foo.bar/tests/ClassNameTest.php‘,
‚/vendor/foo.bardoom/src/ClassName.php‘,
‚/vendor/foo.bar.baz.dib/src/ClassName.php‘,
‚/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php‘,
));

    $this->loader->addNamespace(
        'Foo\Bar',
        '/vendor/foo.bar/src'
    );

etc.

[/PHP]

  1. Wenn ich das Class Example jetzt nehmen würde, müsste ich theoretisch die Class Example kopieren und in eine Datei.php abspeichern. Und dann kommt der Test dran (Unit Test) wie es da steht. Kommt es auch zusätzlich in eine Datei und muss ich dann nur noch die angegebenen Pfade ändern die da stehen?

  2. Eine ClassName.php muss ja vorhanden sein. Wie mache ich es das ich den Classenname definiere ? Das da z.B nicht steht Class not Found als Fehlermeldung. Den richtigen Classennamen eingeben weiß ich aber wo muss ich es im Code definieren bzw. hinschreiben?

hoffe es ist nicht zu viel nur es verbreitet bisschen Kopfschmerzen und man kann es ja schlecht von heute auf morgen lernen OOP vollständig lernen und verstehen.

PS: zum Buch Design Pattern , ist es nicht etwas veraltet(2007-2009)?

Moin Moin

Zu Frage Nr.1:

Zum Autoloaden von Konfigurations-Daten ist ein solcher PSR-4 Autoloader nicht gedacht. Dieser bezieht sich lediglich auf die automatische Einbindung von Klassen-Dateien. Deine DB-Konfigurationsdatei ziehst du dir ganz regulär zb. per require_once() rein.

Grundsätzlich ist eine Konfigurations-Datei in Form eines PHP-Arrays rellativ sicher. Eine andere Alternative sind ENV-Variablen, aber das ginge hier vermutlich erstmal zu weit. Der Vollständigkeit halber erwähne ich noch die Trennung zwischen öffentlichen Dateien (HTML, CSS, JS) von den Anwendungsdateien (PHP). Zu gut Deutsch heißt dass, dass Domain xyz.loc zb. auf das Verzeichnis /htdocs/public zeigen sollte, während der ganze PHP-Kram innerhalb von zb. /htdocs/app liegen sollte.

Zu Frage Nr.2:

Ein Namespace ist - wie man es ins Deutsche übersetzen würde - ein Namensraum. Dieser spielt zb. dann eine Rolle, wenn mehrere Personen Quellcode zu einem Projekt beisteuern, aber nicht unbedingt bis in’s kleinste Detail die genaue Implementierung kennen. Entwickler A nutzt für seine Klassen zb. den Namespace „DeveloperA“ und Entwickler B nutzt den Namespace „DeveloperB“. Beide können nun zb. eine Klasse schreiben, die „User“ heißt, ohne dass sich beide Klassen in die Quere kommen.

Am ehesten kann man das vielleicht mit einer Postleitzahl vergleichen. In einer Stadt kann es durchaus mehrere Personen mit Nachnamen „Müller“ geben, aber durch die Postleitzahl und genaue Addresse (ließ Namensraum) wird sichergestellt dass der richtige „Müller“ gemeint ist.

Einen Namespace musst du übrigens nicht zwangsweise angeben. Im Closure-Beispiel des PSR-4 Autoloaders (meiner Meinung nach einfacher zu verstehen) kannst du die $prefix-Variable auch auf leer setzen. Allerdings um sich die Praxis mit den Namespaces gleich anzugewöhnen, rate ich nicht unbedingt dazu. Allgemein definiert wird ein Namespace zb. so:

namespace MyProject\Core;

class App {

}

Ganz rudimentär angewendet mit Hilfe des PSR-4 Closure Autoloaders ($prefix auf „MyProject\“ gesetzt) würde das zb. so aussehen:

/htdocs/public/index.php

// Autoloader unter /htdocs/app
require_once('../app/autoload.php');

// Datei App.php unter /htdocs/app/src/Core
$myClass = new MyProject\Core\App;

Um genauer zu untersuchen was der Autoloader zu laden versucht, kannste ja innerhalb der Closure-Funktion mal die Variable $file mit print_r() oder var_dump() ausgeben lassen.

Zu Frage Nr.3:

Auch wenn ich mit folgender Aussage vermutlich anderen Entwicklern hier auf die Füße trete: Den Unit-Test brauchst du in dem Fall nicht mit berücksichtigen.

Unit-Tests sind dazu gedacht, Klassen und deren Methoden-Aufrufe mit möglichst allen erdenkbaren Kombinationen automatisch durchzutesten, BEVOR diese in eine Live-Umgebung übertragen werden, um sicherzustellen dass im Live-Betrieb möglichst keine unerwarteten Dinge passieren. Bei größeren Anwendungen, an denen auch mal höhrere Geldbeträge kleben, sind Unit-Tests Gang und Gebe.

Aber im privatem Umfeld, allen voran wenn es gerade um das erlernen von OOP geht, rechnet sich - meiner Meinung nach - der Aufwand in Relation zum Nutzen nicht. Wenn es dir persönlich wichtig ist, dann kannst du natürlich Unit-Tests machen. Aber dafür bin ich kein Experte und da können dir sicherlich andere Nutzer hier mehr weiterhelfen, wenn es denn dein Anspruch ist. Wichtig ist erstmal dass du zumindest weißt, dass es sowas gibt.

Zu Frage Nr.4:

Siehe dazu das Codebeispiel was ich gepostet habe.

PS: zum Buch Design Pattern , ist es nicht etwas veraltet(2007-2009)?

Ungeachtet des Alters des Buches sind Design Patterns Standardlösungen zu Standardproblemen die sich über die Jahre kaum verändert haben. Die Implementationen der einzelnen Patterns mögen sich - mit neueren Möglichkeiten von PHP - in heutigen Zeiten etwas geändert haben (deshalb auch der Link zu der Website mit den Design Patterns), aber der Grundansatz ist der Gleiche geblieben.

Grüße und angenehme Nachtruhe

Vielen Dank für die ausführliche Beschreibung. Nicht alle machen sich so eine Mühe! :slight_smile:
Ich habe es jetzt grob verstanden und versuche meine OOP-Kenntnisse mit Büchern etc. zu stärken.
Falls ich doch irgendwann am zweifeln bin oder Fragen habe, würde ich mich noch bei einer Hilfe hier melden.