插件替换和分叉
插件替换是一项功能,允许您创建一个插件来替换(或覆盖)另一个插件。当您分叉插件以添加自己的功能但希望能够从原始插件无缝迁移并作为原始插件的替代品时,这很有用(即保留原始数据,实现其他插件对原始插件的依赖性, ETC)。
注册一个插件作为替代品
要启用插件替换功能,请在replaces
内的关键pluginDetails
数组,以及定义哪些版本的插件可以被您的插件替换的版本约束。
public function pluginDetails()
{
return [
'name' => 'Acme Plugin',
'replaces' => [
'Acme.Original' => '>=5.0 <=6.0.4'
],
];
}
版本限制
版本约束允许您限制您的插件仅覆盖当前安装的特定版本的插件。上面的示例仅展示了如果原始插件是介于5.0
和6.0.4
包括的。大多数情况下,您将使用的实际版本约束会简单得多,一个简单的<2.0
指示紧接在您首次发布替换插件的版本之前的所有版本。
这意味着您不必担心原始插件的新版本的更改可能会与您对插件的更改发生冲突。
版本约束在与 Composer 使用的格式相同.一些有效的例子是:
-
1.0
-
>=1.0.3
-
<2.0
-
>=1.5.0 <2.0.0
-
self.version
通过指定一个版本,您的插件将检查原始插件安装的版本,只有当它的版本与约束匹配时,它才会禁用原始插件并启用替换。如果此匹配失败,则替换将被禁用,而原始插件将保持启用状态。
Aliasing
NOTE: 这仅供参考。通过在插件注册文件中注册一个插件作为替代,Winter 会自动为您注册这些别名。
别名是 Winter 的一项功能,它允许向后兼容并支持继承替换的插件:
- 配置选项
- 语言和翻译
- Settings
- Navigation
这将允许,例如,即使使用原始类名,使用原始插件功能的插件仍然可以工作。如果一个插件替换了一个依赖于第三个插件的原始插件,别名将解析对第三个插件的依赖,允许第三个插件继续运行。
Configuration
配置支持 2 种不同类型的别名:registerNamespaceAlias
®isterPackageFallback
.
registerNamespaceAlias
此方法允许在访问配置值时将别名重定向到命名空间。
Config::registerNamespaceAlias('winter.replacement', 'winter.original');
例如,将以下配置注册为plugins/winter/replacement/config/config.php
:
<?php
return [
'foo' => 'bar'
];
可以通过注册的别名访问配置:
config('winter.original::foo'); // returns bar
registerPackageFallback
此方法允许回退到别名的全局配置(在中指定的配置/config/acme/plugin/config.php
).
Config::registerPackageFallback('winter.replacement', 'winter.original');
其逻辑如下:
- 如果
/config/winter/replacement/config.php
存在它将被注册在winter.replacement
命名空间。 - 如果
/config/winter/replacement/config.php
不存在,它将检查/config/winter/original/config.php
如果找到, 它将被注册在winter.replacement
.
语言与翻译
允许将调用重定向到别名并从命名空间返回值。
Lang::registerNamespaceAlias('winter.replacement', 'winter.original');
例如,将以下配置注册为plugins/winter/replacement/lang/en/lang.php
:
<?php
return [
'foo' => 'bar'
];
可以通过注册的别名访问翻译:
Lang::get('winter.original::foo'); // returns bar
Settings
注册设置别名有两种方法。首先,别名可以在PluginManager
通过初始化lazyRegisterOwnerAlias
.
SettingsManager::lazyRegisterOwnerAlias('Winter.Replacement', 'Winter.Original');
如果PluginManager
已加载,则可以通过以下方式注册别名:
SettingsManager::instance()->registerOwnerAlias('Winter.Replacement', 'Winter.Original');
Navigation
注册设置别名有两种方法。首先,别名可以在PluginManager
通过初始化lazyRegisterOwnerAlias
.
NavigationManager::lazyRegisterOwnerAlias('Winter.Replacement', 'Winter.Original');
如果PluginManager
已加载,则可以通过以下方式注册别名:
NavigationManager::instance()->registerOwnerAlias('Winter.Replacement', 'Winter.Original');
处理迁移、播种机和表引用
当分叉插件并使用替换功能时,您将需要通过迁移、播种器和模型类将数据从原始插件迁移到替换插件。为此,我们建议如下:
- 创建迁移以重命名表
- 更新模型以引用您的新表
- 检查迁移以了解模型的任何使用情况
表重命名
示例迁移可能如下所示:
<?php namespace Winter\Plugin\Updates;
use Schema;
use Winter\Storm\Database\Updates\Migration;
class RenameTables extends Migration
{
const TABLES = [
'example',
'foo',
'bar'
];
public function up()
{
foreach (self::TABLES as $table) {
$from = 'acme_plugin_' . $table;
$to = 'winter_plugin_' . $table;
if (Schema::hasTable($from) && !Schema::hasTable($to)) {
Schema::rename($from, $to);
}
}
}
public function down()
{
foreach (self::TABLES as $table) {
$from = 'winter_plugin_' . $table;
$to = 'acme_plugin_' . $table;
if (Schema::hasTable($from) && !Schema::hasTable($to)) {
Schema::rename($from, $to);
}
}
}
}
使用模型迁移
如果旧迁移(即在重命名表的迁移之前运行的任何迁移)正在使用模型来填充数据,它将引用新表,这将在更新时导致问题。解决方案是在插入/修改数据之前动态重命名表:
ExampleModel::extend(function ($model) {
$model->setTable('acme_plugin_example');
});
// execute seeding code
ExampleModel::extend(function ($model) {
$model->setTable('winter_plugin_example');
});
如果模型使用unique
验证规则,您应该确保规则的实施没有任何修饰符(即只是'slug' => 'unique'
, 不是'slug' => 'unique:winter_plugin_table'
这样调用$model->setTable()
也将在该验证逻辑中生效。