Version 1 by Ralph Schindler
on Oct 06, 2008 10:37.

compared with
Current by Ralph Schindler
on Dec 22, 2008 07:32.

Key
This line was removed.
This word was removed. This word was added.
This line was added.

Changes (50)

View Page History
<p>So, now you have seen how to add commands to the zf tooling system. But what if you want to interact with a "Project". &quot;Project&quot;. I guess the bigger question is, what is a "Project"? &quot;Project&quot;? In general, a "project" &quot;project&quot; is a planned endeavor or an initiative. In the computer world, projects generally are a collection of resources. These resources can be files, directories, databases, schemas, images, styles, and more. </p>

<p>This same concept applies to Zend Framework projects. In ZF projects, you have controllers, actions, views, databases and so on and so forth. In terms of Zend_Tool, we need a way to track these types of resources - thus Zend_Tool_Project.</p>

<p>Zend_Tool_Project is capable of tracking project resources throughout the development of a project. So, for example, if in one command you created a controller, and in the next command you wish to create an action within that controller, Zend_Tool_Project is gonna have to *know* <strong>know</strong> about the controller file you created so that you can (in the next action), be able to append that action to it. This is what keeps our projects up to date and *stateful*. <strong>stateful</strong>.</p>

<p>Another important point to understand about projects is that typically, resources are organized in a hierarchical fashion. With that in mind, Zend_Tool_Project is capable of serializing the current project into a internal representation that allows it to keep track of not only *what* <strong>what</strong> resources are part of a project at any given time, but also *where* <strong>where</strong> they are in relation to one another.</p>

<p>So, with that out of the way, lets get to the code. In the below example, we will create a provider that will expose a command called "create mymodel" &quot;create mymodel&quot; which will be a very simple model in our existing project.</p>

<p>As you might recall from Part 1, we first need to create a provider which we will name "Example_MyModelProvider". &quot;My_ModelProvider&quot;. At this point, since our new provider will be Zend_Tool_Project specific, we will extend Zend_Tool_Project's special Provider Abstract. By extending this special provider abstract, we not only are implementing the Zend_Tool_Rpc_Provider_Interface, Zend_Tool_Framework_Provider_Interface, but we are also gaining some common functionality for "Projects" &quot;Projects&quot; that we will need.</p>

{code}
class Example_MyModelProvider implements ZendL_Tool_Project_Provider_Abstract
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class My_ModelProvider implements Zend_Tool_Project_Provider_Abstract
{


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

<p>As you can see, this is all we need to have in order to expose a "create" &quot;create&quot; method for our "mymodel" &quot;model&quot; provider. (Remember, this file will have to exist inside your include_path, at the location Example/MyModelProvider.php My/ModelProvider.php to be found by the Zend_Tool system.)</p>

<p>At this point we have a provider that can be dispatched and essentially won't do much of anything useful as you can see by the empty method body for create. Our next step is to provide that method body which will include some of our own custom logic as well as some logical that is specific to how *new <strong>new resources are integrated with existing projects*. projects</strong>.</p>

Now is a good time to understand how projects are stored with respect to Zend_Tool_Project. To gain this insight, lets go back to our article on <a href="">getting started with Zend_Tool</a>. After the step in that article where we have run "zf create project", lets have a look at the hidden file that was created. It can be found inside the project directory with a name of ".zfproject.xml". It should look like this:
<p>Now is a good time to understand how projects are stored with respect to Zend_Tool_Project. To gain this insight, lets go back to our article on &lt;a href=&quot;&quot;&gt;getting started with Zend_Tool&lt;/a&gt;. After the step in that article where we have run &quot;zf create project&quot;, lets have a look at the hidden file that was created. It can be found inside the project directory with a name of &quot;.zfproject.xml&quot;. It should look like this:</p>

{code}
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
<?xml version="1.0"?>
<projectProfile>
</projectDirectory>
</projectProfile>
{code}
]]></ac:plain-text-body></ac:macro>

This file represents how Zend_Tool_Project manages resources in a hierarchical fashion. For the purposes of our example, we want to be able to add our new "MyModels" into the "ModelsDirectory" of this project. In addition, we want to make sure that our project understands the context of these new resources. What is meant by "context" is so that our project understands what "role" this new resources plays within our project. For example, first and foremost, our "MyModel" resource is a file, so the project knows that this can be written to disk when asked to. Also, it understand that its a "MyModel" resource, and can have some custom logic assigned to it so that is *acts* like a MyModel with respect to other resources.
<p>This file represents how Zend_Tool_Project manages resources in a hierarchical fashion. For the purposes of our example, we want to be able to add our new &quot;Models&quot; into the &quot;ModelsDirectory&quot; of this project. In addition, we want to make sure that our project understands the context of these new resources. What is meant by &quot;context&quot; is so that our project understands what &quot;role&quot; this new resources plays within our project. For example, first and foremost, our &quot;Model&quot; resource is a file, so the project knows that this can be written to disk when asked to. Also, it understand that its a &quot;Model&quot; resource, and can have some custom logic assigned to it so that is <strong>acts</strong> like a Model with respect to other resources.</p>

<p>To be able to assign a context to these resources when they are created, we will also need to create a context class that we can use.</p>

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

require_once 'ZendL/Tool/Project/Structure/Context/Filesystem/Directory.php'; 'Zend/Tool/Project/Context/Filesystem/Directory.php';

class Example_MyModelFileContext extends ZendL_Tool_Project_Structure_Context_Filesystem_File Zend_Tool_Project_Context_Filesystem_File
{
// proteted property to hold the actual models name

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

<p>Now that we have a context, we can start interacting with our project when our create method is called. Lets walk through the code sample below line by line (there will be comments before each line).</p>

{code}
class Example_MyModelProvider implements ZendL_Tool_Project_Provider_Abstract
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class My_ModelProvider implements Zend_Tool_Project_Provider_Abstract
{

// find where we need to write these new model files
// a graph is the serialized structure as objects
$projectGraph = $this->_loadExistingStructureGraph(); $this->_loadProjectProfile();

// lets get a pointer to the node within the graph identified by the
// Now, lets create a new node within our project that will be defined
// by the context we created previously under the existing 'modelsDirectory'
// context called "modelsDirectory" try {
// b/c after all this is where we want to put our models $modelFileNode = $this->_createNodeUnder('modelsDirectory');
$modelsDirectoryNode = $graph->findNodeByContext('modelsDirectory'); } catch (Exception $e) {

// lets do some error checking
if (!$modelsDirectoryNode) {
throw new ZendL_Tool_Rpc_Exception('This Zend_Tool_Framework_Exception('This project doesnt have a models directory');
}

// Now, lets create a new node within our project that will be defined
// by the context we created previously
$modelFileNode = new ZendL_Tool_Project_Structure_Node(new Example_MyModelFileContext());

// Since we know our new node is filesystem based, we should give it its full path
// on disk so it can be written to the correct place
$modelFileNode->setBaseDirectory($modelsDirectoryNode->getContext()->getPath());

// lets give our new model its name provided by the caller.
$modelFileNode->setModelName($modelname);
// our project
$this->_createMyModelContents($modelFileNode->getPath(), $modelname);

$modelsDirectoryNode->append($modelFileNode);

$this->_storeLoadedStructureGraph(); $this->_storeProfile();
}


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

<p>Now that we have those two file in place, its just a matter or running the command:</p>

{code}
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
zf create mymodel --modelname Foo
{code}
]]></ac:plain-text-body></ac:macro>

<p>And there you go, now you have created both a provider and a project context so that you can add custom resources to an existing project!</p>