box-project / console
通过依赖注入构建的命令行应用程序。
Requires
- php: >=5.4
- herrera-io/object-storage: ~1.0
- kherge/file: ~1.3
- symfony/config: ~2.5
- symfony/console: ~2.5
- symfony/dependency-injection: ~2.5
- symfony/yaml: ~2.5
Requires (Dev)
- herrera-io/object-storage: 1.*
- phpunit/phpunit: ~4.6
- symfony/config: 2.5.*
- symfony/console: 2.5.*
- symfony/dependency-injection: 2.5.*
- symfony/event-dispatcher: 2.5.*
- symfony/expression-language: 2.5.*
- symfony/framework-bundle: 2.5.*
- symfony/yaml: 2.5.*
Suggests
- symfony/event-dispatcher: Enables support for observing console events.
- symfony/expression-language: Allows expressions to be used in service registrations.
- symfony/framework-bundle: Enables commands for debugging service registration.
README
控制台
composer require box-project/console
控制台简化了使用依赖注入设计模式构建命令行应用程序的过程。输入和输出管理已经为您处理。您只需创建您的命令并将每个命令注册为服务即可。
use Box\Component\Console\Application; use Symfony\Component\DependencyInjection\ContainerBuilder; $container = new ContainerBuilder(); $application = new Application($container); $container->compile() $application->run();
要求
kherge/file
~1.3herrera-io/object-storage
~1.0symfony/config
~2.5symfony/console
~2.5symfony/dependency-injection
~2.5symfony/yaml
~2.5
建议
symfony/event-dispatcher
~2.5symfony/expression-language
~2.5symfony/framework-bundle
~2.5
入门指南
为了理解任何内容,您需要熟悉Console使用的某些第三方库。这些库来自开源Web应用程序框架Symfony。为了您的方便,以下链接包含了最相关的库的文档。
- 控制台 - 管理控制台的各个方面(输入和输出)。当您编写命令时,您将针对这个库。
- 依赖注入 - 负责将所有依赖项连接在一起。同时也使得更改库提供的默认值以更好地满足您的需求成为可能。
- 事件调度器 - 简单实现的中介模式。启用控制台库中的事件,并使向您的控制台应用程序添加插件系统成为可能。
创建应用程序
use Box\Component\Console\Application; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface;
在创建新应用程序之前,需要一个依赖注入容器。虽然可以使用任何ContainerInterface
的实例,但我们将使用ContainerBuilder
的实例(稍后会详细介绍原因)。
$container = new ContainerBuilder();
有了容器,现在可以创建一个新的Application
实例。
$app = new Application($container);
当将ContainerBuilder
的实例提供给Application
时,它将自动设置参数并注册运行控制台应用程序所需的所需服务。Application
不会设置参数或注册已存在的服务。需要注意的是,只有ContainerBuilder
的实例会导致Application
设置默认参数并注册默认服务。
运行应用程序
在开始运行控制台之前,必须首先编译容器。编译容器可以让一些最后时刻的过程发生。编译 容器。
$container->compile();
编译后的容器使得应用程序准备就绪,可以运行。
$app->run();
当从命令行脚本的代码运行上述示例时,将显示以下输出。需要注意的是,输出可能会因文档的年龄和除了 控制台 之外安装的库而略有不同。
Console Tool
Usage:
[options] command [arguments]
Options:
--help -h Display this help message
--quiet -q Do not output any message
--verbose -v|vv|vvv Increase the verbosity of messages: [...snip...]
--version -V Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
--no-interaction -n Do not ask any interactive question
Available commands:
help Displays help for a command
list Lists commands
config
config:current Displays the current configuration
config:list Lists the registered extensions
config:reference Displays a configuration reference
container
container:debug Displays current services for an application
debug
debug:container Displays current services for an application
使用容器
Application
是围绕容器使用的。所有由 控制台 提供的功能都可以在容器中找到,作为一个参数或服务。因此,对控制台的所有更改(添加命令、添加助手、更改默认值等)也必须通过容器进行。
加载资源
为了更改容器,必须使用 DependencyInjection 库提供的加载器。有关如何使用 DI 加载器 的更多信息,可以在 Symfony 网站上找到。虽然可以使用任何兼容的加载器,但 控制台 仅官方支持基于文件的加载的 XML 和 YAML。PHP 也得到支持,但不能与捆绑的命令或加载器一起使用。
加载 .dist
文件
除了标准加载器之外,控制台 还为特殊情况提供了自己的加载器。许多应用程序都使用以 .dist
结尾的文件。这种文件扩展名用于表示文件是分发的一部分。用户可以复制该文件,删除 .dist
扩展名,并使用自己的软件版本使用该文件。
以下示例将支持加载带有或没有 .dist
文件扩展名的 XML 和 YAML 文件。
use Box\Component\Console\Loader\Resource; use Box\Component\Console\Loader\ResourceCollection; use Box\Component\Console\Loader\ResourceCollectionLoader; use Box\Component\Console\Loader\ResourceSupport; use Symfony\Component\Config\Exception\FileLoaderLoadException; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; // load files from the current directory $locator = new FileLocator('.'); // create a loader for xml and yaml files $loader = new ResourceCollectionLoader( new LoaderResolver( array( new XmlFileLoader($container, $locator), new YamlFileLoader($container, $locator) ) ) ); // load the first available file from a collection of possible resources $loader->load( new ResourceCollection( array( new Resource('example.xml'), new ResourceSupport('example.xml.dist', 'example.xml'), new Resource('example.yml'), new ResourceSupport('example.yml.dist', 'example.yml') ) ) );
正如其名所示,ResourceCollection
类管理一组 Resource
实例。由于标准文件加载器在确定对文件的支持时的行为,使用 ResourceSupport
将不支持文件扩展名(例如 .yml.dist
)映射到支持文件扩展名(例如 .yml
)。然后,ResourceCollectionLoader
加载器将遍历集合,尝试加载每个资源,直到成功加载。如果集合中的第一个资源由于不存在而无法加载,将尝试下一个资源。此迭代将继续,直到列表耗尽,或者在处理可用资源时出现错误。
在上面的示例中,如果集合中的任何资源都不存在,则抛出异常。要可选地加载资源而不抛出异常,应使用 loadOptional()
方法。
$loader->loadOptional( new ResourceCollection( array( new Resource('example.xml'), new ResourceSupport('example.xml.dist', 'example.xml'), new Resource('example.yml'), new ResourceSupport('example.yml.dist', 'example.yml') ) ) );
注册命令
要注册命令,必须使用 "box.console.command" 标签标记其服务。
在 PHP 中
$definition = new Definition('My\Command'); $definition->addTag('box.console.command'); $container->setDefinition('my_command', $definition);
在 XML 中
<container> <services> <service class="My\Command" id="my_command"> <tag name="box.console.command"/> </service> </services> </container>
在 YAML 中
services: my_command: class: My\Command tags: - { name: box.console.command }
注册助手
要注册一个命令,您必须使用“box.console.helper”标签其服务。
在PHP中
$definition = new Definition('My\Helper'); $definition->addTag('box.console.helper'); $container->setDefinition('my_helper', $definition);
在XML中
<container> <services> <service class="My\Helper" id="my_helper"> <tag name="box.console.helper"/> </service> </services> </container>
在YAML中
services: my_helper: class: My\Helper tags: - { name: box.console.helper }
注册事件监听器和订阅者
EventDispatcher库支持监听器的注册,或通过所谓的“订阅者”注册一组监听器。监听器是一个单一的调用者,而订阅者是一个在特定事件分发时必须调用哪些方法的类。
监听器
在PHP中
$definition = new Definition('My\Listener'); $definition->addTag( 'box.console.event.listener', array( 'event' => 'the.event', 'method' => 'onEvent' ) ); $container->setDefinition('my_listener', $definition);
在XML中
<container> <services> <service class="My\Listener" id="my_listener"> <tag name="box.console.event.listener" event="the.event" method="onEvent"/> </service> </services> </container>
在YAML中
services: my_listener: class: My\Listener tags: - name: box.console.event.listener event: the.event method: onEvent
订阅者
在PHP中
$definition = new Definition('My\Subscriber'); $definition->addTag('box.console.event.subscriber'); $container->setDefinition('my_subscriber', $definition);
在XML中
<container> <services> <service class="My\Subscriber" id="my_subscriber"> <tag name="box.console.event.subscriber"/> </service> </services> </container>
在YAML中
services: my_subscriber: class: My\Subscriber tags: - { name: box.console.event.subscriber }
注册扩展
扩展提供了一种设置参数和为容器设置服务定义的另一种方式。但是,为了使这些扩展可用于container
助手,以便捆绑的命令仍然正常工作,必须通过registerExtension()
方法进行注册。
$app->registerExtension(new MyExtension());
这将在容器构建器中创建一个标记的服务定义,同时在容器中注册扩展。这将允许助手在为捆绑的命令创建新的容器构建器时重新注册相同的扩展。
默认设置
如“入门”部分中提到的,当将ContainerBuilder
实例传递给Application
时,容器中会设置一组默认参数和服务。以下是这些参数和服务的列表。
参数
名称(默认值) | 描述 |
---|---|
box.console.auto_exit
( true ) |
如果为true ,则在命令完成后调用exit() 。 |
box.console.class
( Symfony\Component\Console\Application ) |
控制台应用程序的类。 |
box.console.command.*.class
( Symfony\Component\Console\Command\Command 的实例) |
每个默认命令的类。 |
box.console.event_dispatcher.class
( Symfony\Component\EventDispatcher\ContainerAwareDispatcher ) |
事件分发器的类。 |
box.console.helper.*.class
( Symfony\Component\Console\Helper\Helper 的实例) |
每个默认助手的类。 |
box.console.helper.container.class
( Box\Component\Console\Helper\ContainerHelper ) |
提供对容器访问的助手类。 |
box.console.helper_set.class
( Symfony\Component\Console\Helper\HelperSet ) |
助手集的类。 |
box.console.input.class
( Symfony\Component\Console\Input\ArgvInput ) |
默认输入管理器的类。 |
box.console.name
( UNKNOWN ) |
控制台应用程序的名称。 |
box.console.output.class
( Symfony\Component\Console\Output\ConsoleOutput ) |
默认输出管理器的类。 |
box.console.version
( UNKNOWN ) |
控制台应用程序的版本。 |
服务
标识符(类) | 描述 |
---|---|
box.console
( %box.console.class% ) |
包含所有命令的控制台应用程序。 |
box.console.helper.container
( %box.console.helper.container.class% ) |
提供容器访问的辅助工具。 |
box.console.command.*
( %box.console.command.*.class% ) |
一个命令。 |
box.console.helper.*
( %box.console.helper.*.class% ) |
一个辅助工具。 |
box.console.event_dispatcher
( %box.console.event_dispatcher.class% ) |
事件调度器。 |
box.console.helper_set
( %box.console.helper_set.class% ) |
包含所有辅助工具的辅助工具集。 |
box.console.input
( %box.console.input.class% ) |
输入管理器。 |
box.console.output
( %box.console.output.class% ) |
输出管理器。 |
命令
命令 | 描述 |
---|---|
config:current |
显示与容器注册的扩展的当前配置。 |
config:list |
显示与容器注册的扩展列表。 |
config:reference |
显示与容器注册的扩展的参考配置。 |
debug:container |
显示容器中的参数和服务。此命令仅在安装了 symfony/framework-bundle 时可用。 |
辅助工具
辅助工具 | 描述 |
---|---|
container |
提供对容器的访问。 |
性能
构建容器的处理可能非常耗时且成本高昂。 控制台 提供了一种缓存构建容器结果的方法,以便后续应用程序的使用可以更快。
use Box\Component\Console\ApplicationCache; use Symfony\Component\DependencyInjection\ContainerBuilder; ApplicationCache::bootstrap( '/path/to/cache/example.php', function (ContainerBuilder $container, ApplicationCache $app) { // first-run container building // register extensions using $app }, 'MyCachedContainer', // name of cached container class true // toggle debugging );
ApplicationCache::bootstrap()
方法管理创建、加载和保存容器的过程。当应用程序第一次使用此方法运行时,将创建以下文件。请注意,生成的文件名称将根据您提供给 bootstrap()
的第一个参数而有所不同。
文件 | 描述 |
---|---|
example.php |
缓存的容器。 |
example.php.meta |
用于确定是否需要刷新缓存的缓存元数据。 |
example.xml |
用于调试的容器配置。 |
默认情况下,缓存的容器类名为 ConsoleContainer
,位于根命名空间中。默认情况下,启用“调试”。调试选项将导致资源更新时刷新缓存。禁用调试后,必须在资源更改生效之前手动删除缓存文件。
许可
本软件根据 MIT 许可证发布。