Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dependency injection in der OXID Projektentwicklung

Dependency injection in der OXID Projektentwicklung

Ein Überblick über die features, die OXID Projektentwickler nutzen können, die durch den integrierten Symfony DI Container bereitgestellt werden.

Michael Koltan

November 12, 2019
Tweet

Other Decks in Programming

Transcript

  1. DEPENDENCY DEPENDENCY INJECTION INJECTION IN DER OXID IN DER OXID

    PROJEKTENTWICKLUNG PROJEKTENTWICKLUNG Michael Koltan So ware Architect OXID eSales
  2. DAS PRINZIP: DEPENDENCY DAS PRINZIP: DEPENDENCY INVERSION INVERSION vs. class

    foo { public function __construct() { $this->bar = new Bar(); } } class foo { public function __construct(BarInterface $bar) { $this->bar = $bar; } }
  3. DER DI CONTAINER: SYMFONY DI DER DI CONTAINER: SYMFONY DI

    services.yaml services: _defaults: autowire: true public: false OxidEsales\EshopCommunity\Internal\FooInterface: class: OxidEsales\EshopCommunity\Internal\Foo public: true OxidEsales\EshopCommunity\Internal\BarInterface: class: OxidEsales\EshopCommunity\Internal\Bar
  4. DER DER INTERNAL INTERNAL NAMESPACE NAMESPACE Internal/ ├── Container ├──

    Domain ├── Framework ├── README.md ├── services.yaml └── Transition
  5. DATA OBJECTS DATA OBJECTS Repräsentieren Objekte der realen Welt: Kunde,

    Einkaufswagen, Rechnung, ... Haben verschiedene Instanzen: Kunde Müller, Kunde Maier, Kunde Schulz, ... Instanzen sind zustandsbeha et: $customer1->lastName = 'Müller'; $customer2->lastName = 'Maier';
  6. SERVICES SERVICES Repräsentieren Aktionen: speichere Kundendaten, prüfe Rechte, berechne Preis,

    ... Singletons - es gibt nur eine Instanz: CustomerDao, PermissionService, PriceCalculationFacade, ... Die Instanz ist zustandslos (naja, fast)
  7. WEITERE UNTERSCHIEDE WEITERE UNTERSCHIEDE Data objects Services Implementiert kein Interface

    Muss ein Interface implementieren Hat keine äußeren Abhängigkeiten Kann von anderen services und data objects abhängen Instantiierung durch new oder einen factory service Instantiierung durch den DI container
  8. FRAMEWORK FRAMEWORK Framework/ ├── Config ├── Console ├── Dao ├──

    Database ├── DIContainer ├── Event ├── FileSystem ├── Form ├── FormConfiguration ├── Logger ├── Module ├── services.yaml ├── Smarty ├── Storage ├── Templating └── Theme
  9. EINFACHER EINSTIEGSPUNKT: EINFACHER EINSTIEGSPUNKT: class GraphQL extends WidgetController { public

    function init(): void { ContainerFactory::getInstance() ->getContainer() ->get(GraphQLQueryHandlerInterface::class) ->executeGraphQLQuery(); } }
  10. EIGENE EIGENE SERVICES.YAML SERVICES.YAML DATEI: DATEI: services: _defaults: public: false

    autowire: true OxidEsales\GraphQL\Framework\GraphQLQueryHandlerInterface: class: OxidEsales\GraphQL\Framework\GraphQLQueryHandler public: true OxidEsales\GraphQL\Framework\RequestReaderInterface: class: OxidEsales\GraphQL\Framework\RequestReader ...
  11. WIE KOMMEN DIE SERVICES IN DEN WIE KOMMEN DIE SERVICES

    IN DEN CONTAINER? CONTAINER? var/generated/generated_services.yaml imports: - resource: /shop/source/modules/oe/graphql-base/services.yaml
  12. DAS VAR VERZEICHNIS DAS VAR VERZEICHNIS var/ ├── configuration │

    └── shops │ └── 1.yaml └── generated └── generated_services.yaml
  13. VERWENDUNG VON SERVICES AUS DEM VERWENDUNG VON SERVICES AUS DEM

    CORE CORE class FooDao { private $queryBuilderFactory; public function __construct(QueryBuilderFactoryInterface $fac) { $this->queryBuilderFactory = $fac; } public function getFooById(int $fooId)): Foo { $queryBuilder = $this->queryBuilderFactory->create(); $queryBuilder->select('*')->from('foo') ->where('id = :id')->setParameters(['id' => $fooId]); ... // execute query and build object } }
  14. EIN PAAR WORTE ZUR BACKWARD EIN PAAR WORTE ZUR BACKWARD

    COMPATIBILITY COMPATIBILITY Patch releases sind immer backward compatible Minor und major releases: Keine bc für Implementierungen! Bc nur für Interfaces die mit @stable annotiert sind!
  15. BESTEHENDE FUNKTIONALITÄT ERWEITERN BESTEHENDE FUNKTIONALITÄT ERWEITERN (NEW STYLE) (NEW STYLE)

    class FooEventSubscriber implements EventSubscriberInterface { public function handleFooEvent(FooEvent $event) { $foo = $event->getFoo(); ... // Do something with foo return $event; } public static function getSubscribedEvents() { return [FooEvent::NAME => 'handleFooEvent']; } }
  16. SHOP AWARE EVENTS SHOP AWARE EVENTS class FooEventSubscriber implements ShopAwareEventSubsciber

    { public function handleFooEvent(FooEvent $event) { $foo = $event->getFoo(); ... // Do something with foo return $event; } public static function getSubscribedEvents() { return [FooEvent::NAME => 'handleFooEvent']; } }
  17. WAS TUN, WENN ES KEINEN EVENT WAS TUN, WENN ES

    KEINEN EVENT GIBT? GIBT? Mail an [email protected] Eigene Implementierung schreiben, entweder in einem Modul oder eine Komponente Service überschreiben in var/configuration/configurable_services.yaml
  18. NOCH EINMAL DAS NOCH EINMAL DAS VAR VAR-VERZEICHNIS -VERZEICHNIS var

    ├── configuration │ ├── configurable_services.yaml │ └── shops │ └── 1.yaml └── generated └── generated_services.yaml
  19. ZUSAMMENFASSUNG ZUSAMMENFASSUNG Internal namespace mit Schichtenarchitektur Services werden instantiiert durch

    Symfony DI container Container kann auch in Modulen verwendet werden (services.yaml) Funktionalitätserweiterung durch events Neue Erweiterungsmöglichkeit durch OXID Komponenten Eventsubscriber / console commands können shop aware sein System services können in der configurable_services.yaml überschrieben werden