如何以 PhpStorm 理解的方式进行依赖注入

问题描述 投票:0回答:3

我目前正在开发一个 PHP 项目,我在我的代码中实现了依赖注入。代码运行正常,但我遇到了 PhpStorm(版本 2023.1)错误解释代码的问题,这导致类型提示中断。我正在向社区寻求帮助以解决此问题并帮助 PhpStorm 正确解释我的代码以恢复无缝类型提示功能。

为了提供一些上下文,这里有一个简化的代码示例:

class B {

    public static function SayHello(){
        echo 'Hello World';
    }

}


class A {

    /**
     * @param B::class $B
     */
    public function __construct(
        private readonly string $B
    ){}

    public function start(){
        $this->B::SayHello(); // <---- I Would like that SayHallo() was available via typehinting
    }

}

class AFactory extends A {

    public function __construct(){
        parent::__construct(B::class);
    }
}


$class = new AFactory();
$class->start();

这种行为令人费解,因为我已经在 PHPDoc 中明确指出

$B
应该是
B::class
类型,指的是类而不仅仅是一个通用字符串。

在尝试解决这个问题时,我多次尝试通知 PhpStorm

$this->B
应该被识别为
B
类的一个实例,而不仅仅是一个字符串。我尝试的一种方法是在 PHPDoc 中指定
$B
应被视为
B
类的实例。然而,这种方法引入了其他问题。

PhpStorm 将 PHPDoc 声明解释为表明

$B
已经被初始化,但事实并非如此。结果,它引入了进一步的混乱并且没有按预期解决问题。

我将非常感谢社区的任何帮助或建议,以解决此问题或找到有效实施依赖注入的替代方法。

php dependency-injection phpstorm php-8.2
3个回答
2
投票

如果你的目标是实现DI,那么你不想传递一个包含类名的字符串,你想传递一个包含类实例的对象。

这种行为令人费解,因为我已经在 PHPDoc 中明确指出 $B 应该是 B::class 类型,指的是类而不仅仅是一个通用字符串。

没有。

B::class
是一个字符串,其中包含类的名称,即
"B"
。你想要一个B
instance
,所以只需使用
B

// this means that $obj must be an instance of B
public function __construct(private readonly B $obj)
{
}

public function start()
{
    $this->obj::<start typing> // now your IDE will autocomplete B's methods
}

所以,那么你会做:

$b = new B();
$a = new A($b); // This is where the DI happens.

在您的示例中,您是说构造函数的参数只能是确切的字符串

"B"
——这没有任何意义,就好像它永远不会改变一样,您为什么还要费心将它作为参数。

另请注意,如果您是显式类型提示,那么您通常不需要文档块,因为您的 IDE 将能够仅从类型提示中推断出类型,并且同时提供这两种提示可能会使它们发生冲突。除非您要为参数添加说明,否则我会将它们排除在外。否则,确保它们匹配:

/**
 * @param B $obj An instance of B.
 */
public function __construct(private readonly B $obj)
{
}

1
投票

不幸的是,您无法在不污染代码的情况下执行此操作,因为您无法输入提示

$this->B
。解决方法是将它重新分配给另一个变量并键入提示该变量,如下所示:

    public function start(){
        /** @var B $cls */
        $cls = $this->B;
        $cls::SayHello();
    }

1
投票

感谢 Marcin Olowsky 的帖子,我找到了解决该问题的方法。正如他所建议的,我不得不稍微污染一下我的代码。通过编写

start()
方法如下:

public function start(){
    /**
     * @var class-string<B> $c
     */
    $c = $this->B;
    $c::SayHello();

}

通过这种方式,PHPStorm 知道

$c
的可能性并为我提供正确的类型提示。

© www.soinside.com 2019 - 2024. All rights reserved.