(meine) wahrheit über symfony€¦ · what if we want unit tests to run fast without waiting for...

Post on 11-Aug-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

(Meine) Wahrheit über

SymfonyTimon Schroeter www.php-schulung.de

Timon != Timon

Timon Schroeter

● www.php-schulung.de● Schulung, Coaching, Beratung

Version 4.2 (2002)OOP ?register_globals ?

http://doitandhow.com/2012/07/16/fun-colored-spaghetti/

OOP

C++

C++HPC

C++HPC fortran

C++HPC

Matlabfortran

professionell entwickeln

rumbasteln

TDD

TDDunit

TDDunit OOP + DI

Version 2.0 (2011)

professionell entwickeln

rumbasteln

FormsTWIG

Validation

uvm.

Dependency InjectionContainer

Event Dispatcher

FormsTWIG

Validation

uvm.

Timon Schroeter 23 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ● Prozedural● Objektorientiert

Timon Schroeter 24 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

Timon Schroeter 25 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

http://doitandhow.com/2012/07/16/fun-colored-spaghetti/

Timon Schroeter 27 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

● Objektorientiert– Objekte, Eigenschaften, Methoden usw.

Timon Schroeter 28 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

● Objektorientiert– Objekte, Eigenschaften, Methoden usw.

– Funktionen in abgegrenzten Kontexten verfügbar

http://www.spieltischshop.de/lego-soft.html

Timon Schroeter 30 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

● Objektorientiert– Objekte, Eigenschaften, Methoden usw.

– Funktionen in abgegrenzten Kontexten verfügbar

Timon Schroeter 31 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

● Objektorientiert– Objekte, Eigenschaften, Methoden usw.

– Funktionen in abgegrenzten Kontexten verfügbar

– feste Abhängigkeiten zwischen Klassen

Timon Schroeter 32 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

● Prozedural– Funktionen die alle global verfügbar sind

● Objektorientiert– Objekte, Eigenschaften, Methoden usw.

– Funktionen in abgegrenzten Kontexten verfügbar

– feste Abhängigkeiten zwischen Klassen

● OOP mit Dependency Injection– Instanzen variabel kombinierbar (Schraubendreher)

Timon Schroeter 33 www.php-schulung.de

Timon Schroeter 34 www.php-schulung.de

wiederverwendbarunit-testbarGroßteil der Codebasis

Timon Schroeter 35 www.php-schulung.de

nicht wiederverwendbarnicht unit-testbarMinimum an Code

wiederverwendbarunit-testbarGroßteil der Codebasis

Timon Schroeter 36 www.php-schulung.de

DependencyInjection

Timon Schroeter 37 www.php-schulung.de

Dependency Injection

DI

Timon Schroeter 38 www.php-schulung.de

Structure of the next slides

● Code example: DI for generic PHP classes● Code example: DI in Symfony 2

You are here

Timon Schroeter 39 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Why is this classdifficult to unit test?

Timon Schroeter 40 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

Why is this classdifficult to unit test?

Timon Schroeter 41 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

What if we ever want to

use a different HTTP client?

Why is this classdifficult to unit test?

Timon Schroeter 42 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

What if we ever want to

use a different HTTP client?What if we

ever want to use a differentlogger class?

Why is this classdifficult to unit test?

Timon Schroeter 43 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

What if we ever want to

use a different HTTP client?What if we

ever want to use a differentlogger class?

Why is this classdifficult to unit test?

What if we ever want to

use a differentlog format?

Timon Schroeter 44 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

What if we ever want to

use a different HTTP client?

What if we want unit tests to run fastwithout logging?

What if we ever want to

use a differentlogger class?

What if we want unit tests to run fastwithout logging?

Why is this classdifficult to unit test?

What if we ever want to

use a differentlog format?

Timon Schroeter 45 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

What if we want unit tests to run fastwithout waiting for the network?

What if we ever want to

use a different HTTP client?

What if we want unit tests to run fastwithout logging?

What if we ever want to

use a differentlogger class?

What if we want unit tests to run fastwithout logging?

Why is this classdifficult to unit test?

What if we ever want to

use a differentlog format?Dependencies are pulled.=> Replacing requires refactoring=> Dynamic replacing (e.g. for

testing) is impossible

Timon Schroeter 46 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\Client;use Acme\Logger\XmlLogger;

class FeedAggregator {private $client;private $logger;

public function __construct () {

$this->client = new Client();$this->logger = new XmlLogger();

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pulled.

Timon Schroeter 47 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Timon Schroeter 48 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Timon Schroeter 49 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Implementations areinjected at runtime

Timon Schroeter 50 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Implementations areinjected at runtime

Easy to replace, evendynamically (for testing)

Timon Schroeter 51 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Implementations areinjected at runtime

Easy to replace, evendynamically (for testing)

On the level of the class,You are now experts for Dependency Injection.

Timon Schroeter 52 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Implementations areinjected at runtime

Easy to replace, evendynamically (for testing)

On the level of the class,You are now experts for Dependency Injection.

Any questions?

Timon Schroeter 53 www.php-schulung.de

<?phpnamespace Acme\FeedBundle\Service\FeedAggregatoruse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$baseurl.$path);return null;

}

return $response->getBody();}// ...

}

Dependencies are pushed.

Class only dependson interfaces

Implementations areinjected at runtime

Easy to replace, evendynamically (for testing)

On the level of the class,You are now experts for Dependency Injection.

Who constructsand pushes all the

dependencies?

Timon Schroeter 54 www.php-schulung.de

Timon Schroeter 55 www.php-schulung.de

Dependency Injection Container

DIC

“DI Container”, “DIC”, “Service Container”, “the Container”

Timon Schroeter 56 www.php-schulung.de

Timon Schroeter 57 www.php-schulung.de

Very Many Frameworks support Dependency Injection

Timon Schroeter 58 www.php-schulung.de

DI is very easy in Symfony 2

Timon Schroeter 59 www.php-schulung.de

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Timon Schroeter 60 www.php-schulung.de

# app/config/config.yml# ...services: my_service: class: Acme\MyBundle\Service\AwesomeClass

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Timon Schroeter 61 www.php-schulung.de

# app/config/config.yml# ...services: my_service: class: Acme\MyBundle\Service\AwesomeClass

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Class to manage

Name of the new service

Timon Schroeter 62 www.php-schulung.de

# php app/console container:debug

Timon Schroeter 63 www.php-schulung.de

# app/config/config.yml# ...services: my_service: class: Acme\MyBundle\Service\AwesomeClass

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Timon Schroeter 64 www.php-schulung.de

# app/config/config.yml# ...services: my_service: class: Acme\MyBundle\Service\AwesomeClass arguments: some_arg: “string” another:

- array_member - array_member

even_more: @another_service

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Timon Schroeter 65 www.php-schulung.de

# app/config/config.yml# ...services: my_service: class: Acme\MyBundle\Service\AwesomeClass arguments: some_arg: “string” another:

- array_member - array_member

even_more: @another_service

DI is very easy in Symfony 2

● Any ordinary PHP class can be managed by DIC● Only 2 lines of configuration per class are needed● Any class managed by the DIC is called a “Service”

Any other servicecan be injected as

as argument

Arguments can bestrings, numbers,

arrays, placeholders,and many more ...

Timon Schroeter 66 www.php-schulung.de

<?phpuse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$host.$path);return null;

}

return $response->getBody();}// ...

}

Timon Schroeter 67 www.php-schulung.de

<?phpuse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$host.$path);return null;

}

return $response->getBody();}// ...

}

Timon Schroeter 68 www.php-schulung.de

# app/config/config.yml# ...services: feed_aggregator: class: Acme\FeedBundle\Service\FeedAggregator arguments: client: @http_client logger: @logger

<?phpuse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$host.$path);return null;

}

return $response->getBody();}// ...

}

Timon Schroeter 69 www.php-schulung.de

# app/config/config.yml# ...services: feed_aggregator: class: Acme\FeedBundle\Service\FeedAggregator arguments: client: @http_client logger: @logger

<?phpuse Guzzle\Http\ClientInterface;use Acme\Logger\LoggerInterface;

class FeedAggregator {private $client;private $logger;

public function __construct(ClientInterface $client, LoggerInterface $logger) {

$this->client = $client;$this->logger = $logger;

}

public function retrieveFeed ($baseurl, $path) {$request = $this->client->setBaseUrl($baseurl)->get($path);$response = $request->send();if (200 != $response->getStatusCode()) {

$this->logger->log('Could not get: '.$host.$path);return null;

}

return $response->getBody();}// ...

}

Timon Schroeter 70 www.php-schulung.de

Different Config needed for Functional Testing?

● app/config/config.yml● app/config/config_dev.yml● app/config/config_test.yml Put it here here

Timon Schroeter 71 www.php-schulung.de

Timon Schroeter 72 www.php-schulung.de

wiederverwendbarunit-testbarGroßteil der Codebasis

Timon Schroeter 73 www.php-schulung.de

nicht wiederverwendbarnicht unit-testbarMinimum an Code

wiederverwendbarunit-testbarGroßteil der Codebasis

Timon Schroeter 74 www.php-schulung.de

DependencyInjection

Timon Schroeter 75 www.php-schulung.de

DependencyInjection

Services

Timon Schroeter 76 www.php-schulung.deServices

Controller bekommenInstanzen der Services vom DIC, z.B. so:

$this->get(“logger“)

Timon Schroeter 77 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

● Modularität● Erweiterbarkeit● Wartbarkeit● Testbarkeit● Performance

Timon Schroeter 78 www.php-schulung.de

Further Reading

● http://fabien.potencier.org/article/11/what-is-dependency-injection

● http://symfony.com/doc/current/components/dependency_injection/compilation.html

● http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html

● Use the source ...

Timon Schroeter 79 www.php-schulung.de

Timon Schroeter 80 www.php-schulung.de

Commonly used Types of Events

● Kernel events● Form events● Doctrine events

Timon Schroeter 81 www.php-schulung.de

Kernel Events

Timon Schroeter 82 www.php-schulung.de

Kernel Events

Used in SensioFrameworkExtraBundle to act on the @Template annotation.

Timon Schroeter 83 www.php-schulung.de

To act on a Kernel Event

● Create a Listener Class● Let the DIC do all remaining work for you

Timon Schroeter 84 www.php-schulung.de

To act on a Kernel Event

● Create a Listener Class● Let the DIC do all remaining work for you

– Create a service definition

Timon Schroeter 85 www.php-schulung.de

To act on a Kernel Event

● Create a Listener Class● Let the DIC do all remaining work for you

– Create a service definition

# app/config/config.ymlservices: your_listener_name: class: Acme\DemoBundle\EventListener\AcmeExceptionListener

Timon Schroeter 86 www.php-schulung.de

To act on a Kernel Event

● Create a Listener Class● Let the DIC do all remaining work for you

– Create a service definition

– Add a tag labeling the service as a listener

# app/config/config.ymlservices: your_listener_name: class: Acme\DemoBundle\EventListener\AcmeExceptionListener

Timon Schroeter 87 www.php-schulung.de

To act on a Kernel Event

● Create a Listener Class● Let the DIC do all remaining work for you

– Create a service definition

– Add a tag labeling the service as a listener

# app/config/config.ymlservices: your_listener_name: class: Acme\DemoBundle\EventListener\AcmeExceptionListener tags: - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

Timon Schroeter 88 www.php-schulung.de

How to listen to

● Kernel events– listener class + service tag

● Form events● Doctrine events

Timon Schroeter 89 www.php-schulung.de

How to listen to

● Kernel events– listener class + service tag

● Form events– listener class + service tag

– closure inside form type class

● Doctrine events

Timon Schroeter 90 www.php-schulung.de

How to listen to

● Kernel events– listener class + service tag

● Form events– listener class + service tag

– closure inside form type class

● Doctrine events– listener class + service tag

– callback method inside entity class

Timon Schroeter 91 www.php-schulung.de

Time Checkpoint

● Skip?

Timon Schroeter 92 www.php-schulung.de

Which listeners are active?

● Your answer?

Timon Schroeter 93 www.php-schulung.de

Which listeners are active?● Kernel events

– listener class + service tag

● Form events– listener class + service tag

– closure inside form type class

● Doctrine events– listener class + service tag

– callback method inside entity class

● Your own custom events– listener class + service tag

– closure etc.

Timon Schroeter 94 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Timon Schroeter 95 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Timon Schroeter 96 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Timon Schroeter 97 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller

Timon Schroeter 98 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller

$listeners = $this->getContainer()->get('event_dispatcher')->getListeners();

Timon Schroeter 99 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller

$listeners = $this->getContainer()->get('event_dispatcher')->getListeners();

print_r (array_keys($listeners));print_r (array_keys($listeners['kernel.view']));

Timon Schroeter 100 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller

$listeners = $this->getContainer()->get('event_dispatcher')->getListeners();

print_r (array_keys($listeners));print_r (array_keys($listeners['kernel.view']));

$entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');

Doctrine Entity Manageruses an instance of the

Doctrine Event Manager(injected by the DIC).

Timon Schroeter 101 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller

$listeners = $this->getContainer()->get('event_dispatcher')->getListeners();

print_r (array_keys($listeners));print_r (array_keys($listeners['kernel.view']));

$entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');$listeners = $entityManager->getEventManager()->getListeners();

print_r (array_keys($listeners));// ...

Timon Schroeter 102 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events● Check in your own Command oder Controller● ListenersDebugCommandBundle

Timon Schroeter 103 www.php-schulung.de

ListenersDebugCommandBundle

● https://github.com/egulias/ListenersDebugCommandBundle

● app/console container:debug:listeners

--event=event.name: if issued will filter to show only the listeners listening to the given name (ordered by descending priority, unless you use: --order-asc)

--show-private : if issued will show also private services

...

Timon Schroeter 104 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

● Modularität● Erweiterbarkeit● Wartbarkeit● Testbarkeit● Performance

Timon Schroeter 105 www.php-schulung.deElastic S.

ServerGenerischerWebserver

Sol-r BundleElastic Search

BundleGuzzleBundle

Client Lib.Sol-r

Client Lib.Elastic S.

GuzzleHTTP Client

DoctrineBundle

DatenbankSol-r Server

ShopAAABundle

ShopCCCBundle

ShopBBBBundle

Shop Aggregator Bundle

DIC Tag: shop_service

Product Search Bundle

Deal Finder Bundle

Deal Lookup Bundle

Shop Crawler Bundle

Product Bundle

Gute Performance machbar?

Timon Schroeter 106 www.php-schulung.deElastic S.

ServerGenerischerWebserver

Sol-r BundleElastic Search

BundleGuzzleBundle

Client Lib.Sol-r

Client Lib.Elastic S.

GuzzleHTTP Client

DoctrineBundle

DatenbankSol-r Server

ShopAAABundle

ShopCCCBundle

ShopBBBBundle

Shop Aggregator Bundle

DIC Tag: shop_service

Product Search Bundle

Deal Finder Bundle

Deal Lookup Bundle

Shop Crawler Bundle

Product Bundle

Gute Performance machbar !Danke Opcache:

Byte-Code im

RAM

Timon Schroeter 107 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

● Modularität● Erweiterbarkeit● Wartbarkeit● Testbarkeit● Performance

Timon Schroeter 108 www.php-schulung.de

Further Reading:Dependency Injection

● http://fabien.potencier.org/article/11/what-is-dependency-injection

● http://symfony.com/doc/current/components/dependency_injection/compilation.html

● http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html

● Use the source ...

Timon Schroeter 109 www.php-schulung.de

Further Reading:Event Dispatcher

● Symfony Event Dispatcher– http://symfony.com/doc/current/components/event_dispatcher/

– http://symfony.com/doc/current/cookbook/event_dispatcher/

– http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html

– http://api.symfony.com/2.4/Symfony/Component/EventDispatcher/EventDispatcher.html

● Doctrine Event Manager– http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/event-listeners.html

– http://www.whitewashing.de/2013/07/24/doctrine_and_domainevents.html

– http://www.doctrine-project.org/api/orm/2.4/class-Doctrine.ORM.EntityManager.html

– http://www.doctrine-project.org/api/common/2.4/class-Doctrine.Common.EventManager.html

Timon Schroeter 110 www.php-schulung.de

Vielen Dank für Eure Aufmerksamkeit!

Timon Schroeter 111 www.php-schulung.de

Fragen? Ideen, Wünsche, Anmerkungen?

top related