我有一个PHP命令行实用程序,执行方式如下:
tool plugin command [options]...
这个想法是可以使用第三方插件,因此主要工具不知道它们是什么。它可以通过环境变量找到它们,就像PATH
。
主工具应用程序的组合根目录包含所有插件(共享)使用的依赖项。但是,每个插件都有自己的依赖项,因此,插件的构造函数是我有第二个组合根的地方。
这听起来像多个组合根的合法案例吗?
$c = new DIContainer();
$c->bind(...); // whatever is needed
$loader = new PluginLoader($c);
// argv[1] is the plugin name. the loader will inject the Container
// into the plugin's constructor. This is the 2nd composition root
$plugin = $loader->get($argv[1]);// locates and constructs
// the plugin populates its commands as plugin.command
$cmd = $c[ $argv[1] . '.' . $argv[2] ];
$cmd->execute(array_splice($argv, 3));
第二个问题
每个命令都有一个Option对象数组,我不确定Command是否应该预先组合和注入此数组,或者是否应将OptionFactory注入命令的构造函数中。后者很好,因为它保留了封装在命令中的选项,而插件的构造函数必须为它支持的每个命令构建一个选项列表。请注意,这些不是命令行选项($argv
),它只是命令支持的选项列表,并包含验证程序。
// Plugin class, 2nd composition root, called by PluginLoader
class MyPlugin{
public function __construct(Container $c){
$c->bind('myplugin.command', function(Container $c){
return new Command([ ... create option objects here ...]);
// or
return new Command($c['option-factory']); // let cmd build option[]
});
}
}