1

我已经创建 WordPress 插件几个月了,我开发了一组“基类”(大多数是抽象类,但不是全部)我与插件一起使用(有些与所有插件一起使用) -ins,当插件需要类提供的特定东西时使用其他插件 - 可能是管理屏幕或可视化编辑器上的按钮或其他)。

当然,这很有效,但是如果我更新一个或多个基类以添加一些新功能,那么如果有人安装了多个我的插件,那么这些插件中的一个或多个很可能崩溃。

这是因为如果使用较早版本的更新类的插件加载较早,那么它会“保留”该名称,而其他需要更新类的插件没有功能/修复/等。

我已经尝试过“不错”的解决方案,但我唯一能可靠工作的就是更改每个插件的实际基类名称,这远非理想。

命名空间显然有效但不能使用,因为许多流行的托管公司都在使用 5.2x 版本的 PHP(可能是 WordPress 也不需要 5.3 的原因)

我尝试动态创建类名并使用类工厂,但它们不起作用或没有克服重命名所有基类的需要。我什至尝试过(虽然我没想到它会起作用,但你永远不会知道 PHP):

类 childClassName 扩展 $parentClassName

这种情况不会那么不寻常(人们真的每次都从头开始重写所有内容和/或使用不同的类名),但我找不到解决方案,也想不出一个优雅的解决方案。这甚至不是 WordPress 的问题,一个公司内使用公共基类的多个应用程序会遇到同样的问题。

我也不能强迫每个人每次都升级他们所有的插件,因为它可能会在他们之前崩溃,我不确定我要求他们是否合理,甚至我可以亲自更新和重新测试,每一次,每一个现在都有近 10 个插件,未来还会有更多。

我当前最好的解决方案是使用工厂来创建所有基类,并将标记放在我可以进行全局搜索和替换的基类中,以便每个插件的类名都是唯一的;请注意,仅可替换的令牌就可以了。

是否有一些 PHP 代码可以让我为这个常见的类名冲突问题实现简单、轻松的解决方案?

=========================================

貌似没有人知道用 PHP 怎么做,也许做不到,所以我就按照我上面说的方法去了。

我想我会把它放在这里,因为这是我最终得到的效果很好,如果不是我所希望的,也许它可以帮助其他人:

  1. 我在基类名称中添加了标记,例如:

类 someBaseClass[ TokenNameGoesHere ](我用 [ ReplaceWithVersionNumber ])

类 someChildClass 扩展 someBaseClass[ TokenNameGoesHere ]

  1. 我创建了一个名为 createNewClass 的方法,并将类名(作为字符串)和任何要传递给新类的参数(在数组中)。

我还传递了诸如应用程序中使用的令牌值(在我的情况下为版本号)和命名空间(如果我可以使用 PHP 5.3 及更高版本,则用于代替令牌值)等信息。

然后我使用反射来创建类。虽然反射明显变慢了,但我发现我不需要使用 createNewClass 的次数并不多,因此在易于记忆和提高清晰度之间取得了平衡。

$reflectionOfClass = 新 \ReflectionClass($desiredClassName); $newObject = $reflectionOfClass->newInstanceArgs($ParametersToPass);

其中 $desiredClassName 是由类名和其他参数构建的:在我的例子中是版本和命名空间。

然后,在任何我想创建一个我会使用的基类对象的地方:

$myNewObject = $this->createNewObject("someBaseClass", 其他参数);

  1. 当我为一个新应用程序复制类库时,我只是进行了大量搜索,并用我想要在所有文件中替换它的内容替换了令牌。如果我不必像使用 WordPress 插件那样担心与我的类库的其他版本发生冲突,它可能是版本号甚至是空字符串。

尽管返回并插入令牌很乏味,但这很容易做到并且效果很好。

当然,这一切都可以只用令牌来完成,但我不想记住在名称上加上后缀以及我使用的是哪个令牌名称等等。

我希望对某人有所帮助,如果有人有更好的方法(对我来说这意味着更少的代码修改和更多的代码清晰度),我很想听听。

4

2 回答 2

0

不确定您是否找到了问题的正确解决方案。我正在处理同样的问题,我的方法(不完美,但可以满足我的需要)将是这个:

从变量创建可重用类的类别名,如下所示:

$aliasclass = $really_unique_prefix."_Prefix_MyPlugin_Class";
class_alias("Prefix_MyPlugin_Class", $aliasclass);
new $aliasclass();

希望能帮助到你!

于 2013-11-25T10:39:48.783 回答
0

是的,命名空间是完美的解决方案。

如果 php 可以提供卸载/加载类的方法,问题就可以轻松解决。但是您再次需要重新链接/实例化其他依赖的活动插件,以便使用新类的对象,这涉及停用和激活现有插件。

同样的想法,我可以想到这个解决方案,你很清楚你有 1,2,3 .. n 个使用 X 类的插件。1 和 2 插件正在使用版本的 X,您将要使用较新版本的 X 安装/更新插件 3。停用所有插件并首先激活具有 X 类最新功能/版本的插件 (3),稍后再激活所有其他人。

$all_plugins = array(
    ABSPATH.'wp-content/plugins/plugin_1/index.php',
    ABSPATH.'wp-content/plugins/plugin_2/index.php'
    ......
    ABSPATH.'wp-content/plugins/plugin_n/index.php'
);
if (class_exists('X') && X::version < currentXVersion) {
    deactivate_plugins($all_plugins);
    $plugin_3_lastest_class_X = ABSPATH.'wp-content/plugins/plugin_3/index.php';
    array_unshift($all_plugins, $plugin_3_lastest_class_X);
    activate_plugins($all_plugins);
}

*如果可以停用/激活您的插件并且您不修改 X 类现有功能的签名,您可以添加新功能。

于 2013-12-13T06:31:23.103 回答