Php Yii2依赖项注入、配置和继承
假设我有这样一个配置(来自的代码片段): 我创建了一个名为FancyLinkPager的类:Php Yii2依赖项注入、配置和继承,php,inheritance,dependency-injection,yii2,Php,Inheritance,Dependency Injection,Yii2,假设我有这样一个配置(来自的代码片段): 我创建了一个名为FancyLinkPager的类: class FancyLinkPager extends \yii\widgets\LinkPager { // ... } 当我像这样创建FancyLinkPager类的对象时(请忽略$pagination对象,它在这里是为了正确性): 我的问题是,我希望$fancyLinkPager->maxButtonCount按配置为5。我知道我可以在配置中添加另一行或调整它以指定自定义类,但这不是我
class FancyLinkPager extends \yii\widgets\LinkPager
{
// ...
}
当我像这样创建FancyLinkPager类的对象时(请忽略$pagination对象,它在这里是为了正确性):
我的问题是,我希望$fancyLinkPager->maxButtonCount按配置为5。我知道我可以在配置中添加另一行或调整它以指定自定义类,但这不是我的解决方案,因为:
也许唯一真正的解决方案是创建我自己的yii\di\Container实现,允许从父类继承配置,但在深入研究之前,我想知道我是否忽略了什么。最后,我提出了我自己的di Container实现,引入了新的可配置属性:
public $inheritableDefinitions = [];
完整类别代码:
<?php
namespace app\di;
/**
* @inheritdoc
*/
class Container extends \yii\di\Container
{
/**
* @var array inheritable object configurations indexed by class name
*/
public $inheritableDefinitions = [];
/**
* @inheritdoc
*
* @param string $class
* @param array $params
* @param array $config
*
* @return object the newly created instance of the specified class
*/
protected function build($class, $params, $config) {
$config = $this->mergeInheritedConfiguration($class, $config);
return parent::build($class, $params, $config);
}
/**
* Merges configuration arrays of parent classes into configuration of newly created instance of the specified class.
* Properties defined in child class (via configuration or property declarations) will not get overridden.
*
* @param string $class
* @param array $config
*
* @return array
*/
protected function mergeInheritedConfiguration($class, $config) {
if (empty($this->inheritableDefinitions)) {
return $config;
}
$inheritedConfig = [];
/** @var \ReflectionClass $reflection */
list($reflection) = $this->getDependencies($class);
foreach ($this->inheritableDefinitions as $parentClass => $parentConfig) {
if ($class === $parentClass) {
$inheritedConfig = array_merge($inheritedConfig, $parentConfig);
} else if (is_subclass_of($class, $parentClass)) {
/** @var \ReflectionClass $parentReflection */
list($parentReflection) = $this->getDependencies($parentClass);
// The "@" is necessary because of possible (and wanted) array to string conversions
$notInheritableProperties = @array_diff_assoc($reflection->getDefaultProperties(),
$parentReflection->getDefaultProperties());
// We don't want to override properties defined specifically in child class
$parentConfig = array_diff_key($parentConfig, $notInheritableProperties);
$inheritedConfig = array_merge($inheritedConfig, $parentConfig);
}
}
return array_merge($inheritedConfig, $config);
}
}
现在,如果我创建一个扩展yii\widgets\LinkPager
的类FancyLinkPager
,DI容器将合并默认配置:
$pagination = \Yii::createObject(Pagination::class);
$linkPager = \Yii::createObject(['class' => LinkPager::class, 'pagination' => $pagination]);
$fancyLinkPager = \Yii::createObject(['class' => FancyLinkPager::class, 'pagination' => $pagination]);
$linkPager->maxButtonCount; // 5 as configured
$fancyLinkPager->maxButtonCount; // 5 as configured - hurrah!
我还考虑了类定义中默认属性值的显式设置,因此如果我们将FancyLinkPager
类声明为:
class FancyLinkPager extends LinkPager
{
public $maxButtonCount = 18;
}
将遵守以下属性设置:
$linkPager->maxButtonCount; // 5 as configured
$fancyLinkPager->maxButtonCount; // 18 as declared
要在应用程序中交换默认DI容器,必须在条目脚本中的某个位置显式设置Yii::$container
:
Yii::$container = new \app\di\Container();
我也有同样的问题:我认为不可能配置父类。因此,我的配置有一些冗余设置。。。根据,重写容器可能会导致性能问题,因为。我认为你的构造方法是合理的。如果你想了解这一点,请发布一个答案。感谢@robsch为我指出Yii2的工作人员对此的评论,我自己找不到。这使我认识到,如果配置继承是可选的,并且是有意的,那就最好了。
class FancyLinkPager extends LinkPager
{
public $maxButtonCount = 18;
}
$linkPager->maxButtonCount; // 5 as configured
$fancyLinkPager->maxButtonCount; // 18 as declared
Yii::$container = new \app\di\Container();