php.de

Zurück   php.de > Webentwicklung > PHP-Fortgeschrittene

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Bewertung: Bewertung: 1 Stimmen, 5,00 durchschnittlich.
Alt 10.06.2011, 20:44  
Benutzer
 
Registriert seit: 07.08.2009
Beiträge: 94
PHP-Kenntnisse:
Anfänger
Anyone befindet sich auf einem aufstrebenden Ast
Standard Dependency Injection Container

Guten Abend,

ich befasse mich zurzeit mit einem Container für die Injizierung für Abhängigkeiten. Ich muss dazu leider gestehen, dass ich wohl die Vorgehensweise der Implementierung, nicht jedoch den Sinn bzw. den Nutzen eines solchen Containers verinnerlicht habe. Hierzu möchte ich euch ein kleines - fiktives - Beispiel zeigen, welches meinen Gedankengang hoffentlich verdeutlicht.

PHP-Code:
class User {
    private 
$db;

    public function 
__construct($db) {
         
$this->db $db;
    }
}

class 
PremiumUser {
    private 
$db;

    public function 
__construct($db) {
         
$this->db $db;
    }

Beide Klassen beziehen ihre Daten aus jeweils einer eigenständigen MySQL-Datenbank. Sinn / Unsinn dieser Annahme ist nicht weiter von Relevanz.

Code:
Datenbank: Standard 
-- Tabelle: StandardUser

Datenbank: Premium
-- Tabelle: PremiumUser
Den Container für die Injizierung der Abhängigkeiten würde ich folgendermaßen implementieren:

PHP-Code:
class DIContainer {
    public static function 
createUser() {
        return new 
User(new PDO('mysql:host=localhost;dbname=Standard'''''));
    }

    public static function 
createPremiumUser() {
        return new 
PremiumUser(new PDO('mysql:host=localhost;dbname=Premium'''''));
    }

Eine mögliches Testbeispiel könnte folgendermaßen aussehen:

PHP-Code:
$user DIContainer::createUser();
$premiumUser DIContainer::createPremiumUser(); 
Einerseits verstehe ich in diesem Zusammenhang, dass die Applikation keine Kentnisse darüber haben muss, welche Objekte die Klasse 'User' bzw. auch die Klasse 'PremiumUser' benötigt, um ihren Aufgaben vollständig gerecht zu werden. Andererseits stelle ich mir die Frage, warum die Applikation nicht wissen muss, welche Objekte eine bestimmte Klasse haben muss? Folgende weiterführende Beispiele wären denkbar:

PHP-Code:
class MyController 
    public function 
doSomething() {
        
$user = new User(new PDO('mysql:host=localhost;dbname=Standard'''''));
        
$premiumUser = new PremiumUser(new PDO('mysql:host=localhost;dbname=Premium'''''));
    }
}

class 
MyAnotherController {
    public function 
doSomething() {
        
$user DIContainer::createUser();
        
$premiumUser DIContainer::createPremiumUser();
    }  

Ich muss mir wohl eingestehen, dass die zweite Variante einen geringeren Schreibaufwand zur Konsequenz hat, allerdings sehe ich persönlich einen gravierenden Nachteil: Bei der ersten Variante habe ich die Flexbilität, die Datenbankverbindungen bei Bedarf sogar zu vertauschen, ohne dafür den DIContainer verändern zu müssen. Ich könnte praktisch - ist sinnlos, dessen bin ich mir bewusst - folgendes machen:

PHP-Code:
class MyController 
    public function 
doSomething() {
        
$user = new User(new PDO('mysql:host=localhost;dbname=Standard'''''));
        
$premiumUser = new PremiumUser(new PDO('mysql:host=localhost;dbname=Premium'''''));

        
$user2 = new User(new PDO('mysql:host=localhost;dbname=Premium'''''));
        
$premiumUser2 = new PremiumUser(new PDO('mysql:host=localhost;dbname=Standard'''''));
    }

Mir wäre die Möglichkeit gegeben, flexibel in der Injizierung der Objekte zu sein. Ich könnte den normalen Benutzer sowohl mit Daten der Tabelle StandardUser als auch mit der Tabelle PremiumUser arbeiten lassen, da hier eine lose Kopplung geschaffen wurde. Dasselbe kann ich aber meines Erachtens nicht in Verbindung mit einem DIContainer tun. Diesen müsste ich umständlicherweise modifizieren:

PHP-Code:
class DIContainer {
    public static function 
createUser() {
        return new 
User(new PDO('mysql:host=localhost;dbname=Standard'''''));
    }

    public static function 
createUser2() {
        return new 
User(new PDO('mysql:host=localhost;dbname=Premium'''''));
    }

    public static function 
createPremiumUser() {
        return new 
PremiumUser(new PDO('mysql:host=localhost;dbname=Premium'''''));

    public static function 
createPremiumUser2() {
        return new 
PremiumUser(new PDO('mysql:host=localhost;dbname=Standard'''''));
    }

Beim Container bräuchte ich demnach vier Methoden, um dem Entwickler mögliche Flexibilitäten in diesem Kontext zu ermöglichen, dies ist doch aber bestimmt nicht Sinn und Zweck eines Containers für die Injizierung von Abhängigkeiten.

Zusammengefasst:
Nach meinem Dafürhalten ist die Implementierung eines Containers zu konkret, sodass dieser unflexibel wird. Entgegen einer konkreten Implementierung in der Applikation selbst, verschließe ich mir geradezu die Möglichkeit, Objekte flexbiel zu injizieren oder verstehe ich da vielleicht etwas grundlegend falsch?

Ich hoffe, dass ich euch mein Problem halbwegs verständlich verdeutlichen konnte. Wäre über Hinweise sehr dankbar.

Geändert von Anyone (10.06.2011 um 20:51 Uhr).
Anyone ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 10.06.2011, 21:00  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.987
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Zitat:
Ich muss dazu leider gestehen, dass ich wohl die Vorgehensweise der Implementierung, nicht jedoch den Sinn bzw. den Nutzen eines solchen Containers verinnerlicht habe.
Mal ne Frage: Warum willst Du es dann nutzen?
Zitat:
$user = DIContainer::createUser();
$premiumUser = DIContainer::createPremiumUser();
Also mir wär das so zu nahe am Factory method. Wo wird da was injected? Schau Dir mal http://en.wikipedia.org/wiki/Dependency_injection an. Framework-managed dependency injection zeigt ein bissel das Prinzip. Ähnelt eher der Verwaltung eines Callbacks. In Deinem Fall würde ich eher überlegen, den User direkt zu injecten. Bei Bedarf ihn außen zu erzeugen oder ihn aus einem UserManager-Objekt (Singleton, aus Registry) zu holen.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 10.06.2011, 21:08  
Benutzer
 
Registriert seit: 07.08.2009
Beiträge: 94
PHP-Kenntnisse:
Anfänger
Anyone befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Mal ne Frage: Warum willst Du es dann nutzen?
Damit ich es verstehen und nachvollziehen kann.

Zitat:
Also mir wär das so zu nahe am Factory method. Wo wird da was injected? Schau Dir mal http://en.wikipedia.org/wiki/Dependency_injection an. Framework-managed dependency injection zeigt ein bissel das Prinzip. Ähnelt eher der Verwaltung eines Callbacks. In Deinem Fall würde ich eher überlegen, den User direkt zu injecten. Bei Bedarf ihn außen zu erzeugen oder ihn aus einem UserManager-Objekt (Singleton, aus Registry) zu holen.
Die Überlegung, die Notwendigkeiten eines Objektes, andere Objekte zu beinhalten über XML zu regeln ist mir auch schon in den Sinn gekommen bzw. habe ich Bezüge auf den XML-Aspekt des Öfteren gesehen / gelesen. Würden dann aber nicht Unmengen an XML-Dokumenten anfallen?

Und was wäre mit folgendem Beispiel:

Der Entwickler möchte eine Instanz der Klasse A erzeugen. Die Klasse A benötigt allerdings ein Objekt der Klasse B und C. Dies wird ganz normal über den Container geregelt. Was passiert allerdings, wenn das Objekt der Klasse B hingegen noch ein Objekt der Klasse D benötigt? Das wäre ja dann möglicherweise rekursiv zu lösen - ob das aber so komfortabel / sinnvoll ist?

Code:
A benötigt
    -> B benötigt
          -> D
    -> C
Anyone ist offline   Mit Zitat antworten
Alt 10.06.2011, 21:08  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 2.308
PHP-Kenntnisse:
Fortgeschritten
fab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblick
Standard

Nichts hindert dich daran, den DI-Container konfigurierbar zu machen. Schau dir mal die Dokumentation zum Symfony DI Container an, insbesondere ab hier, da wird das Prinzip sehr gut erklärt (die vorigen Seiten werden nicht viel neues für dich sein, es fängt mit genau so einem Beispiel-Container an wie deinem.

Es wäre übrigens einfacher zu erläutern wenn du ein etwas realistischeres Beispiel gewählt hättest

Edit:

Zitat:
Zitat von Anyone Beitrag anzeigen
Und was wäre mit folgendem Beispiel:

Der Entwickler möchte eine Instanz der Klasse A erzeugen. Die Klasse A benötigt allerdings ein Objekt der Klasse B und C. Dies wird ganz normal über den Container geregelt. Was passiert allerdings, wenn die Klasse B hingegen noch ein Objekt der Klasse D benötigt? Das wäre ja dann möglicherweise rekursiv zu lösen - ob das aber so komfortabel / sinnvoll ist?
Ja sicher, was sind deine Bedenken dabei?
fab ist offline   Mit Zitat antworten
Alt 10.06.2011, 21:13  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.987
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Macht man nicht einfach nur einen globalen DI-Container? Dann wäre das Problem doch gelöst.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist offline   Mit Zitat antworten
Alt 10.06.2011, 21:13  
Benutzer
 
Registriert seit: 07.08.2009
Beiträge: 94
PHP-Kenntnisse:
Anfänger
Anyone befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von fab Beitrag anzeigen
Nichts hindert dich daran, den DI-Container konfigurierbar zu machen. Schau dir mal die Dokumentation zum Symfony DI Container an, insbesondere ab hier, da wird das Prinzip sehr gut erklärt (die vorigen Seiten werden nicht viel neues für dich sein, es fängt mit genau so einem Beispiel-Container an wie deinem.

Es wäre übrigens einfacher zu erläutern wenn du ein etwas realistischeres Beispiel gewählt hättest

Edit:



Ja sicher, was sind deine Bedenken dabei?
Eigentlich hast du Recht, mir würde kein konkretes Beispiel einfallen, welches einen solchen Aufwand an Notwendigkeiten stellen könnte. Ich schau mir das von dir genannte Framework an und komme gegebenenfalls nochmal mit einem realistischem Beispiel zurück. Sorry

PS: Danke schonmal für eure Beiträge.
Anyone ist offline   Mit Zitat antworten
Alt 11.06.2011, 10:05  
Erfahrener Benutzer
 
Registriert seit: 25.05.2010
Beiträge: 852
PHP-Kenntnisse:
Anfänger
Trainmaster wird schon bald berühmt werden
Standard

Zitat:
Zitat von nikosch Beitrag anzeigen
Macht man nicht einfach nur einen globalen DI-Container?
Würde ich auch sagen. Eine Klasse ist ausreichend. Das könnte in etwa so aussehen:

PHP-Code:
$DIContainer DIContainer::getInstance();
$object $DIContainer->injectObject('path/to/class''class_name'$options); 
bzw. bei entsprechendem Applikationsdesign:
PHP-Code:
$object $this->injectObject('path/to/class''class_name'$options); 


wobei $options ein optionaler Array ist. Kann man mitschicken, muss man aber nicht.
Trainmaster ist offline   Mit Zitat antworten
Alt 11.06.2011, 21:38  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

@Trainmaster: das geht etwas am DI-Prinzip vorbei. In der Applikation willst eben nichts von Klassen und Optionen wissen, sondern lediglich einen Service beziehen, der von aussen konfiguriert und mit den Abhängigkeiten bestückt wird.

Eine adäquate Signatur wäre:

PHP-Code:
$object $container->getService('namespace/to/service''service_name'); 
Alles andere ist wieder die Definition einer expliziten Abhängigkeit und damit nicht mehr dem Prinzip entsprechend.

EDIT: siehe auch http://adventure-php-framework.org/S...plexe-Services.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 15.06.2011, 09:41  
Erfahrener Benutzer
 
Registriert seit: 02.09.2009
Beiträge: 1.019
PHP-Kenntnisse:
Fortgeschritten
mquadrat befindet sich auf einem aufstrebenden Ast
Standard

Ich meine wir hatten hier auch mal einen Thread ob man einen DI-Container jetzt am besten mit XML oder Annotations konfiguriert. Da dürfte auch der ein oder andere hilfreiche Post drin stecken.
__________________
Wir suchen PHP Entwickler (Vollzeit) im Raum Darmstadt / Rhein-Main. Infos via E-Mail mueller@new-frontiers.de
mquadrat ist offline   Mit Zitat antworten
Alt 15.06.2011, 10:49  
Erfahrener Benutzer
 
Registriert seit: 30.07.2008
Beiträge: 1.167
PHP-Kenntnisse:
Fortgeschritten
xm22 sorgt für eine eindrucksvolle Atmosphärexm22 sorgt für eine eindrucksvolle Atmosphärexm22 sorgt für eine eindrucksvolle Atmosphäre
Standard

Was mich immer noch irgendwie stört, ist, dass es i. d. R. kein wirkliche API gibt und man sich immer per String-Identifikator Objekte holen muss. Wer mal mit Magento gearbeitet hat und versucht hat, herauszufinden, welche Klassen dann teilweise dahinter stehen, der weiß, was ich meine.

Ich habe mir vor einiger Zeit daher mal überlegt, einen abstrakten DI-Container zu benutzen, der abgeleitet wird und dann eine "richtige" API zur Verfügung stellt mit Gettern und (etvl.) Settern. Also etwa so:

Code:
...
getLogger()
getSession()
...
Was haltet ihr davon?

Und wofür ich noch keine Patentlösung gefunden habe (Eigentlich noch gar keine), ist, wie man mehrere eine dynamische Anzahl an Argumenten an einen Konstruktor übergeben kann (z. B. bei der Instanziierung von PDO) -> außer eben, dass man dafür dedizierte Methoden in den DI-Container schreibt.

Geändert von xm22 (15.06.2011 um 11:03 Uhr).
xm22 ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
jQuery <div> Container generieren lassen ? dreamcatcher JavaScript, Ajax und mehr 5 23.02.2011 14:01
[Erledigt] Mehrere DIV Container mit einem Klick ändern (mit mehreren Request Aufrufe Lebenssonde JavaScript, Ajax und mehr 11 26.08.2010 09:01
Netz von Objekten mit Abhängigkeiten darstellen/zeichnen serPHPico PHP-Fortgeschrittene 12 25.08.2010 18:52
kürzeren div container authoatisch der höhe des contends anpassen litterauspirna HTML, Usability und Barrierefreiheit 15 29.07.2009 00:57
2 div Container immer gleich lang Kein Genie HTML, Usability und Barrierefreiheit 4 27.07.2009 13:38
Links vom Untermenü in Container öffnen Surfer PHP Tipps 2008 0 27.12.2008 19:24
[Erledigt] Zentrieren von a Blocks im DIV Container Daniel HTML, Usability und Barrierefreiheit 21 24.09.2008 09:37
[CSS] Container in Container Igäl HTML, Usability und Barrierefreiheit 5 04.09.2007 11:29
CSS - Bild im div container überlappt andere container Buschdieb HTML, Usability und Barrierefreiheit 13 19.07.2007 23:17
IE6: Container mit Float dabei wird margin doppelt gewertet DonTermi HTML, Usability und Barrierefreiheit 1 11.01.2007 09:02
Problem mit Container max-dhom HTML, Usability und Barrierefreiheit 3 20.09.2006 11:10
[Erledigt] Dependency/Property Injection Off-Topic Diskussionen 1 18.05.2006 10:52
CSS: Verschachtelter Container und Text danach HTML, Usability und Barrierefreiheit 2 01.12.2005 10:00
[Erledigt] Container im Firefox falsch dargestellt HTML, Usability und Barrierefreiheit 27 15.08.2005 23:18

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
dependency injection container, php dependency injection container, dependency injection container php, vorteile dependency injection container, dependency injection php, php pdo dependency injection, php dependency injection, di container php, dependency injection pattern php mysql, di container beispiel, php xml di container, pdo and dependency injection erklärung, dependency injection php mysql, depedency injection container, pdo and dependency injection, dependency-injection-container, php dependency container, php static dependency injection container, symfony dependency injection pdo, php dependency injection container tutorial

Alle Zeitangaben in WEZ +2. Es ist jetzt 00:55 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum