-
-
Save janmarek/623720 to your computer and use it in GitHub Desktop.
Službě lze nastavit: | |
- factory - jméno továrničky | |
- class - jméno třídy | |
- arguments - pole parametrů konstruktoru nebo továrničky | |
- callMethods - pole volaných metod, kterým se také definují argumenty | |
Argumenty: | |
- začíná na $$ - Environment::getConfig | |
- začíná na $ - Environment::getVariable | |
- začíná na % - Context::getService |
<?php | |
// ... | |
$serviceLoader = new ServiceLoader; | |
$serviceLoader->loadNeonConfigFiles(Nette\Environment::getContext(), array( | |
APP_DIR . "/services.neon", | |
)); | |
// ... |
<?php | |
namespace Neuron; | |
use Nette\Environment, Nette\String; | |
use Nette\NeonParser; | |
use Nette\Reflection\ClassReflection; | |
use Nette\IContext; | |
/** | |
* Service loader | |
* | |
* @author Jan Marek | |
*/ | |
class ServiceLoader | |
{ | |
public function loadNeonConfigFiles(IContext $context, array $configFiles) | |
{ | |
$parser = new NeonParser; | |
foreach ($configFiles as $file) { | |
$config = $parser->parse(file_get_contents($file)); | |
$this->loadConfig($context, $config); | |
} | |
} | |
public function loadConfig(IContext $context, $config) | |
{ | |
foreach ($config as $serviceName => $serviceConfig) { | |
if ($context->hasService($serviceName)) { | |
$context->removeService($serviceName); | |
} | |
$options = null; | |
$singleton = isset($serviceConfig["singleton"]) ? (bool) $serviceConfig["singleton"] : true; | |
if (isset($serviceConfig["arguments"]) || isset($serviceConfig["callMethods"])) { | |
$service = array($this, "universalFactory"); | |
if (isset($serviceConfig["class"])) { | |
$options["class"] = $serviceConfig["class"]; | |
} | |
if (isset($serviceConfig["factory"])) { | |
$options["factory"] = $serviceConfig["factory"]; | |
} | |
if (isset($serviceConfig["arguments"])) { | |
$options["arguments"] = $serviceConfig["arguments"]; | |
} | |
if (isset($serviceConfig["callMethods"])) { | |
$options["callMethods"] = $serviceConfig["callMethods"]; | |
} | |
$options["context"] = $context; | |
} elseif (isset($serviceConfig["factory"])) { | |
$service = $serviceConfig["factory"]; | |
} elseif (isset($serviceConfig["class"])) { | |
$service = $serviceConfig["class"]; | |
} | |
$context->addService($serviceName, $service, $singleton, $options); | |
} | |
} | |
public function processArguments($args, IContext $context) | |
{ | |
return array_map(function ($arg) use ($context) { | |
if (!is_string($arg)) { | |
return $arg; | |
} elseif (String::startsWith($arg, "%")) { | |
return $context->getService(substr($arg, 1)); | |
} elseif (String::startsWith($arg, "$$")) { | |
return Environment::getConfig(substr($arg, 2)); | |
} elseif (String::startsWith($arg, "$")) { | |
return Environment::getVariable(substr($arg, 1)); | |
} else { | |
return $arg; | |
} | |
}, $args); | |
} | |
public function universalFactory($options) | |
{ | |
$arguments = isset($options["arguments"]) ? $this->processArguments($options["arguments"], $options["context"]) : array(); | |
if (isset($options["class"])) { | |
if (!empty($arguments)) { | |
$object = ClassReflection::from($options["class"])->newInstanceArgs($arguments); | |
} else { | |
$class = $options["class"]; | |
$object = new $class; | |
} | |
} | |
if (isset($options["factory"])) { | |
$object = call_user_func_array($options["factory"], $arguments); | |
} | |
if (isset($options["callMethods"])) { | |
foreach ($options["callMethods"] as $method => $args) { | |
call_user_func_array(array($object, $method), $this->processArguments($args, $options["context"])); | |
} | |
} | |
return $object; | |
} | |
} |
Doctrine\ORM\EntityManager: | |
factory: ServiceFactories::createEntityManager | |
arguments: [$$database] | |
Nette\Security\IAuthenticator: | |
class: MyApp\Model\Authenticator | |
arguments: [%UserService] | |
UserService: | |
class: MyApp\Model\UserService | |
arguments: [%Doctrine\ORM\EntityManager] | |
ExampleService: | |
class: MyApp\Example | |
arguments: [$tempDir, true] | |
callMethods: | |
setMode: [$exampleMode] | |
setEntityManager: [%Doctrine\ORM\EntityManager] | |
setArray: | |
- [a, b, c] |
Ta neon konfigurace je cool, ale neměl by tohle řešit spíš nějkej "NeonConfigurableContext implements IContext"?
Moc pěkně vymyšlené +1 ... kde se lobuje?
Tak jsem nad tím přemýšlel a souhlasím s mkoubik... Nehceš to sepsat jako RFC na Nette Fóru?
Čau, vytvořil jsem něco podobného:
https://github.com/Dundee/Diphy/tree/nette
Rozdíl je hlavně v tom, že Diphy funguje ve většině případů bez konfigurace.
Příklady:
$di->getService('Example\Application');
Vytvoří instanci třídy Application. Pokud má třída závislosti, musí je vyjmenovat v konstruktoru. Diphy je pak při tvorbě instance sama doplní.
$di->getService('Foo\BarInterface');
Najde a vytvoří instanci implementace rozhraní BarInterface. Pokud má interface více implementací, je nutné zvolit jednu v konfiguraci.
Tajně doufám že něco podobného bude přímo v Nette