如何在不修改太多代码的情况下专门化命名空间的 class 并使用它?

How can I specialize a class of a namespace and use it without modifying too much code?

我有一个基于名称空间的代码,有一个 "Model" 文件夹。我在我的代码中到处静态地调用我的模型:

\Myapp\Model\PersonModel::doSomething()

现在,我想在几个国家分发我的应用程序,并能够为某些国家覆盖 PersonModel 的某些功能(并为某些国家添加模型,等等)。

我会有:

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

考虑到这一点,我希望能够使用专用版本:

一个解决方案是为每个国家专门化每个控制器,并在所有地方使用完全限定的名称,但我不确定它是否现实(耗时,甚至可能无法正常工作)。

另一种解决方案是覆盖每个模型,并在某个地方添加一个函数,该函数会给我完全限定的名称 class(对于当前国家/地区),但代码会变得丑陋,我会丢失代码补全。

第三种解决方案是为每个国家建立一个存储库,并尝试修改所有内容,以便核心代码位于 Git 子模块中,其他所有内容都是专门的 classes.. . 这对我来说似乎是最好的解决方案,但它似乎是 Titan 的作品,我更希望所有国家都在同一个存储库中以控制事情。

我真的没有别的想法。我敢肯定我不是唯一遇到该问题的人,但我进行了搜索但一无所获。请告诉我命名空间有一个我不知道的神奇功能,或者什么? :)


编辑:部分解决

我现在使用的是自定义自动加载器,它将加载特定国家/地区的正确内容class。但是所有国家/地区特定的 classes 将共享 same 名称空间(这将起作用,因为我们在给定时间仅使用 1 个国家/地区)。然而,我失去了代码完成,但这是一个我可以接受的权衡。如果有人有允许保持代码完成的解决方案,请随时回答!

好的,我找到了一个全球满意的解决方案:

所有特定国家的 类 将共享 相同的 名称空间(例如 "Myapp\Model\Custom*"),这不会导致冲突,因为只有 1 个国家/地区一次。

自定义自动加载器将根据当前国家/地区加载正确的 class/file。

此解决方案的不便之处在于:

  • 不可能同时"use"多个国家(这不是目标,所以没关系)
  • 丢失代码补全:(

优点是:

  • 比为每个国家/地区创建存储库更省时更费力
  • 全局清理代码和代码结构

请随时post更优雅的解决方案,我将很高兴阅读(并接受)!

另一个想法,来自我在评论中的想法。移动这个:

\Myapp\Model\PersonModel

到这里(随机位置,因为我不知道你的默认区域):

\Myapp\Model\Germany\PersonModel

您现在将有两个 class 名称空间中有一个国家/地区,当然您可以添加更多。您现在可以添加一个新的广义 class,因此:

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) will ensure you retain auto-completion, and you can learn more about the call magic methods here.

当然,请确保您的特定语言 classes 引用父 class,这样您就不会复制大块代码。有些方法也可能不关心语言,在这种情况下,它们可以进入 \Myapp\Model\PersonModel,好处是它们不需要手动 phpdoc 条目。