Skip to end of metadata
Go to start of metadata

<p>Zend_Tool for the Developer</p>

<p>By now, you have probably read the <a href="http://devzone.zend.com/article/3811-Using-Zend_Tool-to-start-up-your-ZF-Project&quot;&gt;earlier article</a> on getting Zend_Tool installed and working on your development machine... (or at least you should have!) And you might have casually played with it, or perhaps you are using it to create the general scaffold for your ZF MVC based projects. Either way, at some point you are bound to ask the question "how do I extend Zend_Tool?"</p>

<p>Background on Zend_Tool_Framework</p>

<p>In order to understand how to extend Zend_Tool, you need to know a few things about its overall structure. The whole of the system was built with extensibility in mind. Each of the major functional parts of the system are abstracted in such a way that its easy to not only extend, but to replace with completely separate implementations. For example, our initial interface to this system is a command line interface (cli), but its just as easy to replace the cli interface with an XML-RPC interface, or a web interface. Once replaced, the internals of the tooling system can remain the same, but you'll see that you can issue requests to the system from drastically different environments.</p>

<p>We will strictly be dealing with the CLI client for this system in this article, but its important to know that CLI could just as easily be some other environment. To understand in greater detail how these different parts work together, you can read both the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Tool_Framework+<span style="text-decoration: line-through;"><span style="text-decoration: underline;">Ralph+Schindler">RPC System/internals of Zend_Tool proposal</a>, and also have a look at the <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Tool_Framework_Client_Cli</span></span>+Ralph+Schindler">CLI Specific Implementation proposal</a>.</p>

<p>But for our first order of business, we'll demonstrate how to add new commands to the Zend_Tool system.</p>

<p>Hello World!</p>

<p>Out of the box, Zend_Tool finds all its commands on php's include_path. Finding which files might contain what Zend_Tool calls "Providers", is based off of some conventions set by the default Zend_Tool loader. When Zend_Tool starts up, the first thing it does is scan all the paths in your include_path in order to find files that match the regular expression ".*(?:Tool|Manifest|Provider)\.php". That essentially says any files that end in Tool.php, Manifest.php or Provider.php. Once it finds these files, it will require_once them into the runtime, and look for any classes within them that implement either the Zend_Tool_Framework_Manifest_Interface interface or the Zend_Tool_Framework_Provider_Interface interface. If they do indeed implement this interface, these classes are loaded into the tooling system and can now be called by your client.</p>

<p>To illustrate how this works, open two files in a text editor, first Zend/Tool/Framework/System/Manifest.php, then Zend/Tool/Framework/System/Provider/Version.php. First thing to note is that Zend/Tool/Framework/System/Manifest.php ends in Manifest.php and the class within it (Zend_Tool_Framework_System_Manifest) implements Zend_Tool_Framework_Manifest_Interface. Classes implementing the Zend_Tool_Framework_Manifest_Interface interface allow us to tell the tooling system which "providers" can be loaded and used. This method allows us to specify multiple providers without explicitly naming them XXXXProvider.php. As you can see, in the getProviders() method, you'll notice that it returns an array of two classes, one of those classes is Zend_Tool_Framework_System_Provider_Version.</p>

<p>Now, lets turn our attention to the Zend/Tool/Framework/System/Provider/Version.php file. As you can see, the class in this file implements Zend_Tool_Framework_Provider_Interface, thus it "provides" a set of capabilities that can be dispatched from the tooling system. In our last article, we saw the command "zf show version". Effectively, that ran the show() method from the Zend_Tool_Framework_System_Provider_Version class.</p>

<p>Without getting into the gory details, there is are a few things we want to take away from this exercise:<br />
1) Zend/Tool/Framework/System/Manifest.php is in the php include_path, so it can be found by the Zend_Tool loader.<br />
2) Zend_Tool_Framework_System_Manifest implements Zend_Tool_Framework_Manifest_Interface which allows Zend_Tool to know what providers to load.<br />
3) Zend_Tool_Framework_System_Provider_Version is in the aforementioned Manifest file AND it implements Zend_Tool_Framework_Provider_Interface, so Zend_Tool can dispatch this "provider"<br />
4) Zend_Tool_Framework_System_Provider_Version has a show() method which can be called from the command line "zf show version", where Version is the short name for this provider.</p>

<p>So, with that newly acquired knowledge, we should be able to create a hello world provider. Assuming your include_path is /usr/lib/php, lets create a file at this location: /usr/lib/php/My/HelloWorldProvider.php</p>

<p>Inside that file, we will put this following code:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
<?php

class My_HelloWorldProvider implements Zend_Tool_Framework_Provider_Interface
{

public function say()

Unknown macro: { echo 'Hello World!'; }

}
]]></ac:plain-text-body></ac:macro>

<p>Save file, and now on the command line, we should be able to issue the following command:</p>

<p>zf say hello-world</p>

<p>You SHOULD receive output that looks like this:</p>

<p>~$ zf say hello-world<br />
Hello World!<br />
~$</p>

<p>Thats it! So lets review what just happened here:<br />
1) we created a file that ended in Provider.php (My/HelloWorldProvider.php) in our include_path.<br />
2) the class My_HelloWorldProvider implements Zend_Tool_Framework_Provider_Interface<br />
3) we saved the file, and issued the command "zf say hello-world"</p>

<p>At this point you might have a few questions:</p>

<p> How do I know what the provider name is?</p>

<p> The provider name is the <b>last segment</b> name of the class with the words "Provider" or "Manifest" stripped off the end. There are ways to override this behavior, but that is a topic for a more in-depth article.</p>

<p> Why is the provider name dash-separated on the command line, but camel case in the class?</p>

<p> The idiom you use within a specific environment (or are generally used to seeing), is kept consistent with respect to the environment you are in. So for command line, dash-separated is the common format, and in OO code, CamelCase is the common format. Zend_Tool strives to keep these namings consistent with the environment they are in.</p>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Dec 02, 2008

    <p>The more I think about the more I'm convinced that Zend_Application and Zend_Tool resource loading should look similar and that both could be simpler. Maybe we should simply reserve ZFTool and ZFResource as package names so we can pick up any class in those packages for use with Zend_Tool and Zend_Application, respectively. It's just one ideas; I'm having a hard time keeping up with all the different ways to define entities in the current proposal.<br />
    Of course, having too much flexibility with sane defaults is much less concerning than too little flexibility.</p>

  2. Mar 22, 2010

    <p>You now have to manually configure your providers. Add custom providers in the ZF config file by editing <strong>~/.zf.ini</strong> and adding:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    php.include_path = ".:/path/to/zf/library:/path/to/your-tool/library:/path/to/pear"

    basicloader.classes.1 = "Your_Tool_Project_Provider_Manifest"
    ]]></ac:plain-text-body></ac:macro>
    <p>You can also include them using something like:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    zf enable config.manifest class-name
    ]]></ac:plain-text-body></ac:macro>
    <p>See <strong>zf enable config.?</strong> for more details.</p>