php локатор классов или маршрутизация классов - PullRequest
0 голосов
/ 28 января 2020

Я ищу простой способ использовать локатор классов для php.

Я разработал приложение, которое работает для разных клиентов, требования клиентов очень похожи, но с некоторыми небольшими отличиями и исключениями. Таким образом, код почти одинаков для всех клиентов, но с некоторыми отличиями для реализации этих исключений для каждого клиента.

Я хочу использовать один и тот же базовый код для всех клиентов, я хочу сделать его простым, но при этом разрешить настройку для каждого клиента. Он должен быть прост в обслуживании, и я хочу уменьшить сложность цикломати c.

Пример, скажем, у меня есть класс A, подобный этому:

namespace src;

class A
{
   public function f1()
   {
       // do something  
   }

   public function f2()
   {
       // do something  
   }

   public function F()
   {
       return $this->f1() + $this->f2();
   }
}

Класс A реализует поведение по умолчанию или Наиболее распространенный используемый путь. Для некоторых клиентов это работает.

Другие клиенты нуждаются в особом поведении в одном или нескольких своих методах, поэтому мой первый подход состоял в том, чтобы использовать некоторые из них, если внутри каждого метода, как этот

class A
{
   public function f1()
   {
       if (CLIENT === 'peter') {
           // do something for client peter  
       } elseif (CLIENT === 'mary') {
           // do something for client mary  
       } else {
           // default client
       }
   }
}

Это работает , но мне это не нравится, потому что у меня много клиентов, и мне становится трудно читать, тестировать и поддерживать, и код для каждого метода становится очень длинным.

Второй подход Я пытался расширить основной класс для каждого клиента что-то вроде

namespace src\peter;

class A extends \src\A
{
    public function f1()
    {
        // do something for client peter
    }
}

и когда мне нужно его использовать:

if (CLIENT === 'peter') {
    $className = src\peter\A::class;
} elseif (CLIENT === 'mary') {
    $className = src\mary\A::class;
} else {
   $className = src\A::class;
}

$object = new $className();
$object->f();

Это работает, это лучше, потому что разделяет реализацию методов для каждого клиента на отдельный класс и выглядит чище , но у меня все еще есть две проблемы:

1 - В IDE, такой как phpstorm, я не могу перемещаться по коду, щелкая по методу или имени класса, потому что имя класса теперь является переменной.

2 - я по-прежнему есть это «если» в коде.

Я ищу более чистое решение, какой-то способ определить текущего клиента как CONST в файле конфигурации, а в коде я просто хочу написать

* 1 030 * $ a = new A ();

и A, может быть src \ peter \ A; или src \ mary \ A; в зависимости от того, как я его настроил, и если класс A не определен для настроенного клиента, тогда класс по умолчанию src \ A; следует использовать.

можно использовать какой-нибудь локатор классов, как этот?

спасибо!

1 Ответ

1 голос
/ 28 января 2020

А как насчет этого кода?

$clientClassName = 'src\\'.CLIENT.'\A';
$baseClassName = 'src\A';

if (class_exists($clientClassName) && is_subclass_of($clientClassName, $baseClassName)) {
    $className = $clientClassName;
} else {
    $className = $baseClassName;
}

$object = new $className();
$object->f();

Вы должны проверить, нет ли скрытых ошибок php / namespace / et c, но он должен работать.

...