我已经创建了一个加密服务并希望在实体内部访问它。 像这样:
public function setCompanyName(string $companyName, Encryption $encryption)
{
$this->companyName = $encryption->encrypt($companyName);
}
但是,如果不调用带有两个参数的函数setCompanyName,是否可以做到这一点?我必须在函数内注入容器并调用服务吗?
您想将加密数据存储在数据库中吗?
最好的方法是创建事件侦听器,该侦听器将在每个实体保存时启动,并在那里进行加密(您可以注入任何您想要侦听器的内容) 第二个事件侦听器在从数据库加载数据进行解密时启动
如果你这样做正确,所有加密/解密的事情都将在代码中透明(它只存在于那些侦听器中)
看这个 https://symfony.com/doc/3.4/doctrine/event_listeners_subscribers.html http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html
不可能在实体内部注入服务。 但是您可以使用实体侦听器来使用您的服务并在保留之前对公司名称进行加密。 看看 https://symfony.com/doc/current/bundles/DoctrineBundle/entity-listeners.html
您可以使用 PostLoad 实体侦听器将服务注入到您的实体中。事实上,Doctrine Lazy Collections 包含许多服务,并在水合时注入到实体中。
但是,我认为这并不是 Doctrine 和 Symfony 开发人员想象的实体的工作方式。问题是它使您的实体变得非常庞大和复杂,这使得它们难以测试。
面向对象的最初想法是将数据与转换数据的所有逻辑封装起来,以确保数据永远不会以业务逻辑代码作者不希望的方式进行转换。这使得将所有业务逻辑添加为实体上的方法变得合理。
但是,大多数 Symfony 应用程序将其业务逻辑拆分为实体类和许多无状态服务。
尽管他们对这些服务使用“类”或“构造函数”等面向对象的术语,但这更接近函数式编程的思想——您可以将无状态服务视为一个闭包,它包含注入的依赖项。这使得无状态服务更容易测试:
无状态服务的方法的结果仅取决于您在构造函数中放入的内容以及在方法的参数中放入的内容。然而,调用方法的顺序永远不会改变方法的作用。
尽管如此,实体中的封装对于确保满足某些约束非常有用。这就是为什么大多数 Symfony 应用程序将无状态服务与面向对象的实体类混合在一起。但他们试图保持实体类小、轻量级且易于测试,因此他们不鼓励依赖实体中的其他服务 - 相反,您应该以相反的方式做,让您的服务依赖于实体类(“反转”)控制”)。
如果您确实想确保数据始终加密,您有以下选择:
@psalm-internal Path\To\EncryptionService
或 @phpstan-internal Path\To\EncryptionService
注释来确保“EncryptedData”对象仅由该服务创建对于加密数据,第一个选项可能是最合理的,但我想提供其他选项,以防人们遇到类似的情况,即在持久和加载时转换数据不太合理。
也许在 Encrypt 类中创建一个静态方法,并直接在实体中调用它?
class Encryption {
public static function encrypt(string $string) {
// your code
}
}
public function setCompanyName(string $companyName) {
$this->companyName = Encryption::encrypt($companyName);
}