+ All Categories
Home > Software > Nette framework - How to compile an extensible di container

Nette framework - How to compile an extensible di container

Date post: 20-Mar-2017
Category:
Upload: filip-prochazka
View: 417 times
Download: 1 times
Share this document with a friend
45
Nette Framework How to compile an extensible DI Container @ProchazkaFilip
Transcript
Page 1: Nette framework - How to compile an extensible di container

Nette FrameworkHow to compile an extensible DI Container

@ProchazkaFilip

Page 2: Nette framework - How to compile an extensible di container

Co si povíme?

- Ujasníme si pojmy- Koukneme jak funguje DI v Nette- Ukážeme si jak napsat rozšíření

Page 3: Nette framework - How to compile an extensible di container

Pojmy

- Dependency Injection Container- služba- rozšíření- neon

Page 4: Nette framework - How to compile an extensible di container

Jak to funguje v Nette?Ale než postoupíme,

je všechno jasné?

Page 5: Nette framework - How to compile an extensible di container

DI\Containerclass Container

{

function getParameters();

function addService($name, $service);

function getService($name);

function getByType($class, $need = TRUE);

Page 6: Nette framework - How to compile an extensible di container

Jak se to používá?

$container = new Container();

$container->addService('app, new Application);

$app = $container->getService('app');

Page 7: Nette framework - How to compile an extensible di container

To asi nebude ideální

Vytvořit instance 500 tříd na každý request?To nechceš.

Page 8: Nette framework - How to compile an extensible di container

Řešenímje kompilace DIC!

Page 9: Nette framework - How to compile an extensible di container

app/bootstrap.php$c = new Nette\Configurator;

$c->setTempDirectory(__DIR__ . '/../temp');

$c->addConfig(__DIR__ . '/config/config.neon');

$c->addConfig(__DIR__ . '/config/config.local.neon');

$container = $configurator->createContainer();

Page 10: Nette framework - How to compile an extensible di container

new Nette\Configurator

- vyřeší výchozí parametry

Page 11: Nette framework - How to compile an extensible di container

->setTempDirectory()

- nastaví temp složku- nastaví parametr tempDir

Page 12: Nette framework - How to compile an extensible di container

->addConfig()

- přidá neon/ini/php config

Page 13: Nette framework - How to compile an extensible di container

->createContainer()

Page 14: Nette framework - How to compile an extensible di container

->createContainer()

Zkusí jestli už zkompilovaný container existuje

- pokud ano, tak vytvoří instanci.- pokud ne, tak zkompiluje container

a vytvoří instanci

Page 15: Nette framework - How to compile an extensible di container

Kompilace pohledem z dálky

- nakonfiguruje se ContainerBuilder- Nette vygeneruje PHP třídu- uloží do tempu- profit

Page 16: Nette framework - How to compile an extensible di container

Co se vygeneruje?class SystemContainer extends Nette\DI\Container {

protected $meta = array(

'types' => array(),

'services' => array(),

'tags' => array()

);

public function __construct() {

parent::__construct(array(/* parameters */));

}

Page 17: Nette framework - How to compile an extensible di container

Co se vygeneruje?class SystemContainer extends Nette\DI\Container {

public function createServiceApplication()

{

$service = new Nette\Application\Application(

$this->getService('nette.presenterFactory'), ...

);

$service->catchExceptions = FALSE;

$service->errorPresenter = 'Front:Error';

return $service;

}

Page 18: Nette framework - How to compile an extensible di container

Jak se to používá?$app = $container

->getService('application');

use Nette\Application\Application;

$app = $container

->getByType(Application::class);

Page 19: Nette framework - How to compile an extensible di container

Proces kompilaceAle než postoupíme,

je všechno jasné?

Page 20: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- načte configy a všechny je spojí do pole- expandne parametry

parameters:

imageDir: %wwwDir%/images

Page 21: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- zavolá všechna rozšíření- Nette samo sebe konfiguruje rozšířenímy

$ext->loadConfiguration()

Page 22: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- projde služby z configu

services:

- App\UserManager

Page 23: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- zavolá všechna rozšíření

$ext->beforeCompile()

Page 24: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- autowiring- vygeneruje PHP třídu SystemContainer

Page 25: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- zavolá všechna rozšíření

$ext->afterCompile($class)

Page 26: Nette framework - How to compile an extensible di container

Kompilace DI Containeru

- uložit do tempu- profit

Page 27: Nette framework - How to compile an extensible di container

Jak fungují rozšířeníAle než postoupíme,

je všechno jasné?

Page 28: Nette framework - How to compile an extensible di container

Každé rozšíření

- pracuje s ContainerBuilder- dědí od Nette\DI\CompilerExtension- má “dynamické” jméno- má vlastní sekci v configu

Page 29: Nette framework - How to compile an extensible di container

ContainerBuilderclass ContainerBuilder

{

/** @return ServiceDefinition */

function addDefinition($name, $definition = NULL);

/** @return ServiceDefinition */

function getDefinition($name);

/** @return ServiceDefinition[] */

function getDefinitions();

function removeDefinition($name);

Page 30: Nette framework - How to compile an extensible di container

ContainerBuilderclass ContainerBuilder

{

/** @return string service name or NULL */

function getByType($class);

/** @return string[] */

function findByType($class, $autowired = TRUE);

/** @return array of [service name => tag attributes] */

function findByTag($tag);

Page 31: Nette framework - How to compile an extensible di container

ContainerBuilderclass ContainerBuilder

{

public $parameters = array();

function expand($value);

function addExcludedClasses(array $classes);

function addDependency($file);

/** @return Nette\PhpGenerator\PhpLiteral */

static function literal($phpCode);

Page 32: Nette framework - How to compile an extensible di container

ServiceDefinitionclass ServiceDefinition extends Nette\Object {

public $class;

public $factory;

public $setup = array();

public $parameters = array();

public $tags = array();

public $autowired = TRUE;

public $dynamic = FALSE;

public $implement;

public $implementType;

Page 33: Nette framework - How to compile an extensible di container

Registrace rozšířeníextensions:

doctrine: Kdyby\Doctrine\DI\OrmExtension

doctrine:

host: 127.0.0.1

user: root

password: heslo

Page 34: Nette framework - How to compile an extensible di container

Extension points of extensions

- loadConfiguration()- pouze na zpracování configu a přidávání služeb

- beforeCompiler()- modifikace existujících služeb, nepřidávat nové!

- afterCompile()- modifikace vygenerovaného kódu

Page 35: Nette framework - How to compile an extensible di container

Rozumné výchozí hodnoty

public $defaults = array(

'catchExceptions' => "%productionMode%",

);

Page 36: Nette framework - How to compile an extensible di container

loadConfiguration()

public function loadConfiguration()

{

$builder = $this->getContainerBuilder();

$config = $this->getConfig($this->defaults);

// ...

Page 37: Nette framework - How to compile an extensible di container

loadConfiguration()

Validators::assertField($config,

'catchExceptions', 'bool');

$builder

->addDefinition($this->prefix('application'))

->setClass('Nette\Application\Application')

->addSetup('$catchExceptions',

array($config['catchExceptions']));

Page 38: Nette framework - How to compile an extensible di container

beforeCompile()

public function beforeCompile()

{

$builder = $this->getContainerBuilder();

// ...

Page 39: Nette framework - How to compile an extensible di container

beforeCompile()

$manager = $builder->getDefinition($this->prefix('manager'));

$services = $builder->findByTag(self::TAG_SUBSCRIBER);

foreach ($services as $serviceName => $meta) {

$manager->addSetup('addEventSubscriber',

array('@' . $serviceName));

}

Page 40: Nette framework - How to compile an extensible di container

afterCompile($class)use Nette\PhpGenerator as Code;

public function afterCompile(Code\ClassType $class)

{

$config = $this->getConfig();

$initialize = $class->methods['initialize'];

$initialize->addBody('date_default_timezone_set(?);',

array($config['date.timezone']));

Page 41: Nette framework - How to compile an extensible di container

Závislosti rozšíření

- například BlogExtension, který potřebuje OrmExtension

- vyřešilo se to změnou přístupu- dva přístupy

- ask (starý)- tell (lepší)

Page 42: Nette framework - How to compile an extensible di container

Závislosti rozšíření - askuse Kdyby\Doctrine\DI\IDatabaseTypeProvider;

$exts = $this->compiler

->getExtensions(IDatabaseTypeProvider::class);

foreach ($exts as $ext) {

$types = $ext->getDatabaseTypes();

// ...

Page 43: Nette framework - How to compile an extensible di container

Závislosti rozšíření - telluse Kdyby\Doctrine\DI\OrmExtension;

$exts = $this->compiler

->getExtensions(OrmExtension::class);

$exts[0]->addDatabaseType($metadata);

Page 44: Nette framework - How to compile an extensible di container

Dotazy?

Page 45: Nette framework - How to compile an extensible di container

Díky za pozornost!filip-prochazka.com

Follow me maybe? @ProchazkaFilip


Recommended