您可以使用现有的依赖容器之一在那里,如PHP-DI会更好或疙瘩。不过,如果你正在寻找一个简单的解决方案,那么我已经实现了一个依赖容器作为一篇文章,我写在这里的一部分:http://software-architecture-php.blogspot.com/
这里是容器
class Container implements \DecoupledApp\Interfaces\Container\ContainerInterface
{
/**
* This function resolves the constructor arguments and creates an object
* @param string $dataType
* @return mixed An object
*/
private function createObject($dataType)
{
if(!class_exists($dataType)) {
throw new \Exception("$dataType class does not exist");
}
$reflectionClass = new \ReflectionClass($dataType);
$constructor = $reflectionClass->getConstructor();
$args = null;
$obj = null;
if($constructor !== null)
{
$block = new \phpDocumentor\Reflection\DocBlock($constructor);
$tags = $block->getTagsByName("param");
if(count($tags) > 0)
{
$args = array();
}
foreach($tags as $tag)
{
//resolve constructor parameters
$args[] = $this->resolve($tag->getType());
}
}
if($args !== null)
{
$obj = $reflectionClass->newInstanceArgs($args);
}
else
{
$obj = $reflectionClass->newInstanceArgs();
}
return $obj;
}
/**
* Resolves the properities that have a type that is registered with the Container.
* @param mixed $obj
*/
private function resolveProperties(&$obj)
{
$reflectionClass = new \ReflectionClass(get_class($obj));
$props = $reflectionClass->getProperties();
foreach($props as $prop)
{
$block = new \phpDocumentor\Reflection\DocBlock($prop);
//This assumes that there is only one "var" tag.
//If there are more than one, then only the first one will be considered.
$tags = $block->getTagsByName("var");
if(isset($tags[0]))
{
$value = $this->resolve($tags[0]->getType());
if($value !== null)
{
if($prop->isPublic()) {
$prop->setValue($obj, $value);
} else {
$setter = "set".ucfirst($prop->name);
if($reflectionClass->hasMethod($setter)) {
$rmeth = $reflectionClass->getMethod($setter);
if($rmeth->isPublic()){
$rmeth->invoke($obj, $value);
}
}
}
}
}
}
}
/**
*
* @param string $dataType
* @return object|NULL If the $dataType is registered, the this function creates the corresponding object and returns it;
* otherwise, this function returns null
*/
public function resolve($dataType)
{
$dataType = trim($dataType, "\\");
$obj = null;
if(isset($this->singletonRegistry[$dataType]))
{
//TODO: check if the class exists
$className = $this->singletonRegistry[$dataType];
$obj = $className::getInstance();
}
else if(isset($this->closureRegistry[$dataType]))
{
$obj = $this->closureRegistry[$dataType]();
}
else if(isset($this->typeRegistry[$dataType]))
{
$obj = $this->createObject($this->typeRegistry[$dataType]);
}
if($obj !== null)
{
//Now we need to resolve the object properties
$this->resolveProperties($obj);
}
return $obj;
}
/**
* @see \DecoupledApp\Interfaces\Container\ContainerInterface::make()
*/
public function make($dataType)
{
$obj = $this->createObject($dataType);
$this->resolveProperties($obj);
return $obj;
}
/**
*
* @param Array $singletonRegistry
* @param Array $typeRegistry
* @param Array $closureRegistry
*/
public function __construct($singletonRegistry, $typeRegistry, $closureRegistry)
{
$this->singletonRegistry = $singletonRegistry;
$this->typeRegistry = $typeRegistry;
$this->closureRegistry = $closureRegistry;
}
/**
* An array that stores the mappings of an interface to a concrete singleton class.
* The key/value pair corresond to the interface name/class name pair.
* The interface and class names are all fully qualified (i.e., include the namespaces).
* @var Array
*/
private $singletonRegistry;
/**
* An array that stores the mappings of an interface to a concrete class.
* The key/value pair corresond to the interface name/class name pair.
* The interface and class names are all fully qualified (i.e., include the namespaces).
* @var Array
*/
private $typeRegistry;
/**
* An array that stores the mappings of an interface to a closure that is used to create and return the concrete object.
* The key/value pair corresond to the interface name/class name pair.
* The interface and class names are all fully qualified (i.e., include the namespaces).
* @var Array
*/
private $closureRegistry;
}
上面的代码代码可以在这里找到:https://github.com/abdulla16/decoupled-app(在/容器文件夹下)
你可以注册你的依赖作为一个单身,作为一个类型(每次一个新的对象将被实例化),或作为封闭(容器将调用你注册的函数和该函数应该返回实例)。
例如,
$singletonRegistry = array();
$singletonRegistry["DecoupledApp\\Interfaces\\UnitOfWork\\UnitOfWorkInterface"] =
"\\DecoupledApp\\UnitOfWork\\UnitOfWork";
$typeRegistry = array();
$typeRegistry["DecoupledApp\\Interfaces\\DataModel\\Entities\\UserInterface"] =
"\\DecoupledApp\\DataModel\\Entities\\User";
$closureRegistry = array();
$closureRegistry["DecoupledApp\\Interfaces\\DataModel\\Repositories\\UserRepositoryInterface"] =
function() {
global $entityManager;
return $entityManager->getRepository("\\DecoupledApp\\DataModel\\Entities\\User");
};
$container = new \DecoupledApp\Container\Container($singletonRegistry, $typeRegistry, $closureRegistry);
此容器解决了一个类的属性以及构造参数。
香港专业教育学院一直在你的地方,我会建议你在看向[疙瘩DI(http://pimple.sensiolabs.org/)它是一个单独的类(据我记得),它是相对简单。看看它,了解它是如何工作的。这应该有助于你旋转DIC –
你自己的变化你可以看看我的第一个答案在这里,是我前几天提出的解决方案,但我没有发表任何意见,但我仍然不会不知道是否有什么好处,如果你有时间看到它,我会非常想听到你对此的看法。谢谢! –
我注意到的第一件事情之一是你正在大量使用反射,你能解释一下为什么? (虽然我没有深究) –