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

111
(Meine) Wahrheit über Symfony Timon Schroeter www.php-schulung.de

Upload: others

Post on 11-Aug-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

(Meine) Wahrheit über

SymfonyTimon Schroeter www.php-schulung.de

Page 2: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon != Timon

Page 3: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter

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

Page 4: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Version 4.2 (2002)OOP ?register_globals ?

Page 5: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 6: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want
Page 7: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

OOP

Page 8: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

C++

Page 9: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

C++HPC

Page 10: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

C++HPC fortran

Page 11: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

C++HPC

Matlabfortran

Page 12: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want
Page 13: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

professionell entwickeln

rumbasteln

Page 14: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

TDD

Page 15: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

TDDunit

Page 16: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

TDDunit OOP + DI

Page 17: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Version 2.0 (2011)

Page 18: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

professionell entwickeln

rumbasteln

Page 19: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want
Page 20: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

FormsTWIG

Validation

uvm.

Page 21: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Dependency InjectionContainer

Event Dispatcher

FormsTWIG

Validation

uvm.

Page 22: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want
Page 23: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 23 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ● Prozedural● Objektorientiert

Page 24: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 24 www.php-schulung.de

Was sind die Kennzeichen dieser Paradigmen?

● Imperativ– Sequenz, Schleife, Verzweigung

Page 25: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 26: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 27: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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.

Page 28: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 29: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 30: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 31: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 32: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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)

Page 33: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 33 www.php-schulung.de

Page 34: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 34 www.php-schulung.de

wiederverwendbarunit-testbarGroßteil der Codebasis

Page 35: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 35 www.php-schulung.de

nicht wiederverwendbarnicht unit-testbarMinimum an Code

wiederverwendbarunit-testbarGroßteil der Codebasis

Page 36: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 36 www.php-schulung.de

DependencyInjection

Page 37: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 37 www.php-schulung.de

Dependency Injection

DI

Page 38: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 39: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 40: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 41: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 42: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 43: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 44: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 45: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 46: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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.

Page 47: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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.

Page 48: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 49: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 50: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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)

Page 51: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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.

Page 52: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 53: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 54: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 54 www.php-schulung.de

Page 55: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 55 www.php-schulung.de

Dependency Injection Container

DIC

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

Page 56: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 56 www.php-schulung.de

Page 57: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 57 www.php-schulung.de

Very Many Frameworks support Dependency Injection

Page 58: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 58 www.php-schulung.de

DI is very easy in Symfony 2

Page 59: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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”

Page 60: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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”

Page 61: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 62: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 62 www.php-schulung.de

# php app/console container:debug

Page 63: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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”

Page 64: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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”

Page 65: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 66: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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();}// ...

}

Page 67: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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();}// ...

}

Page 68: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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();}// ...

}

Page 69: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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();}// ...

}

Page 70: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 71: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 71 www.php-schulung.de

Page 72: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 72 www.php-schulung.de

wiederverwendbarunit-testbarGroßteil der Codebasis

Page 73: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 73 www.php-schulung.de

nicht wiederverwendbarnicht unit-testbarMinimum an Code

wiederverwendbarunit-testbarGroßteil der Codebasis

Page 74: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 74 www.php-schulung.de

DependencyInjection

Page 75: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 75 www.php-schulung.de

DependencyInjection

Services

Page 76: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 76 www.php-schulung.deServices

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

$this->get(“logger“)

Page 77: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 77 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

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

Page 78: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 79: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 79 www.php-schulung.de

Page 80: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 80 www.php-schulung.de

Commonly used Types of Events

● Kernel events● Form events● Doctrine events

Page 81: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 81 www.php-schulung.de

Kernel Events

Page 82: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 82 www.php-schulung.de

Kernel Events

Used in SensioFrameworkExtraBundle to act on the @Template annotation.

Page 83: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 84: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 85: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 86: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 87: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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 }

Page 88: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 88 www.php-schulung.de

How to listen to

● Kernel events– listener class + service tag

● Form events● Doctrine events

Page 89: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 90: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 91: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 91 www.php-schulung.de

Time Checkpoint

● Skip?

Page 92: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 92 www.php-schulung.de

Which listeners are active?

● Your answer?

Page 93: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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.

Page 94: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 94 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Page 95: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 95 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Page 96: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 96 www.php-schulung.de

Which listeners are active?

● Symfony profiler > Events

Page 97: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 97 www.php-schulung.de

Which listeners are active?

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

Page 98: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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();

Page 99: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 100: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 101: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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));// ...

Page 102: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 102 www.php-schulung.de

Which listeners are active?

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

Page 103: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

...

Page 104: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 104 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

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

Page 105: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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?

Page 106: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 107: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 107 www.php-schulung.de

Nachhaltige Architektur für große Web-Projekte

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

Page 108: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 109: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

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

Page 110: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 110 www.php-schulung.de

Vielen Dank für Eure Aufmerksamkeit!

Page 111: (Meine) Wahrheit über Symfony€¦ · What if we want unit tests to run fast without waiting for the network? What if we ever want to use a different HTTP client? What if we want

Timon Schroeter 111 www.php-schulung.de

Fragen? Ideen, Wünsche, Anmerkungen?