Slide 1

Slide 1 text

DEPENDENCY DEPENDENCY INJECTION INJECTION IN DER OXID IN DER OXID PROJEKTENTWICKLUNG PROJEKTENTWICKLUNG Michael Koltan So ware Architect OXID eSales

Slide 2

Slide 2 text

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; } }

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

DER DER INTERNAL INTERNAL NAMESPACE NAMESPACE Internal/ ├── Container ├── Domain ├── Framework ├── README.md ├── services.yaml └── Transition

Slide 5

Slide 5 text

CONTAINER CONTAINER $container = ContainerFactory::getInstance()->getContainer(); $foo = $container->get(FooInterface::class);

Slide 6

Slide 6 text

DIE CACHE-DATEI FÜR DEN DIE CACHE-DATEI FÜR DEN CONTAINER CONTAINER rm source/tmp/container_cache.php

Slide 7

Slide 7 text

DOMAIN DOMAIN Data objects vs. services

Slide 8

Slide 8 text

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';

Slide 9

Slide 9 text

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)

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

ZUGRIFFSRECHTE ZUGRIFFSRECHTE Facades Bridges Data objects Utilities Data access objects Domain services

Slide 12

Slide 12 text

FRAMEWORK FRAMEWORK Framework/ ├── Config ├── Console ├── Dao ├── Database ├── DIContainer ├── Event ├── FileSystem ├── Form ├── FormConfiguration ├── Logger ├── Module ├── services.yaml ├── Smarty ├── Storage ├── Templating └── Theme

Slide 13

Slide 13 text

TRANSITION TRANSITION Transition/ ├── Adapter ├── ShopEvents └── Utility

Slide 14

Slide 14 text

MODULE MODULE

Slide 15

Slide 15 text

EINFACHER EINSTIEGSPUNKT: EINFACHER EINSTIEGSPUNKT: class GraphQL extends WidgetController { public function init(): void { ContainerFactory::getInstance() ->getContainer() ->get(GraphQLQueryHandlerInterface::class) ->executeGraphQLQuery(); } }

Slide 16

Slide 16 text

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 ...

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

DAS VAR VERZEICHNIS DAS VAR VERZEICHNIS var/ ├── configuration │ └── shops │ └── 1.yaml └── generated └── generated_services.yaml

Slide 19

Slide 19 text

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 } }

Slide 20

Slide 20 text

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!

Slide 21

Slide 21 text

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']; } }

Slide 22

Slide 22 text

IN DER IN DER SERVICES.YAML SERVICES.YAML: : OxidEsales\FooEventSubscriber: class: OxidEsales\FooEventSubscriber tags: ['kernel.event_subscriber']

Slide 23

Slide 23 text

OXID COMPONENTS OXID COMPONENTS Just a composer package of the type oxideshop-component

Slide 24

Slide 24 text

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']; } }

Slide 25

Slide 25 text

GENERATED_SERVICES.YAML GENERATED_SERVICES.YAML MyProject\FooEventSubscriber: class: MyProject\FooEventSubscriber tags: [kernel.event_subscriber] calls: [{ method: setActiveShops, arguments: [[1]] }, { method: setContext, arguments: ['@...\ContextInterface'] }]

Slide 26

Slide 26 text

COMMAND COMMAND-KLASSEN FÜR DIE SYMFONY -KLASSEN FÜR DIE SYMFONY CONSOLE CONSOLE Basisklasse AbstractShopAwareCommand

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

NOCH EINMAL DAS NOCH EINMAL DAS VAR VAR-VERZEICHNIS -VERZEICHNIS var ├── configuration │ ├── configurable_services.yaml │ └── shops │ └── 1.yaml └── generated └── generated_services.yaml

Slide 29

Slide 29 text

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