Stephan Hochdörfer // 23.10.2019
<?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="dependency" class="\My\Dependency"> </service> <service id="manager" class="\My\Manager"> <call method="setDependency"> <argument type="service" id="dependency" /> </call> </service> </services> </container>
<?php use Symfony\Component\DependencyInjection\Reference; // ... $container ->register('dependency', \My\Dependency::class); $container ->register('manager', \My\Manager::class) ->addMethodCall('setDependency', array(new Reference('dependency')));
<?php $manager = new \My\Manager(); $manager->setDependency(new \My\Dependency());
$ composer.phar require bitexpert/disco
<?php require __DIR__ .'/vendor/autoload.php'; use bitExpert\Disco\AnnotationBeanFactory; use bitExpert\Disco\BeanFactoryRegistry; $beanFactory = new AnnotationBeanFactory(Config::class); BeanFactoryRegistry::register($beanFactory);
$beanFactory->get('productService');
$beanFactory->has('productService');
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ public function productService() : ProductService { $db = new Database('mysql://user:secret@localhost/mydb'); return new ProductService($db); } }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php require __DIR__ .'/vendor/autoload.php'; use bitExpert\Disco\AnnotationBeanFactory; use bitExpert\Disco\BeanFactoryRegistry; $beanFactory = new AnnotationBeanFactory(\Demo\Config::class); BeanFactoryRegistry::register($beanFactory);
var_dump($beanFactory->has('productService'));
bool(true)
var_dump($beanFactory->has('database'));
bool(false)
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"singleton" = true}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php var_dump($instance = $beanFactory->get('productService')); var_dump($instance2 = $beanFactory->get('productService'));
object(Demo\ProductService)#9 (0) { } object(Demo\ProductService)#9 (0) { }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"singleton" = false}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php var_dump($instance = $beanFactory->get('productService')); var_dump($instance2 = $beanFactory->get('productService'));
object(Demo\ProductService)#9 (0) { } object(Demo\ProductService)#11 (0) { }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"lazy" = false}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php var_dump($instance = $beanFactory->get('productService'));
object(Demo\ProductService)#9 (0) { }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"lazy" = true}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php var_dump($instance = $beanFactory->get('productService'));
object(ProxyManagerGeneratedProxy\__PM__\ProductService\Gen1d5)#143 (3) { }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"scope" = "request"}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** @Bean */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } /** @Bean({"scope" = "session"}) */ public function productService() : ProductService { return new ProductService($this->database()); } }
<?php use bitExpert\Disco\AnnotationBeanFactory; use bitExpert\Disco\BeanFactoryRegistry; $config = new \bitExpert\Disco\BeanFactoryConfiguration( sys_get_temp_dir() ); $beanFactory = new AnnotationBeanFactory(Config::class, [], $config); BeanFactoryRegistry::register($beanFactory);
$beanStore = serialize($config->getBeanStore());
<?php use bitExpert\Disco\AnnotationBeanFactory; use bitExpert\Disco\BeanFactoryRegistry; $config = new \bitExpert\Disco\BeanFactoryConfiguration( sys_get_temp_dir() ); $beanFactory = new AnnotationBeanFactory(Config::class, [], $config); BeanFactoryRegistry::register($beanFactory);
$beanStore = unserialize($beanStore); $config->setBeanStore($beanStore);
var_dump($instance = $beanFactory->get('productService'));
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; use bitExpert\Disco\Annotations\Parameter; /** @Configuration */ class Config { /** * @Bean({ * "parameters"={ * @Parameter({"name" = "db.dsn"}) * } * }) */ protected function database($dsn = '') : Database { return new Database($dsn); } // [...] }
<?php $config = [ 'db' => [ 'dsn' => 'mysql://user:secret@localhost/mydb' ] ]; $beanFactory = new AnnotationBeanFactory(Config::class, $config); BeanFactoryRegistry::register($beanFactory);
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; use bitExpert\Disco\Annotations\Parameter; /** @Configuration */ class Config { /** * @Bean({ * "parameters"={ * @Parameter({"name" = "db.dsn", "default" = "mysql://..."}) * } * }) */ protected function database($dsn = '') : Database { return new Database($dsn); } // [...] }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; use bitExpert\Disco\Annotations\Parameter; /** @Configuration */ class Config { // [...] /** @Bean */ public function productService() : ProductService { // no need to pass parameters to the database method! return new ProductService($this->database()); } }
$ composer.phar require vlucas/phpdotenv
DB_DSN="mysql://user:secret@localhost/mydb"
<?php require __DIR__ .'/vendor/autoload.php'; use bitExpert\Disco\AnnotationBeanFactory; use bitExpert\Disco\BeanFactoryRegistry; $dotenv = new Dotenv\Dotenv(__DIR__); $dotenv->load(); $beanFactory = new AnnotationBeanFactory(Config::class, $_ENV); BeanFactoryRegistry::register($beanFactory);
<?php use bitExpert\Disco\Annotations\Alias; use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** * @Bean({ * "aliases"={ * @Alias({"name" = "\Identifier\With\Namespace"}) * } * }) */ public function productService() : ProductService {} // [...] }
<?php var_dump($instance = $beanFactory->get('productService')); var_dump($instance2 = $beanFactory->get('\Identifier\With\Namespace'));
object(Demo\ProductService)#9 (0) { } object(Demo\ProductService)#9 (0) { }
<?php use bitExpert\Disco\Annotations\Alias; use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** * @Bean({ * "aliases"={ * @Alias({"type" = true}) * } * }) */ public function productService() : ProductService {} // [...] }
<?php var_dump($instance = $beanFactory->get('\Demo\ProductService'));
object(Demo\ProductService)#9 (0) { }
<?php use bitExpert\Disco\Annotations\Alias; use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class Config { /** * @Bean({ * "aliases"={ * @Alias({"alias" = "\My\Db"}) * } * }) */ protected function database() : Database { return new Database('mysql://user:secret@localhost/mydb'); } }
<?php var_dump($instance = $beanFactory->get('\My\Db'));
object(Demo\Database)#11 (0) { }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class BeanConfiguration { /** @Bean */ protected function database() : Database {} /** @Bean */ public function productRepository() : productRepository {} /** @Bean */ public function productService() : ProductService {} /** @Bean */ public function productAction() : ProductAction {} }
/home/shochdoerfer/Workspace/disco-demo |-src |---Demo |-----Config.php |-----SliceA |-------SliceAConfigTrait.php |-----SliceB |-------SliceBConfigTrait.php |-----SliceC |-------SliceCConfigTrait.php
<?php use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class BeanConfiguration { use ProductSlice; }
<?php use bitExpert\Disco\Annotations\Bean; trait ProductSlice { /** @Bean */ public function productService() : ProductService { $db = new Database('mysql://user:secret@localhost/mydb'); return new ProductService($db); } }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class BeanConfiguration { use ProductSlice; /** @Bean */ public function productService() : ProductService { return new CustomProductService(); } }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\Configuration; /** @Configuration */ class BeanConfigurationForTests extends BeanConfiguration { /** @Bean */ public function productService() : ProductService { return new ImpossibleToMockProductService(); } }
<?php namespace bitExpert\Disco; interface BeanPostProcessor { /** * Apply this BeanPostProcessor to the given new bean instance * after the bean got created. * * @param object $bean * @param string $beanName */ public function postProcess($bean, $beanName); }
<?php use bitExpert\Disco\BeanPostProcessor; class DatabaseBeanCharSetPostProcessor implements BeanPostProcessor { protected $charset; public function __construct($charset) { $this->charset = $charset } public function postProcess($bean, $beanName) { if ($bean instanceof Database) { $bean->setCharset($this->charset); } } }
<?php use bitExpert\Disco\Annotations\Bean; use bitExpert\Disco\Annotations\BeanPostProcessor; use bitExpert\Disco\Annotations\Configuration; use bitExpert\Disco\Annotations\Parameter; /** @Configuration */ class Config { /** * @BeanPostProcessor({ * "parameters"={ * @Parameter({"name" = "db.charset"}) * } * }) */ public function charset($cst = '') : DatabaseBeanCharSetPostProcessor { return new DatabaseBeanCharSetPostProcessor($cst); } }
<?php $projectTmpDir = '/some/path/on/the/server/'; $config = new \bitExpert\Disco\BeanFactoryConfiguration($projectTmpDir); $config->setProxyAutoloader( new \ProxyManager\Autoloader\Autoloader( new \ProxyManager\FileLocator\FileLocator($projectTmpDir), new \ProxyManager\Inflector\ClassNameInflector('Disco') ) ); $beanFactory = new \bitExpert\Disco\AnnotationBeanFactory(Config::class, [],$config); BeanFactoryRegistry::register($beanFactory);
sitepoint.com: A Fresh Look at Dependency Injection
php[architect]: Your Dependency Injection Needs a Disco