Skip to content

Instantly share code, notes, and snippets.

@ngyuki
Last active March 6, 2018 12:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngyuki/7c6648cfc769f8143309 to your computer and use it in GitHub Desktop.
Save ngyuki/7c6648cfc769f8143309 to your computer and use it in GitHub Desktop.
Example of uopz di experimental
<?php
interface SayInterface
{
public function say();
}
class Ore implements SayInterface
{
public function say()
{
return "oreore";
}
}
class Are implements SayInterface
{
private $name;
/**
* @var SayInterface
*/
private $say;
public function __construct($name)
{
$this->name = $name;
}
public function setSay(SayInterface $say)
{
$this->say = $say;
}
public function say()
{
return "$this->name and {$this->say->say()}";
}
}
class Sore implements SayInterface
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function say()
{
return $this->name;
}
}
<?php
require_once __DIR__ . '/uopz-di.php';
require_once __DIR__ . '/uopz-di-classes.php';
///
echo (new Ore())->say() . PHP_EOL;
// oreore
///
Di::register([
'Ore' => [
'class' => 'Are',
'params' => ['are'],
'setters' => [
'setSay' => [Di::lazyNew('Sore')],
],
],
'Sore' => [
'class' => 'Sore',
'params' => ['sore'],
],
]);
echo (new Ore())->say() . PHP_EOL;
// are and sore
///
Di::register([]);
echo (new Ore())->say() . PHP_EOL;
// oreore
///
Di::register([
'Ore' => [
'class' => 'Sore',
'params' => ['dare?'],
],
]);
echo (new Ore())->say() . PHP_EOL;
// dare?
///
echo get_class(new Ore()) . PHP_EOL;
// uopz.Ore.Sore
<?php
class Di
{
private static $instance;
private $config;
private $reflection;
public static function register(array $config)
{
if (isset(self::$instance) == false) {
self::$instance = new self();
}
self::$instance->config = $config;
}
public static function lazyNew($class)
{
return new DiLazyNew($class);
}
protected function __construct()
{
$this->reflection = new \ReflectionClass('ReflectionClass');
uopz_overload(ZEND_NEW, function (&$class) {
$this->overload($class);
});
}
private function overload(&$class)
{
if (isset($this->config[$class]) == false) {
return;
}
$cfg = $this->config[$class];
$orig = $class;
$base = isset($cfg['class']) ? $cfg['class'] : $class;
$class = "uopz.$orig.$base";
if (class_exists($class, false)) {
return;
}
$construct = function ($orig, $obj, $scope) {
$this->construct($orig, $obj, $scope);
};
uopz_compose($class, [$base], [
'__construct' => function () use ($construct) {
list (, $class) = explode('.', get_class($this));
$construct($class, $this, function ($method, $args) {
call_user_func_array(['parent', $method], $args);
});
}
]);
}
private function construct($class, $obj, $scope)
{
$cfg = isset($this->config[$class]) ? $this->config[$class]: [];
$params = isset($cfg['params']) ? $cfg['params'] : [];
$setters = isset($cfg['setters']) ? $cfg['setters'] : [];
if (count($params) || method_exists(get_parent_class($obj), '__construct')) {
$scope('__construct', $this->createArgs($params));
}
foreach ($setters as $methodName => $methodParams) {
$scope($methodName, $this->createArgs($methodParams));
}
}
private function newInstance($class)
{
$cfg = isset($this->config[$class]) ? $this->config[$class]: [];
$class = isset($cfg['class']) ? $cfg['class'] : $class;
$params = isset($cfg['params']) ? $cfg['params'] : [];
$setters = isset($cfg['setters']) ? $cfg['setters'] : [];
/* @var $reflection \ReflectionClass */
$reflection = $this->reflection->newInstance($class);
$obj = $reflection->newInstanceArgs($this->createArgs($params));
foreach ($setters as $methodName => $methodParams) {
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
$method->invokeArgs($obj, $this->createArgs($methodParams));
}
return $obj;
}
private function createArgs($params)
{
$args = [];
foreach ($params as $val) {
if ($val instanceof DiLazyNew) {
$args[] = $this->newInstance($val->getClass());
} else {
$args[] = $val;
}
}
return $args;
}
}
class DiLazyNew
{
private $class;
public function __construct($class)
{
$this->class = $class;
}
public function getClass()
{
return $this->class;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment