<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>webFRACtor</title>
	<atom:link href="http://webfractor.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://webfractor.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Fri, 25 Mar 2011 18:33:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='webfractor.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>webFRACtor</title>
		<link>http://webfractor.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://webfractor.wordpress.com/osd.xml" title="webFRACtor" />
	<atom:link rel='hub' href='http://webfractor.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Using Zend Framework from the Command Line</title>
		<link>http://webfractor.wordpress.com/2008/08/14/using-zend-framework-from-the-command-line/</link>
		<comments>http://webfractor.wordpress.com/2008/08/14/using-zend-framework-from-the-command-line/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 19:29:32 +0000</pubDate>
		<dc:creator>Jed</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Zend_Framework]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Console_Getopt]]></category>

		<guid isPermaLink="false">http://webfractor.wordpress.com/?p=3</guid>
		<description><![CDATA[Want to write CLI scripts and still have access to everything the Zend_Framework has to offer?  Read on...<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webfractor.wordpress.com&amp;blog=4510319&amp;post=3&amp;subd=webfractor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using the Zend Framework since roughly Beta 0.8 and have been thoroughly impressed with its evolution.  Besides web sites I also like using php from the command line for things like cron jobs, shell scripts and the like.  While it isn&#8217;t always the best suited language for such tasks, my familiarity with php often lets me get the job done faster than with another less familiar language.  A few days ago I sat down and figured out how to get full access to the Zend Framework, including MVC, from the command line.  Here&#8217;s how I did it&#8230;</p>
<p>This project is solely for cli use, it will contain a number of scripts running in the same &#8220;framework.&#8221;  There is no web interface for this at all.  I&#8217;m going to use a modified modular conventional file system to allow me to easily addon more scripts as I need them and still share the same infrastructure.   My file system looks like this:</p>
<pre>
.-- project root
|-- application
|   |-- apis
|   |-- config
|   |-- layouts
|   |-- library
|   |   |-- Webf
|   |   `-- Zend
|   |-- models
|   |-- modules
|   |   |-- default
|   |   |   |-- config
|   |   |   |-- controllers
|   |   |   |-- models
|   |   |   `-- views
|   |   |       |-- filters
|   |   |       |-- helpers
|   |   |       |-- layouts
|   |   |       `-- scripts
|   |   `-- moduleX
|   |       |-- config
|   |       |-- controllers
|   |       |-- models
|   |       `-- views
|   |           |-- filters
|   |           |-- helpers
|   |           |-- layouts
|   |           `-- scripts
|   |-- tests
|   `bootstrap.php
|-- data
|   |-- cache
|   |-- indexes
|   |-- locales
|   |-- logs
|   |-- sessions
|   `-- uploads
|-- docs
|-- tmp
'zfcli.php
</pre>
<p><em>* Not all of these directory are needed for this application.</em></p>
<p>Typically you would have a public (htdocs, www, etc..) folder for the web root, however since this isn&#8217;t a web project I&#8217;m using zfcli.php as my &#8220;bootstrap&#8221; file, which is located in the project root.  This file will glue Zend_Console_Getopt together with Zend_Controller_Request_Simple to get arguments from the command line into the request object. This will allow us to use ZF to its full potential from the command line.</p>
<p>Lets go ahead an create a simple IndexController and view so we have something to shoot for:</p>
<p><em><strong>./application/modules/default/controllers/IndexController.php</strong></em><br />
<pre class="brush: php;">
class IndexController extends Zend_Controller_Action
{
    public function indexAction() {}
}
</pre></p>
<p><strong><em>./application/modules/default/views/scripts/index/index.phtml</em></strong><br />
<pre class="brush: php;">
echo &quot;default:index:index\n\n&quot;;
</pre><br />
I&#8217;ll assume you understand the above, if not please check google for some getting started with Zend Framework tutorials.</p>
<p>Ok, we&#8217;re ready to get going.  First up we need the bootstrap file:</p>
<p><strong><em>./zfcli.php</em></strong><br />
<pre class="brush: php;">
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors',true);
$pthRoot = dirname(__FILE__);
set_include_path('.' . PATH_SEPARATOR . $pthRoot . '/application/library'
    . PATH_SEPARATOR . $pthRoot . '/application/models'
    . PATH_SEPARATOR . get_include_path());
date_default_timezone_set('America/Chicago');

require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();

try {
    $opts = new Zend_Console_Getopt(
        array(
            'help|h' =&amp;gt; 'Displays usage information.',
            'action|a=s' =&amp;gt; 'Action to perform in format of module.controller.action',
            'verbose|v' =&amp;gt; 'Verbose messages will be dumped to the default output.',
            'development|d' =&amp;gt; 'Enables development mode.',
        )
    );
    $opts-&amp;gt;parse();
} catch (Zend_Console_Getopt_Exception $e) {
    exit($e-&amp;gt;getMessage() .&quot;\n\n&quot;. $e-&amp;gt;getUsageMessage());
}

if(isset($opts-&amp;gt;h)) {
    echo $opts-&amp;gt;getUsageMessage();
    exit;
}

if(isset($opts-&amp;gt;a)) {
    $reqRoute = array_reverse(explode('.',$opts-&amp;gt;a));
    @list($action,$controller,$module) = $reqRoute;
    $request = new Zend_Controller_Request_Simple($action,$controller,$module);
    $front = Zend_Controller_Front::getInstance();

    $front-&amp;gt;setRequest($request);
    $front-&amp;gt;setRouter(new Webf_Controller_Router_Cli());

    $front-&amp;gt;setResponse(new Zend_Controller_Response_Cli());

    $front-&amp;gt;throwExceptions(true);
    $front-&amp;gt;addModuleDirectory($pthRoot . '/application/modules/');

    $front-&amp;gt;dispatch();
}
</pre><br />
Here we have setup Zend_Console_Getopt with several possible parameters, -a being the one we will use to get the module.controller.action route for the MVC.  After setting up Getopt, we parse() the command line options.  Should an exception be encountered we want to catch it, display the error message and then show the usage message.  Using -h will also show us the usage message.</p>
<p>Then last if{} block is where we get the unification going.  By exploding on &#8220;.&#8221; we get an array of the module, controller and action, reversing the order makes it easier to deal with missing modules.  Break this new array out into individual variables then plug them into Zend_Controller_Request_Simple. if you don&#8217;t use the @ in front of the list() statement you will get warnings when there is no module supplied, since I want to use default in these cases I just make it not report these errors, the router will automatically look for the &#8220;default&#8221; module.</p>
<p>Next we instantiate the front controller and tell it to use the request we just built.  Next up we need a router that can be used in the CLI environment.  Notice I&#8217;ve made a custom router, more on that in a bit. We also need to use the Zend_Controller_Response_Cli response object, tell it where the modules are, tell it to throw exceptions.  Finally we dispatch the controller and our scripts are off and running.</p>
<p><em><strong>./application/library/Webf/Controller/Router/Cli.php</strong></em><br />
<pre class="brush: php;">
require_once ('Zend/Controller/Router/Interface.php');
require_once ('Zend/Controller/Router/Abstract.php');

class Webf_Controller_Router_Cli extends Zend_Controller_Router_Abstract implements Zend_Controller_Router_Interface {

    public function assemble($userParams, $name = null, $reset = false, $encode = true) { }

    public function route(Zend_Controller_Request_Abstract $dispatcher) {}
}
</pre><br />
The router is really very simple, though it took me a bit to figure this out.  In order to ensure compatibility we need to extend the Router_Abstract and implement the Router_Interface.  If, like me, you use a Zend IDE, like Zend Studio for Eclipse, and make use of the class wizards you can end up with a short list of methods to implement.  In fact you only need two and they can be stubs.</p>
<p>That&#8217;s it, you&#8217;re in business.  Try running <strong><em>php zfcli.php -a index.index</em></strong> and see what happens.  You should see default:index:index just above your prompt <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/webfractor.wordpress.com/3/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/webfractor.wordpress.com/3/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webfractor.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webfractor.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webfractor.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=webfractor.wordpress.com&amp;blog=4510319&amp;post=3&amp;subd=webfractor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://webfractor.wordpress.com/2008/08/14/using-zend-framework-from-the-command-line/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d674fd1cddff59f7a9dad88ae4e7ef63?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Jed</media:title>
		</media:content>
	</item>
	</channel>
</rss>
