PHPStorm 自动完成数组键(动态插入)

标签 php dependency-injection inversion-of-control phpstorm pimple

我正在使用 Pimple 依赖注入(inject)器,每次我使用容器中的依赖项时,我都会忍不住仔细检查用于获取依赖项的 key 的拼写:

$ioc = new Pimple();

// 1. Define some object
$ioc["some-key"] = $ioc->share(function($c){ /* ... */});

// 2. Use it
$ioc["som... // Open config file and check spelling...

PHPStorm 是否有某种方法可以查找这些属性并提供自动完成功能?我考虑过使用类似的东西定义所有这些键

define('SOME_KEY', 'some-key');

// ...

$ioc[SOME_KEY] = $ioc->share(/* ... */);

但我想知道是否有更好的方法。

编辑

下面是一些示例代码:

// project_root/library/App/Injector/Ioc.php
require_once "Pimple.php";

/** @var array|Pimple $ioc */
$ioc = new Pimple();

$ioc["version"] = "1.0.1650.63";

$ioc["location-service"] = $ioc->share(function ($c) {
     return new Application_Service_Location();
   }
);

事实证明,无论我是否在 $ioc 声明同一文件之前包含/** @var array|Pimple $ioc */,字符串自动完成都可以正常工作,因为 $ioc 是宣布。但是,由于我使用的是 Zend Framework,因此我通常会这样使用 $ioc:

// project_root/Application/Bootstrap.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
   protected function _initInjector() {
     $ioc = null;
     require_once LIBRARY_PATH . "/MFM/Injector/ioc.php";
     Zend_Registry::set("ioc", $ioc);
   }
}

// project_root/Application/Controllers/SomeController.php
class Application_Controller_SomeController extends Zend_Controller_Action {
   public function IndexAction() {
      /** @var Pimple $ioc */
      $ioc = Zend_Registry::get("ioc");

      // No IDE assistance for the string "location-service"
      $service = $ioc["location-service"];
   }
}

最佳答案

我目前为 PhpStorm 使用 DynamicReturnTypePlugin 并且在我的 dynamicReturnTypeMeta.json 中有以下配置:

{
    "methodCalls": [
        {
            "class": "\\MyOwnWrapperOfDIContainer",
            "method": "get",
            "position": 0
        },
        {
            "class": "\\Pimple\\Container",
            "method": "offsetGet",
            "position": 0
        }
    ]
}

此配置意味着以下内容:无论何时在代码中,我都将 Pimple\Container 类型的任何变量用作数组(这将调用其 ArrayAccess::offsetGet 方法),那么 PhpStorm 应该考虑返回值是访问该数组时用作键的类型。一世。即:

$c = new Pimple\Container;
$c['MyClass']->/*here autocompletion works*/methodOfMyClass();

我也是这么用的:

$myClassInstance = MyOwnWrapperOfDIContainer::get(MyClass::class);
$myClassInstance->methodOfMyClass(); // autocompletion works here

唯一的问题是当你在 Pimple 容器中注册一些依赖时不是通过它们的类名,而是使用你想要的其他名称。例如,自动完成在以下情况下将不起作用:

$c = new Pimple\Container;
$c['my-favourite-var'] = new MyClass(1);
$c[MyClass::class] = new MyClass(2);
$c['my-favourite-var']->/*here autocompletion doesn't work*/methodOfMyClass();
$c['MyClass']->/*here autocompletion works*/methodOfMyClass();

你仍然可以像这样解决它:

class MyFavouriteVar extends MyClass;
$c[MyFavouriteVar::class] = new MyFavouriteVar(2);
// or even like this:
$c[MyFavouriteVar::class] = new MyClass(2);
$c[MyFavouriteVar::class]->/*now autocompletion works fine*/methodOfMyClass();

或者您必须找到其他解决问题的方法...

编辑1

同时考虑这篇文章: http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata

编辑2

还有这个插件 https://github.com/Sorien/silex-idea-plugin

编辑3

也可以像这样解决上面提到的问题:

class MyPimple extends Pimple\Container
{
    public function get($type, $desc = null) {
        return $this[$type . (isset($desc) ? ':' . $desc : '')];
    }
}
$c = new MyPimple;
$c[MyClass::class] = new MyClass('default');
$c[MyClass::class . ':' . 'my-special-value'] = new MyClass('special');
$c->get(MyClass::class, 'my-special-value')->/*autocompletion should work*/methodOfMyClass();

dynamicReturnTypeMeta.json 应该包含:

{
    "methodCalls": [
        {
            "class": "\\MyPimple",
            "method": "get",
            "position": 0
        }
    ]
}

关于PHPStorm 自动完成数组键(动态插入),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20912753/

相关文章:

c# - IoC 和绑定(bind)到接口(interface)

java - 使用 Guicier 注入(inject)替换 Http RestTemplate [Dropwizard]

php - 查询数据库表中整行的最佳实践? (MySQL/CodeIgniter)

javascript - jQuery 读取 JSON 数据

generics - Guice 类型 Kotlin 中的字面量

rest - 将单例作为 Tomcat servlet 注入(inject) JAX-RS (Jersey) 资源

c# - IoC - 控制 "Invert"到哪里去了? (它去哪里?)

php检查当前密码错误

php - Homebrews php56-imagick 模块由于 liblzma 无法加载

c# - 在自定义 TypeFormatter 中使用 RegisterWebApiRequest 时出现 SimpleInjector.ActivationException