(meine) wahrheit über symfony€¦ · what if we want unit tests to run fast without waiting for...
TRANSCRIPT
Timon != Timon
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?