Zitat von BlackScorp
Beitrag anzeigen
Ankündigung
Einklappen
Keine Ankündigung bisher.
Service Locator ein Anti Pattern
Einklappen
Neue Werbung 2019
Einklappen
X
-
[SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]
-
Hey danke euch bieden vielmal für Eure Hilfe.
Zitat von strub Beitrag anzeigen
Deshalb wird bei meinem Container erst bei ->get('Mailer') die Konfiguration erstellt ohne vorher eine Defintion zu definieren, diese wird automatisch je nach Namespace path und container konigfuration gesucht
Was ist der Vorteil?
PHP-Code:class ServiceProvider extends Service {
/**
* @return array|Service\DependencyInjection\Setter
*/
public function logger() {
$fileHandler = new FileHandler();
$fileHandler->setFileName('default');
return [
'method' => [
['addHandler', 'FileHandler', $fileHandler]
]
];
}
public function loggerAnother() {
$fileHandler = new FileHandler();
$fileHandler->setFileName('another');
$setter = diSetter();
$setter->method('addHandler', $fileHandler);
return $setter;
}
}
$this->container->get('Logger');
$this->container->get('LoggerAnother');
So wenn ich z.b. eine neue Applikation schreibe oder nur ein Teil eines Service benutze, haben ich schon mal eine Standartkonifuration.
Oder z.B habe ich eine Konfiguration für das Backend und eine für das Frontend. Aber das lässt sich warscheinlich auch mit dem php-di bewerkstelligen.
Frontend/Config/Service/Logger
Frontend/Config/Service/Session
Backend/Config/Service/Logger
Backend/Config/Service/Session
Kommentar
-
Zitat von strub Beitrag anzeigenDer Vorteil ist das meine Services vorkonfuriert sind in einem ServiceProvider: (..)
PHP-Code:return[
#1 - map interface to class
\My\App\LoggerInterface::class => \My\App\Logger::class,
#2 - use a lazy factory for creation
\My\App\Logger::class => \DI\factory([\My\App\ComplexLoggerFactory::class, 'make']),
#3 - defintion based on an arbitrary name
'anotherLogger' => function(){
return new \My\App\AnotherLogger();
},
#4 - override a constructor parameter
\My\App\SomeService::class => \DI\object()
->constructorParameter('logger', \DI\object(\My\App\VerySpecialLogger::class)),
#5 - map multiple interfaces to multiple implementations automagically
'My\App\*RepositoryInterface' => DI\object('My\App\*DoctrineRepository'),
];
PHP-Code:$loggerA = $container->get(\My\App\LoggerInterface::class);
$loggerB = $contianer->get(\My\App\Logger::class);
$loggerC = $contianer->get('anotherLogger');
PHP-Code:namespace My\App;
use \My\App\{Config, LoggerInterface};
class ComplexLoggerFactory{
private $config;
public function __construct(Config $config){
$this->config = $config;
}
public function make(): LoggerInterface{
$logger = new \My\App\ComplexLogger();
$logger->setFile($config->getErrorLogPath());
// configuration ..
return $logger;
}
}
Zitat von strub Beitrag anzeigenSo wenn ich z.b. eine neue Applikation schreibe oder nur ein Teil eines Service benutze, haben ich schon mal eine Standar d konifuration.
Zitat von strub Beitrag anzeigenOder z.B habe ich eine Konfiguration für das Backend und eine für das Frontend. Aber das lässt sich warscheinlich auch mit dem php-di bewerkstelligen.
Zitat von strub Beitrag anzeigenFrontend/Config/Service/Logger
Frontend/Config/Service/Session
Backend/Config/Service/Logger
Backend/Config/Service/Session
Mein Vorgehen mit PHP-DI:
- Klassen die keine Konfiguration brauchen werden nicht in der Konfiguration aufgeführt (die löst der Autoloader auf)
- Interfaces werden konkreten Implementierungen zugeordnet (teilweise abhängig vom Environment dev/prod)
- Die Erzeugung von komplexen Objekten, die vorher konfiguriert werden müssen, wird an Lazy Factories delegiert
- Wenn eine Klasse eine Implementierung für ein Interface braucht die von der Standardeinstellung abweicht, wird das konfiguriert (siehe #4 im Beispiel)
Damit fahre ich unheimlich gut, denn ich kann zu 100% Autowiring nutzen, die Konfiguration ist sehr schlank, der Footprint ist bei dem gebotenen Featureset minimal und der Einfluss auf die Performance kaum messbar. Mit PHP-DI Version 6 wird es da noch viele Optimierungen geben (u.A. einen pre-compiled container für den Produktivbetrieb).
Letztlich kannst du nutzen was du willst, solange es für dich passt. Ich verbringe ungerne Zeit damit Probleme zu lösen die bereits sehr gut gelöst wurden. Hauptsache du lässt die Finger vom Service Locator[SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]
- 1 Likes
Kommentar
-
PHP-Code:public function make(): LoggerInterface{ }
Kommentar
-
Zitat von tomBuilder Beitrag anzeigenPHP-Code:public function make(): LoggerInterface{ }
Falls du den ":" meinst: das ist Teil einer Return type declaration[SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]
- 1 Likes
Kommentar
-
Zitat von lottikarotti Beitrag anzeigenFalls du den ":" meinst: das ist Teil einer Return type declaration
Kommentar
-
Hey vielen dank Lottikarotti für die tolle Erklärung mit Beispielen. Nun scheint mir alles klarer
Letztlich kannst du nutzen was du willst, solange es für dich passt. Ich verbringe ungerne Zeit damit Probleme zu lösen die bereits sehr gut gelöst wurden.
PHP-Code:Hauptsache du lässt die Finger vom Service Locator
Kommentar
-
Die Diskussion ist offensichtlich ein wenig von der ursprünglichen Fragestellung abgedriftet und verliert sich nun in irgendwelchen Details zu DiC. Aber weder PHP-DI noch ein anderer DiC werden eine saubere Lösung ermöglichen, wenn das Basisdesign schon nicht sauber ist.
PHP-Code:Article extends Action {}
Bei Vererbung soll die abgeleitete Klasse in einer IST-EIN-BEZIEHUNG zu der Basisklasse stehen.
Die Vererbung dient nicht der Erweiterung einer Klasse, sondern der Spezialisierung.
Du setzt Vererbung falsch ein (konzeptionell) und bringst damit Sachen zusammen, die nicht zusammengehören. Das bringt ganz automatisch weitere Probleme mit sich.
Das ist der Punkt an dem du – meiner Ansicht nach - zuerst ansetzen solltest.
vg
jack
-
Kommentar
Kommentar