<?php
class A {
}
class B {
public $a;
public function __construct(A $a) {
$this->a = $a;
}
}
class C {
public $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class D {
public $c;
public function __construct(C $c) {
$this->c = $c;
}
}
class E {
public $d;
public function __construct(D $d) {
$this->d = $d;
}
}
class F {
public $e;
public function __construct(E $e) {
$this->e = $e;
}
}
class G {
public $f;
public function __construct(F $f) {
$this->f = $f;
}
}
class H {
public $g;
public function __construct(G $g) {
$this->g = $g;
}
}
class I {
public $h;
public function __construct(H $h) {
$this->h = $h;
}
}
class J {
public $i;
public function __construct(I $i) {
$this->i = $i;
}
}
class K {
public $j;
public function __construct(K $k) {
$this->k = $k;
}
}
class Dice {
private $rules = [];
private $cache = [];
private $instances = [];
public function addRule($name, Rule $rule) {
$this->rules[ltrim($name, '\\')] = $rule;
}
public function getRule($name) {
if (isset($this->rules[ltrim($name, '\\')])) return $this->rules[ltrim($name, '\\')];
foreach ($this->rules as $key => $rule) {
if ($rule->instanceOf === null && $key !== '*' && is_subclass_of($name, $key) && $rule->inherit === true) return $rule;
}
return isset($this->rules['*']) ? $this->rules['*'] : new Rule;
}
public function create($component, array $args = [], $forceNewInstance = false) {
if (!$forceNewInstance && isset($this->instances[$component])) return $this->instances[$component];
if (!isset($this->cache[$component])) {
$rule = $this->getRule($component);
$class = new \ReflectionClass(empty($rule->instanceOf) ? $component : $rule->instanceOf);
$constructor = $class->getConstructor();
$params = $constructor ? $this->getParams($constructor, $rule) : null;
$this->cache[$component] = function($args, $forceNewInstance) use ($component, $rule, $class, $constructor, $params) {
if ($rule->shared) {
if ($constructor) {
try {
$this->instances[$component] = $object = $class->newInstanceWithoutConstructor();
$constructor->invokeArgs($object, $params($args));
} catch (\ReflectionException $r) {
$this->instances[$component] = $object = $class->newInstanceArgs($params($args));
}
} else {
$this->instances[$component] = $object = $class->newInstanceWithoutConstructor();
}
}
else $object = $params ? $class->newInstanceArgs($params($args)) : new $class->name;
if (!empty($rule->call)) foreach ($rule->call as $call) $class->getMethod($call[0])->invokeArgs($object, call_user_func($this->getParams($class->getMethod($this->expand($call[0])), new Rule), $call[1]));
return $object;
};
}
return $this->cache[$component]($args, $forceNewInstance);
}
private function expand($param, array $share = []) {
if (is_array($param)) return array_map(function($p) use($share) { return $this->expand($p, $share); }, $param);
if ($param instanceof Instance) return $this->create($param->name, $share);
else if (is_callable($param)) return $param($this);
return $param;
}
private function getParams(\ReflectionMethod $method, Rule $rule) {
$subs = empty($rule->substitutions) ? null :$rule->substitutions;
$paramClasses = [];
foreach ($method->getParameters() as $param) $paramClasses[] = $param->getClass() ? $param->getClass()->name : null;
return function($args) use ($paramClasses, $rule, $subs) {
$share = empty($rule->shareInstances) ? [] : array_map([$this, 'create'], $rule->shareInstances);
if (!empty($share) || !empty($rule->constructParams)) $args = array_merge($args, $this->expand($rule->constructParams, $share), $share);
$parameters = [];
foreach ($paramClasses as $class) {
if (!empty($args)) for ($i = 0; $i < count($args); $i++) {
if ($class && $args[$i] instanceof $class) {
$parameters[] = array_splice($args, $i, 1)[0];
continue 2;
}
}
if (!empty($subs) && isset($subs[$class])) $parameters[] = is_string($subs[$class]) ? $this->create($subs[$class]) : $this->expand($subs[$class]);
else if (!empty($class)) $parameters[] = $this->create($class, $share, !empty($rule->newInstances) && in_array(strtolower($class), array_map('strtolower', $rule->newInstances)));
else if (!empty($args)) $parameters[] = array_shift($args);
}
return $parameters;
};
}
}
class Rule {
public $shared = false;
public $constructParams = [];
public $substitutions = [];
public $newInstances = [];
public $instanceOf;
public $call = [];
public $inherit = true;
public $shareInstances = [];
}
class Instance {
public $name;
public function __construct($instance) {
$this->name = $instance;
}
}
class Dice2 {
private $rules = [];
private $cache = [];
private $instances = [];
public function addRule($name, Rule $rule) {
$this->rules[ltrim($name, '\\')] = $rule;
}
public function getRule($name) {
if (isset($this->rules[ltrim($name, '\\')])) return $this->rules[ltrim($name, '\\')];
foreach ($this->rules as $key => $rule) {
if ($rule->instanceOf === null && $key !== '*' && is_subclass_of($name, $key) && $rule->inherit === true) return $rule;
}
return isset($this->rules['*']) ? $this->rules['*'] : new Rule;
}
public function create($component, array $args = [], $forceNewInstance = false) {
if (!$forceNewInstance && isset($this->instances[$component])) return $this->instances[$component];
if (!isset($this->cache[$component])) {
$rule = $this->getRule($component);
$class = new \ReflectionClass(empty($rule->instanceOf) ? $component : $rule->instanceOf);
$constructor = $class->getConstructor();
$params = $constructor ? $this->getParams($constructor, $rule) : null;
$this->cache[$component] = function($args, $forceNewInstance) use ($component, $rule, $class, $constructor, $params) {
if ($rule->shared) {
$this->instances[$component] = $object = $class->isInternal() && $constructor ? $class->newInstanceArgs($params($args)) : $class->newInstanceWithoutConstructor();
if ($constructor && !$class->isInternal()) $constructor->invokeArgs($object, $params($args));
}
else $object = $params ? new $class->name(...$params($args)) : new $class->name;
if (!empty($rule->call)) foreach ($rule->call as $call) $class->getMethod($call[0])->invokeArgs($object, call_user_func($this->getParams($class->getMethod($this->expand($call[0])), new Rule), $call[1]));
return $object;
};
}
return $this->cache[$component]($args, $forceNewInstance);
}
private function expand($param, array $share = []) {
if (is_array($param)) return array_map(function($p) use($share) { return $this->expand($p, $share); }, $param);
if ($param instanceof Instance) return $this->create($param->name, $share);
else if (is_callable($param)) return $param($this);
return $param;
}
private function getParams(\ReflectionMethod $method, Rule $rule) {
$subs = empty($rule->substitutions) ? null :$rule->substitutions;
$paramClasses = [];
foreach ($method->getParameters() as $param) $paramClasses[] = $param->getClass() ? $param->getClass()->name : null;
return function($args) use ($paramClasses, $rule, $subs) {
$share = empty($rule->shareInstances) ? [] : array_map([$this, 'create'], $rule->shareInstances);
if (!empty($share) || !empty($rule->constructParams)) $args = array_merge($args, $this->expand($rule->constructParams, $share), $share);
$parameters = [];
foreach ($paramClasses as $class) {
if (!empty($args)) for ($i = 0; $i < count($args); $i++) {
if ($class && $args[$i] instanceof $class) {
$parameters[] = array_splice($args, $i, 1)[0];
continue 2;
}
}
if (!empty($subs) && isset($subs[$class])) $parameters[] = is_string($subs[$class]) ? $this->create($subs[$class]) : $this->expand($subs[$class]);
else if (!empty($class)) $parameters[] = $this->create($class, $share, !empty($rule->newInstances) && in_array(strtolower($class), array_map('strtolower', $rule->newInstances)));
else if (!empty($args)) $parameters[] = array_shift($args);
}
return $parameters;
};
}
}
$dice1 = new Dice;
$dice2 = new Dice2;
$j1 = $dice1->create('J');
$j2 = $dice2->create('J');
$t1 = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$j = $dice1->create('J');
}
$t2 = microtime(true);
echo 'dice1: ' . ($t2 - $t1) . "\n\n";
$t1 = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$j = $dice2->create('J');
}
$t2 = microtime(true);
echo 'dice1: ' . ($t2 - $t1) . "\n\n";
- Output for 7.4.0
- dice1: 0.10630488395691
dice1: 0.10661721229553
- Output for 7.3.12
- dice1: 0.14965200424194
dice1: 0.13864493370056
- Output for 7.3.11
- dice1: 0.11842799186707
dice1: 0.10567712783813
- Output for 7.3.10
- dice1: 0.10418486595154
dice1: 0.10264301300049
- Output for 7.3.9
- dice1: 0.13548111915588
dice1: 0.09322714805603
- Output for 7.3.8
- dice1: 0.096839189529419
dice1: 0.10510301589966
- Output for 7.3.7
- dice1: 0.089824914932251
dice1: 0.098773956298828
- Output for 7.3.6
- dice1: 0.11837983131409
dice1: 0.13049793243408
- Output for 7.3.5
- dice1: 0.10363411903381
dice1: 0.091729879379272
- Output for 7.3.4
- dice1: 0.091386795043945
dice1: 0.091121196746826
- Output for 7.3.3
- dice1: 0.10534501075745
dice1: 0.098872184753418
- Output for 7.3.2
- dice1: 0.096735000610352
dice1: 0.1175971031189
- Output for 7.3.1
- dice1: 0.099518060684204
dice1: 0.098044872283936
- Output for 7.3.0
- dice1: 0.12313079833984
dice1: 0.10568785667419
- Output for 7.2.25
- dice1: 0.18495893478394
dice1: 0.14590096473694
- Output for 7.2.24
- dice1: 0.13322615623474
dice1: 0.11851811408997
- Output for 7.2.23
- dice1: 0.11774301528931
dice1: 0.12574887275696
- Output for 7.2.22
- dice1: 0.13632702827454
dice1: 0.11550378799438
- Output for 7.2.21
- dice1: 0.13289308547974
dice1: 0.11219477653503
- Output for 7.2.20
- dice1: 0.1131739616394
dice1: 0.11200213432312
- Output for 7.2.19
- dice1: 0.11444616317749
dice1: 0.11965203285217
- Output for 7.2.18
- dice1: 0.13879203796387
dice1: 0.11075806617737
- Output for 7.2.17
- dice1: 0.12527704238892
dice1: 0.15454888343811
- Output for 7.2.0
- dice1: 0.064551115036011
dice1: 0.060163021087646
- Output for 7.1.33
- dice1: 0.15738916397095
dice1: 0.1514778137207
- Output for 7.1.32
- dice1: 0.16988587379456
dice1: 0.16224312782288
- Output for 7.1.31
- dice1: 0.20651006698608
dice1: 0.1558690071106
- Output for 7.1.30
- dice1: 0.21288418769836
dice1: 0.16103601455688
- Output for 7.1.29
- dice1: 0.14858412742615
dice1: 0.14405989646912
- Output for 7.1.28
- dice1: 0.14898610115051
dice1: 0.14545917510986
- Output for 7.1.27
- dice1: 0.18032503128052
dice1: 0.1451210975647
- Output for 7.1.26
- dice1: 0.15536499023438
dice1: 0.14334106445312
- Output for 7.1.7
- dice1: 0.084866046905518
dice1: 0.063967943191528
- Output for 7.1.6
- dice1: 0.10573196411133
dice1: 0.071253061294556
- Output for 7.1.5
- dice1: 0.11230897903442
dice1: 0.073814868927002
- Output for 7.1.0
- dice1: 0.12423610687256
dice1: 0.090756177902222
- Output for 7.0.20
- dice1: 0.084161996841431
dice1: 0.071856021881104
- Output for 7.0.14
- dice1: 0.13094687461853
dice1: 0.092476844787598
- Output for 7.0.12
- dice1: 0.13531708717346
dice1: 0.09647011756897
- Output for 7.0.11
- dice1: 0.13359093666077
dice1: 0.094380140304565
- Output for 7.0.10
- dice1: 0.12842607498169
dice1: 0.095478057861328
- Output for 7.0.9
- dice1: 0.12905192375183
dice1: 0.093661069869995
- Output for 7.0.8
- dice1: 0.13105893135071
dice1: -0.32270884513855
- Output for 7.0.7
- dice1: 0.1290340423584
dice1: 0.092841863632202
- Output for 7.0.6
- dice1: 0.13251709938049
dice1: 0.094222068786621
- Output for 7.0.5
- dice1: 0.13619804382324
dice1: 0.096045017242432
- Output for 7.0.4
- dice1: 0.13443398475647
dice1: 0.09463095664978
- Output for 7.0.3
- dice1: 0.13024592399597
dice1: 0.094304084777832
- Output for 7.0.2
- dice1: 0.12329816818237
dice1: 0.087915897369385
- Output for 7.0.1
- dice1: 0.1336190700531
dice1: 0.094938039779663
- Output for 7.0.0
- dice1: 0.13061189651489
dice1: 0.090490102767944
- Output for 5.6.28
- dice1: 0.26062178611755
dice1: -0.14304184913635
- Output for 5.6.26
- dice1: 0.24897503852844
dice1: 0.18410587310791
- Output for 5.6.25
- dice1: 0.1046290397644
dice1: 0.18799090385437
- Output for 5.6.24
- dice1: -0.17196893692017
dice1: 0.18747711181641
- Output for 5.6.23
- dice1: 0.2396411895752
dice1: 0.18644285202026
- Output for 5.6.22
- dice1: -0.0076589584350586
dice1: 0.18979811668396
- Output for 5.6.21
- dice1: 0.22951912879944
dice1: 0.18392109870911
- Output for 5.6.20
- dice1: 0.24075293540955
dice1: 0.17688918113708
- Output for 5.6.19
- dice1: 0.21180200576782
dice1: 0.18238687515259
- Output for 5.6.18
- dice1: 0.24832487106323
dice1: 0.18479514122009
- Output for 5.6.17
- dice1: 0.24313902854919
dice1: 0.18330597877502
- Output for 5.6.16
- dice1: 0.01963996887207
dice1: 0.18193483352661
- Output for 5.6.15
- dice1: 0.24191999435425
dice1: 0.18578004837036
- Output for 5.6.14
- dice1: 0.23551607131958
dice1: 0.17615509033203
- Output for 5.6.13
- dice1: 0.24272704124451
dice1: 0.18653321266174
- Output for 5.6.12
- dice1: 0.00023794174194336
dice1: 0.18666696548462
- Output for 5.6.11
- dice1: 0.24220204353333
dice1: -0.65352082252502
- Output for 5.6.10
- dice1: 0.24377989768982
dice1: 0.18662810325623
- Output for 5.6.9
- dice1: 0.24490118026733
dice1: 0.18643689155579
- Output for 5.6.8
- dice1: 0.24054789543152
dice1: 0.18914699554443
- Output for 5.6.7
- dice1: 0.054921865463257
dice1: 0.17948293685913
- Output for 5.6.6
- dice1: 0.24124503135681
dice1: -0.65244889259338
- Output for 5.6.5
- dice1: 0.23896503448486
dice1: 0.18144798278809
- Output for 5.6.4
- dice1: 0.24649810791016
dice1: 0.18099403381348
- Output for 5.6.3
- dice1: 0.14708805084229
dice1: 0.18333005905151
- Output for 5.6.2
- dice1: 0.23519492149353
dice1: -0.35163497924805
- Output for 5.6.1
- dice1: 0.24672508239746
dice1: 0.18249201774597
- Output for 5.6.0
- dice1: 0.21862506866455
dice1: 0.18244504928589
- Output for 5.5.0 - 5.5.38
- Parse error: syntax error, unexpected '.' in /in/BlXCT on line 222
Process exited with code 255. - Output for 5.4.0 - 5.4.45
- Parse error: syntax error, unexpected '.', expecting ')' in /in/BlXCT on line 222
Process exited with code 255.
preferences:
136.43 ms | 401 KiB | 167 Q