gpt4 book ai didi

php - 使用 Symfony Autowiring 扩展类的正确方法

转载 作者:行者123 更新时间:2023-12-04 00:24:00 25 4
gpt4 key购买 nike

我想知道这是否是使用 Symfonys Autowiring 扩展和使用类的正确方法。

例如,我有一个 BaseClass 实例化和自动连接实体管理器。

class BaseClass
{
protected $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

protected function someMethodIWantToUse(Entity $something)
{
// Do something there
$this->entityManager->persist($something);
$this->entityManager->flush();
}
}

然后我有一个扩展 BaseClass 并需要访问该方法的子类。所以我让它再次 Autowiring 并将其传递给父构造函数。
class SubClass extends BaseClass
{
private $handler;

public function __construct(EntityManagerInterface $em, SomeHandler $handler)
{
parent::__construct($em);
$this->handler = $handler;
}

public function SubClassMethod()
{
// Get some data or do something
$entity = SomeEntityIGot();
$this->someMethodIWantToUse($entity);
}
}

现在我想知道这是否真的是正确的方法,或者我缺少一些东西,父类应该能够自行 Autowiring 实体管理器?

最佳答案

总结评论,是的,你的方式是正确的。根据您的用例,有替代方案。

这是您可以解决的方法:

1.扩展类和使用Constructor Injection (你做了什么)

    class BaseClass {
protected $some;

public function __construct(SomeInterface $some)
{
$this->some = $some;
}
}

class SubClass extends BaseClass {
private $other;

public function __construct(SomeInterface $some, OtherInterface $other)
{
parent::__construct($some);
$this->other = $other;
}
}

2. Setter Injection
    class BaseClass {
protected $some;

public function __construct(SomeInterface $some)
{
$this->some = $some;
}
}

class SubClass extends BaseClass {
private $other;

public function setOther(OtherInterface $other)
{
$this->other = $other;
}
}

现在 setOther不会自动调用,您必须通过指定 calls 来“手动”调用它您的 services.yaml 中的属性(property)文件,如此处所述: https://symfony.com/doc/current/service_container/calls.html .然后看起来像这样:
// services.yaml
App\SubClass:
calls:
- [setOther, ['@other']]

或者
// services.yaml
app.sub_class:
class: App\SubClass
calls:
- [setOther, ['@other']]

假设, OtherInterface 的实现可用 @other在服务容器中。

如果您使用 Autowiring ,一个更优雅的解决方案,只需添加 @required此处描述的函数注释: https://symfony.com/doc/current/service_container/autowiring.html#autowiring-calls ,看起来像这样:
/**
* @required
*/
public function setOther(OtherInterface $other)
{
$this->other = $other;
}

3. Property Injection
    class BaseClass {
protected $some;

public function __construct(SomeInterface $some)
{
$this->some = $some;
}
}

class SubClass extends BaseClass {
public $other;
}

与 Setter 注入(inject)一样,您需要告诉 Symfony 填充此属性,方法是在您的 services.yaml 中指定它。像这样的文件:
// services.yaml
App\SubClass:
properties:
other: '@other'

或者
// services.yaml
app.sub_class:
class: App\SubClass
properties:
other: '@other'

假设, OtherInterface 的实现可用 @other在服务容器中。

结论:
由于有不同的方法可以解决这个问题,因此您可以为您的用例确定正确的方法。我个人使用注释选择选项 1(构造函数注入(inject))或选项 2(Setter 注入(inject))。它们都允许您使用类型提示,从而允许您的 IDE 帮助您编写干净的代码。
在 90% 的情况下,我会选择选项 1,因为这样对于每个阅读您的代码的人来说,一眼就能看出 __constructor 有哪些服务可用。功能。
Setter 注入(inject)的一个用例是提供所有 setXXX 的基类。函数,但子类不需要所有这些。您可以在每个子类中有一个构造函数,请求所需的服务,然后调用 setXXX基类的方法。
注意:这是一种边缘情况,您可能不会遇到这种情况。

您可以直接在 Symfony 文档中找到每种方法的优缺点列表 Service Container -> Types of Injection

关于php - 使用 Symfony Autowiring 扩展类的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58447365/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com