Symfony3 run-time service laden

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Remco P

Remco P

12/12/2015 21:57:54
Quote Anchor link
Beste leden,

Ik schrijf momenteel een ERP-systeem op basis van het Symfony framework. Een van de benodigde functionaliteiten is dat het pakketten moet kunnen verzenden, d.m.v. verschillende carriers, bijv. UPS of DHL. Voor de API's zijn genoeg libraries beschikbaar die ik kan gebruiken. Hier heb ik dan een kleine service over geschreven die mijn input omzetten naar input die de API slikt.

Op basis van welke carrier de gebruiker gebruikt moet ik één van de services gebruiken. Ik dacht eerst aan een oplossing als de volgende:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace AppBundle\Service;

class ShippingFactory
{
    public function create ($method, $container)
    {

        return $container -> get ($method -> getCarrier () -> getName());
    }
}
[
/code]

In m'n services.yml heb ik de verschillende carriers gedefinieerd als services. Maar hier ben ik geen fan van aangezien ik dan de container moet doorgeven aan m'n factory service. Misschien denk ik veel te moeilijk, maar is hier geen nettere manier voor? In de documentatie kwam ik ook wat tegen over Service Configuration, maar dit is allemaal op basis van vooraf gedefinieerde parameters.
 
PHP hulp

PHP hulp

16/08/2018 18:21:54
 
Wouter J

Wouter J

13/12/2015 14:33:13
Quote Anchor link
Register the carriers als services in the factory, met een naam. Bijvoorbeeld:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
class ShippingFactory
{
    /** @var Carrier */
    private $carriers = [];

    public function addCarrier($name, Carrier $carrier)
    {

        if (isset($this->carriers[$name])) {
            throw new \InvalidArgumentException(sprintf('Carrier "%s" already exists.', $name));
        }


        $this->carriers[$name] = $carrier;
    }


    public function create(ShippingMethod $method)
    {

        $carrierName = $method->getCarrier()->getName();

        if (!isset($this->carriers[$carrierName])) {
            throw new \RuntimeException(sprintf(
                'No carrier named "%s" can be found, available carriers: %s',
                $carrierName,
                implode(', ', array_keys($this->carriers))
            ));
        }


        return $this->carrier[$carrierName];
    }
}

?>


Maak nu van deze factory een service:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
# app/config/services.yml
services:
    app.shipping_factory:
        class: AppBundle\Shipping\ShippingFactory


Vervolgens moet je nog zorgen dat alle carrier services worden toegevoegd aan deze app.shipping_factory service. Dit doe je door de services een tag mee te geven en in een zogenoemde compiler pass alle services met een bepaalde tag toe te voegen aan de shipping factory. Lees meer hierover in http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html en http://symfony.com/doc/current/components/dependency_injection/tags.html

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class RegisterCarriersPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {

        if (!$container->hasDefinition('app.shipping_factory')) {
            // wanneer de factory service niet aanwezig is valt er niks te doen, dus stop de functie
            return;
        }


        $factoryDefinition = $container->getDefinition('app.shipping_factory');
        // vind alle services met de app.carrier tag
        $carrierServiceIDs = $container->findTaggedServiceIds('app.carrier');

        foreach ($carrierServiceIDs as $carrierServiceID => $tags) {
            foreach ($tags as $attributes) {
                // roep de addCarrier method van de factory aan wanneer de factory service wordt geinitialiseer
                // en geef hier de carrier name (tag attribute) en de carrier instance mee

                $factoryDefinition->addMethodCall('addCarrier', array(
                    $attributes['name'],
                    new
Reference($carrierServiceID)
                ));
            }
        }
    }
}

?>
 
Remco P

Remco P

13/12/2015 20:10:31
Quote Anchor link
Super! Bedankt voor je uitgebreide antwoord. Ik had al even gekeken naar tags en compiler passes, maar had de link nog niet gemaakt.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.