Dependency Injection

Psychomentis

Mitglied
Ich befasse mich im moment mit OOP und bin dabei auf Dependency Injection gestoßen doch leider verstehe ich das nicht so ganz...
Kann mir jemand dabei helfen? z.B. Tutorials, usw...
Mein Ziel ist es eine Hauptklasse zu schreiben die einen Autoloader besitzt und gleich alle benötigten Klassen einzubinden und zu initalisieren.
Am Ende will ich den Code wie im folgenden Beispiel verwenden.
PHP:
$core->lang->get("ERROR_INVALID_USERNAME");
$core->database->query("SELECT * FROM `users` WHERE `user_id` = '1'");
$core->security->isAuthorized('a', true);
...

Über jede Hilfe freue ich mich sehr.
Vielen Dank im vorraus!
MfG
Psychomentis
 
Den Sarkasmus kann man sich auch sparen. Es geht darum das ich es nicht verstehe, nicht dass ich nichts gefunden habe. Ich habe das PHP Manual gelesen, Google bis Seite 20 durchforstet aber habe immer noch probleme das zu verstehen... zu mal sehe ich da auch immer 3 verschiedene methoden von DI.
  • Constructor Injection
  • Setter Injection
  • Property Injection
  1. Wo liegen die Vorteile?
  2. Welche Bediengungen müssen erfüllt sein?
  3. Muss man in der Hauptklasse Variablen zur Verfügung stellen für jede einzelne Klasse?
  4. Wird die Klasse auch gleich initalisiert?
  5. Wie funktioniert DI in kombination mit Autoload?
  6. Gibt es Grundsätze die zu beachten sind?
Das ist nur ein kleiner Ausschnitt der Frage die ich mir noch stelle.
Meine Hauptklasse sieht im moment so aus:
PHP:
<?php
class Core
{
  protected $services = array();


  public function __constructor()
  {
  }


  public function autoload($class)
  {
    $file = strtolower($class).'.php';
    if(!file_exists($file) || !is_readable($file))
    {
      throw new LogicException(sprintf("%s does not exist or is not readable",$file));
    }

    return include_once($file);
  }


  public function __set($key, $value)
  {
    self::$services[$key] = $value;
  }


  public function __get($key)
  {
    if(!array_key_exists($key, self::$services))
    {
      throw new InvalidArgumentException(sprintf("%s couln´t found in services!",$key));
    }

    return is_callable(self::$services[$key]) ? self::$services[$key]($this) : self::$services[$key];
  }
}
 
Den Sarkasmus kann man sich auch sparen. Es geht darum das ich es nicht verstehe, nicht dass ich nichts gefunden habe. Ich habe das PHP Manual gelesen, Google bis Seite 20 durchforstet aber habe immer noch probleme das zu verstehen... zu mal sehe ich da auch immer 3 verschiedene methoden von DI.
  • Constructor Injection
  • Setter Injection
  • Property Injection
  1. Wo liegen die Vorteile?
  2. Welche Bediengungen müssen erfüllt sein?
  3. Muss man in der Hauptklasse Variablen zur Verfügung stellen für jede einzelne Klasse?
  4. Wird die Klasse auch gleich initalisiert?
  5. Wie funktioniert DI in kombination mit Autoload?
  6. Gibt es Grundsätze die zu beachten sind?
Das ist nur ein kleiner Ausschnitt der Frage die ich mir noch stelle.
Meine Hauptklasse sieht im moment so aus:
PHP:
<?php
class Core
{
  protected $services = array();


  public function __constructor()
  {
  }


  public function autoload($class)
  {
    $file = strtolower($class).'.php';
    if(!file_exists($file) || !is_readable($file))
    {
      throw new LogicException(sprintf("%s does not exist or is not readable",$file));
    }

    return include_once($file);
  }


  public function __set($key, $value)
  {
    self::$services[$key] = $value;
  }


  public function __get($key)
  {
    if(!array_key_exists($key, self::$services))
    {
      throw new InvalidArgumentException(sprintf("%s couln´t found in services!",$key));
    }

    return is_callable(self::$services[$key]) ? self::$services[$key]($this) : self::$services[$key];
  }
}

zu 4. Nein. Die Klasse müsstest Du schon selber initialisieren ($foo = new Core();)
zu 5. Du müsstest die Klasse samt autoload-Methode per spl_autoload_register() noch registrieren
PHP:
public function __constructor() 
{
    spl_autoload_register( array( $this, 'autoload' ) ); 
}

Damit wird die autoload-Methode beim erstellen der Instanz sofort registriert.

Gruß
 
Ok, ist es sinnvoll die Klasse in der Autoload funktion zu initialisieren?

Nein. Die Core-Klasse musst Du dann schon von Hand initialisieren da sie ja erst die autoload-Methode definiert.

Da mich deine Klasse schon sehr an eine Registryklasse erinnert würde ich evtl. sogar darüber nachdenken ein Singleton-Entwurfsmuster zu verwenden da es meiner Meinung nach keinen Sinn macht die Klasse mehr als einmal zu instanzieren. Wobei ich da nicht genau weiß ob das mit spl_autoload_register() dann noch funktioniert. Müsstest Du mal testen und ein Feedback geben.

Singleton-Möglichkeit:
PHP:
class Core
{
    // statische Variablen (ohne Objekt aufrufbar)
    private static $instance = null; // Speichert die Instanz der Klasse

    /* ... */

    /**
     * Der Konstruktor.
     * 
     * @access <code>private</code> Instanzieren nur innerhalb der Klasse moeglich
     * @return <code>void</code> gibt nichts zurueck
     */
    public function __constructor() 
    {
        // registrieren der autoload-Methode
        spl_autoload_register( 'Core::getInstance()->autoload' );
        /* ganz ehrlich, in dieser Form habe ich das noch nicht getestet */
    }

    /**
     * Die <code>getInstance</code>-Methode des Singleton-Pattern.
     * Die Methode ist <code>statisch</code> (ohne Objekt aufrufbar).
     * Da der Konstruktor <code>private</code> ist, kann nur hier ein
     * Objekt der Klasse erstellt oder, wenn schon ein Objekt existiert,
     * geladen werden.
     * 
     * @return <code>object</code> gibt das Objekt der Klasse zurueck
     */
    public static function getInstance()
    {
        // wenn '$instance' noch auf 'null' steht
        if ( empty( self::$instance ) ) {
            // wird einmalig ein Objekt dieser Klasse erzeugt
            self::$instance = new self();
        }

        // gibt das Objekt der Klasse zurueck
        return self::$instance;
    }

    /* ... */
}

$core = Core::getInstance(); // stellt sicher, dass autload sofort verfuegbar ist

In deinen anderen Klassen kannst Du dir ja z.B. eine getter-Methode bauen:
PHP:
private function getCore()
{
    return Core::getInstance();
}

Zugriff innerhalb der Klassen auf die Variablen von Core dann so:
PHP:
$this->getCore()->vari = 'was auch immer';
echo $this->getCore()->vari;

Ich hoffe das hilft etwas.

Gruß
 
Wenn ich das jetzt richtig verstanden habe gibst du die Core Klasse an die anderen Klassen weiter richtig?
Ich wollte die anderen Klassen wie z.B. (Template, Language, usw.) in die Core intigrieren.
Aber diese richtung ist auch nicht schlecht wenn ich noch eine Session Klasse mit Datenbank anbindung hinzufüge.
 
In einem MVC könntest Du die Klasse natürlich auch nutzen um die anderen Klassen in der Viewklasse zu registrieren. Ich würde mal behaupten es geht in beiden Richtungen. :)

Gruß
 
Zurück