2015-01-11 6 views
0

У меня есть код на основе пространства имен с папкой «Модель». Я называю свои модели статический везде в моем коде:Как я могу специализировать класс пространства имен и использовать его без изменения слишком большого кода?

\Myapp\Model\PersonModel::doSomething() 

Теперь я хотел бы распространить свое применение в ряде стран, и иметь возможность переопределить некоторые особенности PersonModel для некоторых стран (и добавить модели для некоторых стран, и так далее).

у меня будет:

\MyApp\Model\France\PersonModel::doSomething() 

Я хотел бы иметь возможность использовать специализированную версию, имея это в виде:

  • Не модифицирующий слишком много кода
  • Поддерживаю мой IDE код завершение

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

Другим решением было бы переопределить каждую модель и добавить функцию где-нибудь, которая даст мне имя полностью квалифицированного класса (для текущей страны), но код станет уродливым, и я потеряю завершение кода.

Третьим решением будет иметь репозиторий для каждой страны и попытаться изменить все, чтобы основной код находился в подмодуле Git, а все остальное - специализированные классы ... Кажется, это лучшее решение для меня но это похоже на работу Titan, и я предпочел бы, чтобы все страны внутри одного хранилища держали вещи под контролем.

У меня нет другой идеи. Я уверен, что я не единственный с этой проблемой, но я искал и ничего не нашел. Пожалуйста, скажите, есть ли волшебная функция для пространств имен, о которых я не знал или что-то еще? :)


Edit: это частично решается

Я теперь с помощью пользовательского автозагрузчика, который будет загружать собственный класс для конкретной страны. Но все классы, относящиеся к конкретной стране, будут разделять то же самое пространство имен (что будет работать, потому что мы используем только одну страну в данный момент времени). Тем не менее, я теряю завершение кода, но это компромисс, с которым я в порядке. Если у кого-то есть решение, которое должно было бы также, позвольте сохранить код завершения, пожалуйста, не стесняйтесь отвечать!

+0

Я пытаюсь привязать это к конкретному вопросу. Вопрос о том, как лучше всего сделать вызов '\ MyApp \ Model \ France \ PersonModel'? Если это так, вы можете использовать 'call_user_func', но это удаляет ваше автозаполнение. Однако было бы лучше, если бы во всех случаях «PersonModel» вызывать вещи в контексте экземпляра, а затем переменная '$ personModel' может поступать с фабрики, помеченной (с блоками док-станции), как возвращающая« PersonModelInterface ». Здесь статические вызовы - сложнее обобщить. – halfer

+0

Контроллер на страну или репо на страну обычно являются (действительно) неправильными решениями. Обобщите как можно больше. – halfer

+0

На самом деле я нашел решение самостоятельно: используя пользовательский автозагрузчик, который будет искать пользовательский класс в текущей папке страны, но пространство имен для всех стран будет таким же, что позволит мне использовать полностью квалифицированные классы. Хотя, я теряю завершение кода ... Но это компромисс, с которым я в порядке, по сравнению со стоимостью создания репо для каждой страны! –

ответ

0

Другая идея, вытекающая из моих мыслей в комментариях. Переместить это:

\Myapp\Model\PersonModel 

сюда (случайное место, так как я не знаю вашу территорию по умолчанию):

\Myapp\Model\Germany\PersonModel 

Вы в настоящее время есть два класса, со страной, в пространстве имен, и Конечно, вы можете добавить больше. Теперь Вы можете добавить новый обобщенный класс, таким образом:

namespace \Myapp\Model; 

/* 
* Document your methods here using @method, so you get autocompletion 
*/ 
class PersonModel 
{ 
    public function __callStatic($name, $args) 
    { 
     // Convert the call to an appropriate static call on the correct class. 
     // The first parameter is always the country name, which you can examine 
     // and then remove from the list. Throw an exception if $args[0] is 
     // empty. 
    } 
} 

Вы можете сделать это:

\MyApp\Model\PersonModel::doSomething('France', $args); 

Использование @method (see here) обеспечит вам сохранить автозаполнение, и вы можете узнать подробнее о call magic methods here.

Конечно, убедитесь, что ваши языковые классы относятся к родительскому классу, поэтому вы не дублируете большие капли кода. Некоторые методы также могут не заботиться о языке, и в этом случае они могут пойти в \Myapp\Model\PersonModel, при этом им не нужны ручные записи phpdoc.

+0

Привет Halfer. Это может работать действительно, однако, хотя я мог бы использовать сразу несколько стран с вашим решением, я не чувствую себя комфортно, потому что я все равно потеряю завершение, пока у меня нет страны в пространстве имен (или мне нужно будет используйте метод @ для каждого конкретного метода в каждой стране, и, кроме того, он будет «слишком разрешительным» и, возможно, сделает меня неправильным). Ваше решение хорошо, поэтому я согласен с этим, но у меня нет моих личных предпочтений, так как мне более удобно с тем, что было выше. Спасибо, Халфер! –

+0

@Lideln: Я подозреваю, что если вы можете использовать объекты уровня экземпляра, а не статические ссылки, с ними было бы легче работать. Думаю, это было главным образом моим первым комментарием. Тем не менее, если вы довольны своим решением, это хорошо! – halfer

1

Ok я нашел во всем мире, удовлетворяющую решение:

Все классы конкретных стран будут делиться же пространство имен (например, «Myapp \ Model \ Custom *»), который не вызовет конфликтов, потому что есть только 1 страна за раз.

Пользовательский автозагрузчик загрузит соответствующий класс/файл на основе текущей страны.

Inconvenients этого решения являются:

  • Не можно «использовать» несколько стран одновременно (что не является целью, так что это нормально)
  • Потеря автозавершения кода :(

Преимуществами являются:

  • Гораздо меньше времени и таскание за волосы, чем создание репо для каждого со untry
  • Глобально чистый код и код структуры

Пожалуйста, не стесняйтесь отправлять более элегантное решение, я буду рад прочитать его (и принять его)!