如何将方法注入与接口一起使用


interface UserRepositoryInterface {
public function getUser($userType, $login): Builder;
}
class UserRepository implements UserRepositoryInterface {
public function getUser('clientA', 'user-login', EmailValidatorInterface $emailValidator, PhoneValidatorInterface $phoneValidator): Builder {} 
}

方法UserRepository@getUser由于不遵守契约UserRepositoryInterface@getUser而引发错误。在使用方法注入时,如何删除错误?

有几种方法可以解决这种错误。我不太喜欢重写接口提供的方法的签名。比起类的构造函数,我更喜欢DI。

使用构造函数的依赖项注入

这个在我眼里更有感觉,因为它更干净。在重写接口方法签名之前,您必须始终检查附加参数是否在多个方法中使用。如果是这种情况,只需在构造函数上注入依赖项即可。

<?php
declare(strict_types=1);
namespace Marcel;
class UserRepository implements UserRepositoryInterface
{
protected EmailValidatorInterface $emailValidator;
protected PhoneValidatorInterface $phoneValidator;

public function __construct(
EmailValidatorInterface $emailValidator,
PhoneValidatorInterface $phoneValidator
) {
$this->emailValidator = $emailValidator;
$this->phoneValidator = $phoneValidator;
}
public function getUser(string $userType, string $login): Builder
{
// $this->emailValidator and $this->phoneValidator are available
}
}

正如您所看到的,这正是接口所实现的。没有其他参数。只是干净简单的依赖项注入。这种类型的注入需要一个简单的工厂或其他东西来初始化依赖关系。

扩展接口实现的方法

如果由于任何原因不能使用依赖项注入,则可以通过为每个附加参数提供默认值来从接口扩展方法签名。

<?php
declare(strict_types=1);
namespace Marcel;
class UserRepository implements UserRepositoryInterface
{
public function getUser(
string $userType, 
string $login,
?EmailValidatorInterface $emailValidator = null,
?PhoneValidatorInterface $phoneValidator = null
): Builder
{
// $emailValidator and $phoneValidator are available
// just validate them against null
}
}

这是丑陋的af,但它会起作用。当您检查一个类是否实现了UserRepositoryInterface接口时,会发生什么?它只是确保有一个方法getUser,它接受两个参数。该接口对任何其他参数一无所知。这是最纯粹的不一致

在大多数DI系统中,您会在构造函数中解决此问题。

interface UserRepositoryInterface {
public function getUser($userType, $login): Builder;
}
class UserRepository implements UserRepositoryInterface {
public function __construct(
public readonly EmailValidatorInterface $emailValidator,
public readonly PhoneValidatorInterface $phoneValidator
){}
public function getUser('clientA', 'user-login'): Builder {} 
}

最新更新