public function testPragmatic() { $factory = new Factory(I::class, ['a' => A::class, 'c' => C::class, 'd' => D::class]); $this->assertInstanceOf(A::class, $factory->create('a')); $this->assertInstanceOf(B::class, $factory->create(B::class)); $this->assertInstanceOf(D::class, $factory->create('d')); $this->setExpectedException(FactoryException::class); $c = $factory->create('c'); }
/** * SingletonFactory constructor. * * @param string $baseClassName * @param array $aliases */ public function __construct($baseClassName, $aliases = null) { parent::__construct($baseClassName, $aliases); $this->instances = []; }
/** * @return null|object * @throws Exception * @throws FactoryException */ public function getInstance() { if ($this->persistent && $this->instance !== null) { return $this->instance; } $args = []; foreach ($this->args as $name => $arg) { $value = $arg->getValue(); if ($value === null && !$arg->isOptional()) { throw new DiException("Failed to create instance of {$this->className}: " . "Constructor argument {$name} is has not received any existing value yet. " . "Register a " . $arg->getClassName() . " dependency on the wired container " . " or make the argument optional."); } $args[] = $value !== null ? $value->getInstance() : null; } $instance = Factory::createInstance($this->getClassName(), $args); foreach ($this->setters as $name => $setter) { $value = $setter->getValue(); if ($value !== null) { $instance->{$name}($value->getInstance()); } } if ($this->persistent) { $this->instance = $instance; } return $instance; }
public function create($className, $value) { $args = func_get_args(); array_shift($args); return self::$_typeFactory->createInstance($className, $args); }
public function run(App $previousApp = null) { //Make sure all correct feature aliases are registered $this->_registerFeatureAliases(); //We will sort the features by dependency on other features //and initialize them in the correct order //First we create an instance of all features. /** * @var \Tale\App\FeatureBase[] $features */ $features = []; foreach ($this->getOption('features') as $name => $options) { //Aliases are resolved. $className = $this->_featureFactory->resolveClassName($name); //We don't want duplicate instances. Rather create a new feature //It's better for unique identification if (isset($features[$className])) { throw new RuntimeException("Failed to add feature {$name}({$className}): Feature does already exist"); } //This creates the actual instance via Tale\Factory $feature = $this->_featureFactory->createInstance($className, [$this]); //We can pass a string as the options to use a config file if (is_string($options)) { $feature->appendOptionFile($options, true); } else { if (is_array($options)) { $feature->appendOptions($options, true); } else { throw new RuntimeException("Failed to initialize feature {$name}({$className}): " . "Config needs to be a path to a file or an option array"); } } $features[] = $feature; } //All features are instanced and got all the options they will get //at this point. //Now we sort the features by dependencies. //TODO: Circular dependencies probably f**k up. ArrayUtil::mergeSort($features, [__CLASS__, 'compareFeatures']); $classes = array_map('get_class', $features); $features = array_combine($classes, $features); //Now we can initialize the features //Since our deps are ordered now, we can just iterate foreach ($features as $feature) { //First append our dependencies foreach ($feature->getDependencies() as $name => $className) { if (isset($features[$className])) { $feature->setDependency($name, $features[$className]); } } //Now initialize the feature //This is the possibility to add events etc. $feature->init(); } //This is only sorting! We dont ensure, that the feature exists. //The feature has to do that by itself (through an easy way, look at it) //Put together our event args $args = ['app' => $this, 'previousApp' => $previousApp]; //First, we prepare (and let features prepare) if ($this->emit('beforeRun', new Event\Args($args))) { $this->_setPhpOptions(); //Then we run if ($this->emit('run', new Event\Args($args))) { //Clear our features $this->_features = null; //Allow clean-up at the end (Notice that the "true" //makes it reverse $this->emit('afterRun', new Event\Args($args), true); } } return $this; }