我如何让我的PHP IDE了解dependency injection容器?
现状:我在我的项目中有依赖关系,我使用dependency injection来解决。 我想通过使用dependency injection容器(DIC)来缓解我的依赖关系和延迟加载类的pipe理。
我看了Bucket , Pimple和sfServiceContainer ,进行了一些testing,非常感谢DIC的工作。 我可能会去疙瘩,因为它简单和原始的力量。 如果我没有这个问题:
由于DIC提供的抽象,我正在使用的IDE(PHPStorm)不再理解我的代码中发生了什么。 它不明白$ container ['mailer']或$ sc-> mailer是持有一个类对象。 我也尝试过Netbeans IDE:同样的问题。
这对我来说确实是一个问题,因为我的IDE变得毫无用处。 在处理类时,我不想编写没有代码提示,自动完成和重构工具的程序。 我不希望我的IDE在validation代码时发现各种误报。
所以我的问题是:有没有人处理这个问题,并find一个解决scheme?
你可以定义variables的类“手动”:
/** @var YourClassType $mailer */ $mailer = $container['mailer'];
在PhpStorm(以及标准 )中,使用两个星号并在variables的名称之前写入数据types。
您可以写入不带variables名称的数据types(但不包含没有数据types的名称)。
尽pipe每次访问时都可以告诉IDE您的容器中的对象的types,但最好是一次。 以下两种解决scheme都涉及子容器的子类。 我刚开始使用Pimple,build议这样做。
对于使用->
访问的实例成员的容器,或者通过魔术__get
方法公开的__get
,可以告诉你的IDE他们拥有什么types。 这很好,因为它在代码运行时不涉及任何额外的parsing – 只有IDE被它所困扰。
/** * My container. It contains things. Duh. * * @property MyService $service * @property MyDao $dao */ class MyContainer extends Container { }
对于Pimple和其他充当数组的容器,可以为您需要的顶级对象创build访问器函数。 虽然这意味着在创build容器时进行更多的parsing,但应该只执行一次并保存在APC中。 我非常喜欢使用数组访问的方法,因为它将容易忘记的数组键放在自动完成的方法中。
class MyContainer extends Pimple { /** * @return MyService */ public function getMyService() { return $this['service']; } }
顺便说一句,对于在NetBeans中使用@var
types提示内联variables,您需要使用带/*
星号 。 这不是一个文档块的评论,不适用于/**
或/**
。 此外,名称出现在types之前。
public function foo() { /* @var $service MyService */ $service = $container['service']; ... }
由于IDE不执行代码,因此他们不知道需要一些帮助。 我知道这适用于Eclipse和其他IDE:提示variables的types。
Netbeans / Phpstorm / PDT / ZendStudio示例
/* @var $mailer MailerInterface */ $mailer = $sc->mailer
代码完成开始在$mailer
上再次工作。
对于PDT,重要的是:
- 评论仅以一个
*
开始。 - 首先是variables名称,而不是提示。
替代的评论变种
由于它受到了很多讨论,它们在IDE之间可能会有所不同。 但是,大多数IDE支持以上方式的内联代码variables的variables提示。 所以取决于IDE,这可能会写成不同但相似,就像这里前面有两个星号:
/** @var $mailer MailerInterface */
PHPDoc兼容性
如果您为内联代码模拟类var doc-comment,则PHPDocparsing器可能会遇到问题,如下所示:
/** @var MailerInterface $mailer */
该文档通常用于类variables( @var – logging类variables的数据types )。 然后,PHPDoc会在涉及QA负担的注释之后丢失类variables的定义。
但是,有些IDE会为简单variables提供代码完整性,当使用PHPDoc类variables样式编写代码时。 我不知道是否对当前类的代码完成有副作用,然后可能引入一个实际上不存在的新成员。
对于那些从谷歌来到这里的人。
PHPStorm实际上提供了一种方法来解决这种问题,而不是一次又一次地写PHPDocs – 以这里描述的方式创build和设置.phpstorm.meta.php
文件可以顺利地进行自动完成和types检查。
我知道这个问题是关于DIC的,但是有一个Silex Pimple Dumper服务提供者将容器转储到一个json文件。 同一位作者为PHPStorm写了一个插件,它可以读取该文件,并使用服务名称及其types(类,string等)打开自动填充。 我正在使用这两个组件,我可以说是Silex / Pimple自动完成的好select。
疙瘩只是介绍容器制造商的原则。 如果你了解它,你就不需要疙瘩了:
class Container { private $shared = array(); public function getService() { return new Service( this->getFirstDependence(), this->getSecondDependence() ); } protected function getFirstDependence() { return new FirstDependence( this->getSecondDependence() ); } protected function getSecondDependence() { return isset($this->shared[__METHOD__]) ? $this->shared[__METHOD__] : $this->shared[__METHOD__] = new SecondDependence( ); } }
这样Pimple不会隐藏混合$ c ['some key']中的对象types。 编辑容器时,您会有自动完成的build议。 Phpstorm能够从您的代码中自动parsing方法返回types。 你会有清晰的容器。 你可以覆盖容器:
class TestContainer extends Container { protected function getFirstDependence() { return new FirstDependenceMock( ); } }
说实话,用'编程'语言写的容器是错误的路要走。 容器的责任就是把对象的初始化graphics发送给调用者。 使用“编程语言”可以轻松地违反责任。 一些用于configuration依赖关系的DSL更好。 此外,Pimple和sfDepenencyContainer忽略了大多数原始依赖信息(构造函数的参数types提示),使得您的configuration变得臃肿而脆弱。