View Source

<p>This RFC is dealing with the CLI components of the Zend Framework 2 and should discuss:</p>
<ul>
<li>the need for CLI component(s)</li>
<li>various use cases</li>
<li>requirements</li>
<li>possible, but not final, implementations</li>
</ul>


<p>This RFC is planned to be discussed on the next ZF2 IRC meeting, which will be held on November 9th (1)</p>

<p>It is based on a few mailing list threads - (2), (3), (4), (5) - and 2 CLI prototypes by Matt Cockayne and Robert Basic.</p>

<p>The goal is to have two separate components, Zend\Console and Zend\Cli (naming of these components is open to discussion). In context, &ldquo;CLI components&rdquo; refers to both Zend\Console and Zend\Cli.</p>

<p><strong>Zend\Console</strong> should deal with &ldquo;low level&rdquo; problems, like, console argument parsing and outputting to STDOUT\STDERR, similar to what Zend\Console\Getopt is now. At most, it should rely only on the Zend\Stdlib component, on classes and interfaces defined in it. This would assure that this component can be used outside of Zend Framework as a standalone component for writing CLI scripts.</p>

<p><strong>Zend\Cli</strong> should deal with &ldquo;higher level&rdquo; problems, like writing complete CLI modules and applications. Zend\Cli should utilise Zend\Console and follow as close as possible and necessary the Zend\Mvc component. Basically, it would offer a command line entry point to an MVC style application.</p>

<h3>Why we need CLI components?</h3>

<p>To ease creating of CLI scripts, modules and applications, and, most likely, other ZF2 components like Zend\Tool.</p>

<h3>Use cases</h3>

<p>The biggest use case so far is the Module Installation and Distribution (6) which should be the main driving force behind these CLI components, in both the requirements and the deadline for these CLI components to provide something usable and useful.</p>

<p>Other uses cases include cron scripts, scrapers, development modules and tools, which could help with project management (for example, Zend\Tool)...</p>

<h3>Zend\Console Requirements</h3>

<p>Zend\Console <strong>must</strong> provide the functionality of parsing console arguments passed to the called script. This parser <strong>should</strong> put the parsed arguments in a container of sorts, which must implement the Zend\Stdlib\ParametersDescription interface. This would make easier to work with these parameters, as it would be, if not the same, then very similar, as how we are already used to work with $_GET, $_POST... parameters in an HTTP environment.</p>

<p>Zend\Console <strong>must</strong> provide the functionality of working with interactive input. A valid use case for this is (8). A possible implementation for this could be (9), need to ask around/investigate more on this.</p>

<p>Zend\Console <strong>must</strong> provide the functionality of outputting responses to STDOUT|STDERR. It <strong>should</strong> provide different output decorators, which, if needed, could be applied to the output. An example set of these decorators can be found in the Zend\Tool component (7).</p>

<p>Zend\Console <strong>must</strong> provide functionality for capturing and defining an environment. This would handle things such as detecting the OS environment. current working directory. Detecting the current scope. It should also allow for the specification of a custom environment.</p>

<h3>Zend\Cli Requirements</h3>

<p>Zend\Cli <strong>should</strong> provide functionality which would make it possible to write CLI based applications and/or modules, or to add CLI functionality to already written MVC modules. For these reasons, this component should follow as closely as possible the Zend\Mvc component.</p>

<p>Zend\Cli <strong>must</strong> have a bootstrap process which will, similar to the MVC bootstrap, initialize the application.</p>

<p>Zend\Cli <strong>must</strong> have an application object, which will handle the incoming CLI request, by using the Zend\Console components. Also, any output which needs to be sent to the terminal, should be done by the application, again, by using the Zend\Console components.</p>


<p>Zend Cli <strong>should</strong> be able to utilise the consoles environment object to load modules that are defined in the for use globally (such as modules that would comprise a &ldquo;Tool&rdquo;). The environment would provide a configuration that could be passed into the &ldquo;ModuleLoader&rdquo;. The current tool already allows for this in the form of $HOME/.zf/zf.ini. This will allow easy development of modules that can provide tooling or service functionality that is common across modules.</p>

<p>Zend\Cli <strong>should</strong> have a request and a response object.</p>

<p>Zend\Cli <strong>should</strong> have a router and the possibility to define routes. This would allow us to, for example, call module Foo, controller Bar, action Baz, by simply invoking:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
prompt> zf2.php spam
]]></ac:plain-text-body></ac:macro>

<p>The possible routes <strong>should</strong> be kept simple, in the ranks of the following example:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
array(
‘spam’ => array(
‘module’ => ‘foo’,
‘controller’ => ‘bar’,
‘action’ => ‘baz’
)
)
]]></ac:plain-text-body></ac:macro>

<p>If possible to make it similar to one of the HTTP routers, need to ask DASPRiD about this.</p>

<p>It <strong>should</strong> be possible to define a help message on any &ldquo;level&rdquo; of commands. For example, if we have the following commands:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
prompt> zf2.php module fetch http://some-module-uri/
prompt> zf2.php module update http://some-module-uri/
]]></ac:plain-text-body></ac:macro>

<p>we should be able to call help on both <em>fetch</em> and <em>update</em>, <strong>and</strong> on <em>module</em> too:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
prompt> zf2.php module fetch --help
prompt> zf2.php module update --help
prompt> zf2.php module --help
]]></ac:plain-text-body></ac:macro>

<p>If the help message is not defined in any of these cases from the above example, it would either print out a usage message, similar to the <em>getUsageMessage</em> in Zend\Console\Getopt, or just simply a &ldquo;No help found for %s&rdquo; message. A possible way to define help messages is to output the docblock of the controller/action.</p>

<p>The matched route <strong>must</strong> call a module/controller/action combination, defined with the route. The controller <strong>must</strong> be dispatchable and locator aware.</p>

<p>We <strong>should</strong> consider and discuss the possibility of making it possible to access a controller both from an HTTP request and from an CLI request. The pro of this is reusability. The con is possible reduced security. Take just for an example an action which is run by cron to do some maintanance on the database/filesystem; making this accessible via HTTP can impose a security issue. There is also an option of adding a flag of some sort to the controller, which would be <strong>off</strong> by default and would mark the controller accessible only from HTTP or CLI. Setting the flag to <strong>on</strong> would make the controller accessible from both environments.</p>

<h5>Various links</h5>

<p>(1) <ac:link><ri:page ri:content-title="2011-11-09 Meeting Agenda" /></ac:link><br />
(2) <a class="external-link" href="http://zend-framework-community.634137.n4.nabble.com/A-ZF2-Cli-module-td3865659.html">http://zend-framework-community.634137.n4.nabble.com/A-ZF2-Cli-module-td3865659.html</a><br />
(3) <a class="external-link" href="http://zend-framework-community.634137.n4.nabble.com/Cli-Prototype-td3922653.html">http://zend-framework-community.634137.n4.nabble.com/Cli-Prototype-td3922653.html</a><br />
(4) <a class="external-link" href="http://zend-framework-community.634137.n4.nabble.com/Parsing-console-arguments-td3934526.html">http://zend-framework-community.634137.n4.nabble.com/Parsing-console-arguments-td3934526.html</a><br />
(5) <a class="external-link" href="http://zend-framework-community.634137.n4.nabble.com/Improving-Zend-Console-td3934296.html">http://zend-framework-community.634137.n4.nabble.com/Improving-Zend-Console-td3934296.html</a><br />
(6) <ac:link><ri:page ri:content-title="RFC - Module Installation and Distribution" /></ac:link><br />
(7) <a class="external-link" href="https://github.com/zendframework/zf2/tree/master/library/Zend/Tool/Framework/Client/Console/ResponseDecorator">https://github.com/zendframework/zf2/tree/master/library/Zend/Tool/Framework/Client/Console/ResponseDecorator</a><br />
(8) <a class="external-link" href="http://framework.zend.com/wiki/display/ZFDEV2/RFC+-+Module+Installation+and+Distribution#RFC-ModuleInstallationandDistribution-CLIPyrusChannelPublishing">http://framework.zend.com/wiki/display/ZFDEV2/RFC+-+Module+Installation+and+Distribution#RFC-ModuleInstallationandDistribution-CLIPyrusChannelPublishing</a><br />
(9) <a class="external-link" href="https://github.com/zendframework/zf2/tree/master/library/Zend/Tool/Framework/Client/Interactive">https://github.com/zendframework/zf2/tree/master/library/Zend/Tool/Framework/Client/Interactive</a></p>