Вам придется немного поработать, пока этот код не станет лучше. Я постараюсь предложить как можно меньше изменений, чтобы сделать «миграцию» максимально безболезненной, хотя вы на несколько шагов удалены от чистого дизайна.
Для начала вы можете создать AuthStrategyInterface
для ваших новых классов аутентификации.
interface AuthStrategyInterface
{
public function supports(string $channel): bool;
public function auth($user, $data);
}
Каждый из ваших новых классов аутентификации должен реализовывать этот интерфейс. Метод supports($channel)
достаточно прост для понимания: если класс аутентификации может работать с определенным каналом, он должен возвращать true.
Вашему классу Auth
потребуется способ внедрения этих стратегий. Обычно вы делаете это в конструкторе ... но чтобы оставить ваш API неизменным, мы просто создадим для этого метод установки.
При выполнении authChannel()
сначала проверяются введенные стратегии, чтобы увидеть если кто-либо поддерживает используемый $channel
, и используйте его, если это возможно. Если нет, вернитесь, чтобы проверить свои старые реализации.
Таким образом, вам не нужно прикасаться к старому коду при добавлении новых стратегий аутентификации. По мере добавления новых реализаций вы постепенно душите унаследованную систему. В какой-то момент ни одна из старых реализаций не используется, и вы можете перейти к новой фазе рефакторинга кода.
class Auth {
private iterable $strategies = [];
public function __construct($user, $data)
{
$this->user = $user;
$this->data = $data;
}
public function setAuthStrategies(iterable $strategies)
{
$this->strategies = $strategies;
}
public function authChannel($channel)
{
$this->setUserData();
// check if any of the new strategies supports
foreach ($this->strategies as $strategy) {
if ($strategy->supports($channel) {
return $strategy->auth($this->user, $this->data);
}
}
// check "legacy" authentication methods.
if (isset(self::CHANNEL_AUTH_FUNCTIONS[$channel])) {
$authFunction = self::CHANNEL_AUTH_FUNCTIONS[$channel];
return $this->$authFunction($this->user, $this->data);
}
// no valid authentication method
return false;
}
}
Чтобы использовать его, вы должны сделать что-то вроде этого:
$fooAuthStrategy = new FooAuthStrategy();
$barAuthStrategy = new BarAuthStrategy();
$bazAuthStrategy = new BazAuthStrategy();
$auth = new Auth($user, $data);
$auth->setAuthStrategies(
[
$fooAuthStrategy,
$barAuthStrategy,
bazAuthStrategy
]
);
$auth->authChannel($channel);
Специфика будет меняться в зависимости от того, как именно настроено ваше приложение, но что-то подобное приведет вас в правильном направлении, чем ваш текущий подход.