<?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/"
	>

<channel>
	<title>Chris Abernethy . com&#187; Zend Framework</title>
	<atom:link href="http://www.chrisabernethy.com/category/zend-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chrisabernethy.com</link>
	<description></description>
	<lastBuildDate>Wed, 31 Mar 2010 14:42:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Extracting Translatable Strings From Zend_Validate</title>
		<link>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fextracting-translatable-strings-from-zend_validate%2F&amp;seed_title=Extracting+Translatable+Strings+From+Zend_Validate</link>
		<comments>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fextracting-translatable-strings-from-zend_validate%2F&amp;seed_title=Extracting+Translatable+Strings+From+Zend_Validate#comments</comments>
		<pubDate>Thu, 24 Apr 2008 01:05:59 +0000</pubDate>
		<dc:creator>Brownoxford</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.chrisabernethy.com/?p=33</guid>
		<description><![CDATA[This article presents a scripted method for using ReflectionClass to extract translatable strings from concrete Zend_Validate class files for use with Zend_Translate.]]></description>
			<content:encoded><![CDATA[<p>Recently I started working with Zend Framework's Zend_Form and its integrated automatic translation functionality using Zend_Translate. In general, the functionality is really great, but if you have ever tried to translate all of the possible validation error messages, you know that finding them can be a long manual task. Naturally, I brought this up on <a href="irc://irc.freenode.org/#zftalk" rel="nofollow" >#zftalk</a>, and the consensus seemed to be that the translatable messages could be extracted using a little PHP and ReflectionClass magic.</p>
<span id="more-33"></span>
<h2>ReflectionClass to the Rescue</h2>

<p>The following is the script that I came up with, which pulls translatable error messages along with available message variables and generates a data structure based on the class name of the validators. Here is the script in its entirety, with some short comments describing how it works:</p>

<pre lang="php">
$zend_library = "/my/php/library";
set_include_path($zend_library);

// Create a new RecursiveDirectoryIterator for the Zend_Validate
// directory and recursively iterate over the files.

$messages = array();
$rdi = new RecursiveDirectoryIterator($zend_library . '/Zend/Validate');
foreach (new RecursiveIteratorIterator($rdi) as $path) {

    // Read in the file and generate the expected class name by
    // converting the portion of the path starting with Zend/Validate
    // and replacing '/' with '_'. For example, this converts the path
    // Zend/Validate/Regex.php to Zend_Validate_Regex.

    require_once($path);
    $class = strtr(preg_replace('#.*(Zend/Validate/.*)\.php$#', '\1', $path), '/', '_');

    if (class_exists($class)) {

        // If the expected class exists, create a ReflectionClass
        // instance and fetch the properties of the class. Make
        // sure that the property '_messageTemplates' exists, as
        // this indicates that we are dealing with an actual concrete
        // Zend_Validate class.

        $reflection = new ReflectionClass($class);
        if ($reflection->hasProperty('_messageTemplates')) {

            // Get the default properties as an associative array and
            // add the 'value' key to the _messageVariables property
            // since by default, 'value' is always available for substitution
            // into a message template.

            $props = $reflection->getDefaultProperties();
            $props['_messageVariables']['value'] = true;

            // Add an element to the $messages array, keyed on
            // the name of the current class. The element contains
            // an array of translatable templates, and an array of
            // valid message variables that can be substituted into
            // those templates.

            $messages[$class] = array(
                'templates' => $props['_messageTemplates']
              , 'variables' => array_keys($props['_messageVariables'])
            );
        }
    }
}

</pre>

<p>Printing out an element of the $messages array shows the structure that is now available to work with, which brings us to the next step... what can we do with this data?</p>

<pre lang="php">
print_r($messages['Zend_Validate_Regex']);

Array
(
    [templates] => Array
        (
            [regexNotMatch] => '%value%' does not match against pattern '%pattern%'
        )
    [variables] => Array
        (
            [0] => pattern
            [1] => value
        )
)
</pre>

<h2>Processing the Output</h2>

<p>Now we have the data that we need to start providing translations, what can be done with it? I am using the Zend_Translate_Tmx translation adapter, so I iterate over the data and write out a single TMX 1.4 format file for all of my validation error translations (including some notes regarding the source of the translatable string as well as the possible variables that can be used). The following code illustrates how this is done:</p>

<pre lang="php">
$format = '
        &lt;tu tuid="%s"&gt;
            &lt;note>Validation message template for class %s.&lt;/note&gt;
            &lt;note>Possible variables include %s&lt;/note&gt;
            &lt;tuv xml:lang="en"&gt;
                &lt;seg>%s&lt;/seg&gt;
            &lt;/tuv&gt;
        &lt;/tu&gt;
';

echo &lt;&lt;&lt;XML
&lt;?xml version="1.0" ?&gt;
&lt;!DOCTYPE tmx SYSTEM "http://www.lisa.org/fileadmin/standards/tmx1.4/tmx14.dtd.txt"&gt;
&lt;tmx version="1.4"&gt;
    &lt;header creationtool="Reflection" creationtoolversion="1.0" datatype="winres" segtype="sentence" adminlang="en-us" srclang="en-us" o-tmf="txt"&gt;
    &lt;/header&gt;
    &lt;body&gt;
XML;

foreach ($messages as $class_name => $data) {
    $variables = join(', ', $data['variables']);
    foreach ($data['templates'] as $key => $template) {
        printf($format, $key, $class_name, $variables, $template);
    }
}

echo "    &lt;/body&gt;\n"
  .  "&lt;/tmx&gt;\n";
</pre>

<p>The collected data can of course also be formatted in whatever way is required by the type of Zend_Validate_Adapter that you are using.</p>

<p>Hopefully this will save you some time in your translation efforts. One thing to watch out for is that several validators re-use messageTemplate identifiers and so cannot be translated (see bug <a href="http://framework.zend.com/issues/browse/ZF-3164" rel="nofollow" >ZF-3164</a> for more info).</p>



	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate&amp;title=Extracting%20Translatable%20Strings%20From%20Zend_Validate&amp;bodytext=This%20article%20presents%20a%20scripted%20method%20for%20using%20ReflectionClass%20to%20extract%20translatable%20strings%20from%20concrete%20Zend_Validate%20class%20files%20for%20use%20with%20Zend_Translate." title="Digg"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate&amp;title=Extracting%20Translatable%20Strings%20From%20Zend_Validate" title="StumbleUpon"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://sphinn.com/index.php?c=post&amp;m=submit&amp;link=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate" title="Sphinn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/sphinn.png" title="Sphinn" alt="Sphinn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate&amp;title=Extracting%20Translatable%20Strings%20From%20Zend_Validate&amp;notes=This%20article%20presents%20a%20scripted%20method%20for%20using%20ReflectionClass%20to%20extract%20translatable%20strings%20from%20concrete%20Zend_Validate%20class%20files%20for%20use%20with%20Zend_Translate." title="del.icio.us"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate&amp;title=Extracting%20Translatable%20Strings%20From%20Zend_Validate&amp;source=Chris+Abernethy+.+com+&amp;summary=This%20article%20presents%20a%20scripted%20method%20for%20using%20ReflectionClass%20to%20extract%20translatable%20strings%20from%20concrete%20Zend_Validate%20class%20files%20for%20use%20with%20Zend_Translate." title="LinkedIn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fextracting-translatable-strings-from-zend_validate%252F%26amp%3Bseed_title%3DExtracting%2BTranslatable%2BStrings%2BFrom%2BZend_Validate&amp;t=Extracting%20Translatable%20Strings%20From%20Zend_Validate" title="Facebook"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="" title="TwitThis"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/" title="TwitThis" alt="TwitThis" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fextracting-translatable-strings-from-zend_validate%2F&amp;seed_title=Extracting+Translatable+Strings+From+Zend_Validate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Benchmarking Zend Framework Routes</title>
		<link>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-route-benchmarks%2F&amp;seed_title=Benchmarking+Zend+Framework+Routes</link>
		<comments>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-route-benchmarks%2F&amp;seed_title=Benchmarking+Zend+Framework+Routes#comments</comments>
		<pubDate>Fri, 11 Jan 2008 03:34:51 +0000</pubDate>
		<dc:creator>Brownoxford</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.chrisabernethy.com/2008/01/10/zend-framework-route-benchmarks/</guid>
		<description><![CDATA[There are usually several different ways to define the same route using Zend Framework, and the choice of which route type to use is often arbitrary or based on the personal preference of the programmer. I happen to prefer using regex routes over standard routes when positional parameters need to be used, but the opinion on the <a href="irc://irc.freenode.org/#zftalk">#zftalk</a> channel on freenode was that regex routes are always slower than standard routes. This article presents benchmark numbers for both route types obtained using xdebug and kcachegrind. This won't be a full tutorial on how to use xdebug or kcachegrind, so I won't go into great details about how to use them, but the full source code for the benchmarks will be available at the end of the article.]]></description>
			<content:encoded><![CDATA[<p>Hanging out in <a href="irc://irc.freenode.org/#zftalk" rel="nofollow" >#zftalk</a> on freenode is a great way to learn more about using Zend Framework, if you're not already there get yourself an IRC client and sign on. Recently, the following question was posed:</p>

<blockquote>
<p>
How can I create a route with an optional parameter; e.g /search/:foo/:bar, where :bar is optional? Do I need to create two different routes?
</p>
</blockquote>

<p>Several users correctly suggested specifying a default value for :bar when constructing the route, and it was also mentioned that both standard routes and regular expression routes could be used to solve the problem. Naturally, this lead to a discussion of which type of route would be fastest, with no real numbers to fall back on.</p>
<span id="more-26"></span>
<p>The purpose of this article is to present benchmark numbers for both route types (for the specific application described above) and to describe the methods used to run the benchmark tests. This won't be a full tutorial on how to use xdebug or kcachegrind, so I won't go into great details about how to use them, but the full source code for the benchmarks will be available at the end of the article.</p>

<h2>Method</h2>

<p>In order to profile the different routing options, <a href="http://xdebug.org" rel="nofollow" >xdebug</a> was used in profiling mode and the resulting profile data was viewed in <a href="http://kcachegrind.sourceforge.net/cgi-bin/show.cgi" rel="nofollow" >kcachegrind</a>. The profiling test uses two URLs, one with the optional parameter and one without. Each router's <code>match()</code> method is called 10000 with each of the two URLs.</p>

<h2>The Standard Route</h2>

<p>The first route tested was the standard route, which is instantiated with a string describing the route, and an array of default options. The route accepts two parameters, indicated by :foo and :bar. Since a default value is specified for :bar in the initialization array, the route will match both of our test URLs, using the value 'mybar' if no parameter is given for :bar.</p>

<pre lang="php">
$route = new Zend_Controller_Router_Route(
    'search/:foo/:bar'
  , array(
        'controller' => 'search'
      , 'action'     => 'index'
      , 'bar'        => 'mybar'
    )
);
</pre>

<h2>The Regex Route</h2>

<p>The next route tested was the regex route, which is instantiated in the same way as the standard route, with the addition of an array that maps parameter positions to value names; this allows the route map the results from an internal <code>preg_match</code> call to the numerically keyed captured parameters.</p>

<pre lang="php">
$route = new Zend_Controller_Router_Route_Regex(
    'search/(\w+)(?:/(\w+))'
  , array(
        'controller' => 'search'
      , 'action'     => 'index'
      , 'bar'        => 'mybar'
    )
  , array(
        'foo' => 1
      , 'bar' => 2
    )
);
</pre>

<h2>The Results</h2>

<p>The initial test with 10,000 iterations using the test URL that contained both the foo and bar parameters shows that the standard route is faster than the regex route by about 12%. The image at right is a kcachegrind visualization of the call tree rooted in the function that executes the two tests with a distance limit of 1.</p>

<div style="margin:15px 0;text-align:center;">
<img src='http://www.chrisabernethy.com/wp-content/uploads/2008/01/10k_with_optional.png' alt='Zend Router Profiling (part one)' />
</div>

<p>The second test of 10,000 iterations used the test URL with did <em>not</em> contain the bar parameter. It shows that the regex route is significantly faster than the standard route by about 48%.</p>

<div style="margin:15px 0;text-align:center;">
<img src='http://www.chrisabernethy.com/wp-content/uploads/2008/01/10k_without_optional.png' alt='Zend Router Profiling (part two)' />
</div>

<p>Based on these tests, it seems like the best choice depends on how often the optional parameter is expected to be provided. If the answer is less than about 60% of the time, the regex route would seem like the best choice; otherwise the regex route will be faster. Keep in mind that this is all based on a specific route, and your situation may vary so if performance is an issue some custom tests may be in order.</p>

<p>If you are interested in reproducing these benchmarks, you can <a href="http://www.chrisabernethy.com/wp-content/uploads/2008/10/zf_benchmark_routes.tgz" title="Benchmarking Code">download the benchmarking scripts</a> and customize them as needed.</p>




	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes&amp;title=Benchmarking%20Zend%20Framework%20Routes&amp;bodytext=There%20are%20usually%20several%20different%20ways%20to%20define%20the%20same%20route%20using%20Zend%20Framework%2C%20and%20the%20choice%20of%20which%20route%20type%20to%20use%20is%20often%20arbitrary%20or%20based%20on%20the%20personal%20preference%20of%20the%20programmer.%20I%20happen%20to%20prefer%20using%20regex%20routes%20over%20standard%20routes%20when%20positional%20parameters%20need%20to%20be%20used%2C%20but%20the%20opinion%20on%20the%20%23zftalk%20channel%20on%20freenode%20was%20that%20regex%20routes%20are%20always%20slower%20than%20standard%20routes.%20This%20article%20presents%20benchmark%20numbers%20for%20both%20route%20types%20obtained%20using%20xdebug%20and%20kcachegrind.%20This%20won%27t%20be%20a%20full%20tutorial%20on%20how%20to%20use%20xdebug%20or%20kcachegrind%2C%20so%20I%20won%27t%20go%20into%20great%20details%20about%20how%20to%20use%20them%2C%20but%20the%20full%20source%20code%20for%20the%20benchmarks%20will%20be%20available%20at%20the%20end%20of%20the%20article." title="Digg"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes&amp;title=Benchmarking%20Zend%20Framework%20Routes" title="StumbleUpon"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://sphinn.com/index.php?c=post&amp;m=submit&amp;link=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes" title="Sphinn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/sphinn.png" title="Sphinn" alt="Sphinn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes&amp;title=Benchmarking%20Zend%20Framework%20Routes&amp;notes=There%20are%20usually%20several%20different%20ways%20to%20define%20the%20same%20route%20using%20Zend%20Framework%2C%20and%20the%20choice%20of%20which%20route%20type%20to%20use%20is%20often%20arbitrary%20or%20based%20on%20the%20personal%20preference%20of%20the%20programmer.%20I%20happen%20to%20prefer%20using%20regex%20routes%20over%20standard%20routes%20when%20positional%20parameters%20need%20to%20be%20used%2C%20but%20the%20opinion%20on%20the%20%23zftalk%20channel%20on%20freenode%20was%20that%20regex%20routes%20are%20always%20slower%20than%20standard%20routes.%20This%20article%20presents%20benchmark%20numbers%20for%20both%20route%20types%20obtained%20using%20xdebug%20and%20kcachegrind.%20This%20won%27t%20be%20a%20full%20tutorial%20on%20how%20to%20use%20xdebug%20or%20kcachegrind%2C%20so%20I%20won%27t%20go%20into%20great%20details%20about%20how%20to%20use%20them%2C%20but%20the%20full%20source%20code%20for%20the%20benchmarks%20will%20be%20available%20at%20the%20end%20of%20the%20article." title="del.icio.us"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes&amp;title=Benchmarking%20Zend%20Framework%20Routes&amp;source=Chris+Abernethy+.+com+&amp;summary=There%20are%20usually%20several%20different%20ways%20to%20define%20the%20same%20route%20using%20Zend%20Framework%2C%20and%20the%20choice%20of%20which%20route%20type%20to%20use%20is%20often%20arbitrary%20or%20based%20on%20the%20personal%20preference%20of%20the%20programmer.%20I%20happen%20to%20prefer%20using%20regex%20routes%20over%20standard%20routes%20when%20positional%20parameters%20need%20to%20be%20used%2C%20but%20the%20opinion%20on%20the%20%23zftalk%20channel%20on%20freenode%20was%20that%20regex%20routes%20are%20always%20slower%20than%20standard%20routes.%20This%20article%20presents%20benchmark%20numbers%20for%20both%20route%20types%20obtained%20using%20xdebug%20and%20kcachegrind.%20This%20won%27t%20be%20a%20full%20tutorial%20on%20how%20to%20use%20xdebug%20or%20kcachegrind%2C%20so%20I%20won%27t%20go%20into%20great%20details%20about%20how%20to%20use%20them%2C%20but%20the%20full%20source%20code%20for%20the%20benchmarks%20will%20be%20available%20at%20the%20end%20of%20the%20article." title="LinkedIn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-route-benchmarks%252F%26amp%3Bseed_title%3DBenchmarking%2BZend%2BFramework%2BRoutes&amp;t=Benchmarking%20Zend%20Framework%20Routes" title="Facebook"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="" title="TwitThis"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/" title="TwitThis" alt="TwitThis" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-route-benchmarks%2F&amp;seed_title=Benchmarking+Zend+Framework+Routes/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Migrating to Zend Framework: Legacy Scripts</title>
		<link>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-legacy-scripts%2F&amp;seed_title=Migrating+to+Zend+Framework%3A+Legacy+Scripts</link>
		<comments>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-legacy-scripts%2F&amp;seed_title=Migrating+to+Zend+Framework%3A+Legacy+Scripts#comments</comments>
		<pubDate>Tue, 04 Dec 2007 21:27:25 +0000</pubDate>
		<dc:creator>Brownoxford</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.chrisabernethy.com/2007/12/04/zend-framework-legacy-scripts/</guid>
		<description><![CDATA[Migrating an existing PHP application to Zend Framework can be a daunting task, especially if the migration must occur all at once. It is much easier to migrate the application in sections over a longer period of time. The approach outlined here allows developers to slowly integrate Zend Framework with an existing site while still serving legacy scripts without rewriting them as MVC components.]]></description>
			<content:encoded><![CDATA[<p>Migrating an existing PHP application to Zend Framework can be a daunting task, especially if the migration must occur all at once. It is much easier to migrate the application in sections over a longer period of time. This approach requires some modification from a normal Zend Framework setup<span id="more-25"></span>, in which all requests for non-existent files are passed to the bootstrap file and dispatched, but all requests for files which do exist (images, css and, in our case, legacy scripts) bypass the bootstrap and are served directly. In our scenario, we want to be able to integrate features of the Zend Framework into the legacy scripts without rewriting them as MVC components, and without  having to duplicate code from the bootstrap (ie: in an auto_prepend file).</p>

<p>The following mod_rewrite rules will perform the normal routing of non-existent URIs to the bootstrap, but will also route requests for PHP scripts to the bootstrap (this example assumes that the rewrite rules are specified in a <a href="http://www.chrisabernethy.com/mod-rewrite-front-controller/">per-directory context</a>):</p>

<pre lang="apache">
RewriteEngine   On
RewriteCond     %{REQUEST_FILENAME} !-f    [OR]
RewriteCond     %{REQUEST_FILENAME} \.php$
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ^(.*)$ /bootstrap.php/$1 [L,NS]
</pre>

<p>Once legacy scripts are successfully being sent to the bootstrap, we need to modify it so that it does the right thing. The following code checks to see if the current request is for an existing script, and if so that script is served instead of running the front controller dispatch. Any bootstrapping that occurs before this code will be available to the legacy scripts; for example, the Zend_Registry, any config loaded with Zend_Config, Zend_Loader, etc.</p>

<pre lang="php">
$request  = new Zend_Controller_Request_Http();
$docroot = $request->get('DOCUMENT_ROOT');
$uri     = $request->getPathInfo();

if (file_exists($docroot . $uri)) {

    ob_start();
    include $docroot . $uri;

    $response = new Zend_Controller_Response_Http();
    $response->setBody(ob_get_clean());
    $response->sendResponse();

    exit;

}
</pre>

<p>This approach works well for basic sites, but what happens if you already have mod_rewrite rules in place to create SEO-friendly URLs that redirect to actual scripts? This causes a problem because the value of the actual script is not available to Zend Framework, so the request is very likely to be handled by the default /controller/action route. Consider the following example:</p>

<pre lang="apache">
RewriteRule ^/calendar/([0-9a-zA-Z_]+) /view_calendar.php?user_name=$1
</pre>

<p>As long as this rule appears in your apache configuration prior to the bootstrap routing rules outlined previously, the request for <code>/calendar/someusername</code> will be redirected via an internal subrequest to <code>/view_calendar.php?username=someusername</code>. This operation updates the <code>%{REQUEST_FILENAME}</code> value used by mod_rewrite, so the legacy script matching rule is invoked and this request is handed off to the bootstrap script.</p>

<p>The problem that we run into here, is that the bootstrap script is unaware of the update in URI, and still believes that it is handling a request for <code>/calendar/somuser</code>. Since there is a default routing rule in the front controller for paths matching the format <code>/controller/action</code>, our request is dispatched to a non-existent controller and an error is thrown.</p>

<p>This issue can be avoided by converting the SEO mod_rewrite rules into Zend Framework router rules that route to a custom subclass of Zend_Controller_Action that encapsulates the bootstrap code that we developed earlier for serving legacy scripts. Here is Zend Framework rewrite router implementation of the calendar mod_rewrite rule listed above:</p>

<pre lang="php">
$front  = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$route  = new Zend_Controller_Router_Route_Regex(
    'calendar/([0-9a-zA-Z_]+)',
    array(
        'controller' => 'legacy',
        'action'     => 'index',
        'script'     => '/view_calendar.php'
    ),
    array(
        1 => 'user_name'
    ),
    'calendar/%s'
);
$router->addRoute('calendar', $route);
</pre>

<p>In order to handle this route, we need to implement a subclass of Zend_Controller_Action called LegacyController. This class will have a single action called <code>indexAction</code> which is where our legacy script handling code will go:</p>

<pre lang="php">
class LegacyController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        $viewRenderer->setNoRender(true);

        $request = $this->getRequest();
        $docroot = $request->get('DOCUMENT_ROOT');
        $uri     = '/' . ltrim( $request->getParam('script'), '/' ); // Force leading '/'

        if (file_exists($docroot . $uri)) {
            ob_start();
            include $docroot . $uri;
            $output = ob_get_clean();
            $response = $this->getResponse();
            $response->setBody($output);
            $response->sendResponse();
        } else {
            // You could redirect to a custom 404 handler here.
        }
    }
}
</pre>

<p>This works great, but now we have some code duplication between the LegacyController and the bootstrap file. To get rid of the duplication, we can add an additional route that forwards requests for php scripts to the LegacyController like this:</p>

<pre lang="php">
$front  = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$route  = new Zend_Controller_Router_Route_Regex(
    '(.+\.php)',
    array(
        'controller' => 'legacy',
        'action'     => 'index',
    ),
    array(
        1 => 'script'
    ),
    '%s'
);
$router->addRoute('legacy', $route);
</pre>

<p>This new route  allows us to remove the legacy script handling code from the bootstrap file and use the LegacyController for all legacy requests. One item to note is that this rule does NOT provide leading '/' to the value of 'script', which is why the LegacyController must use the <code>'/' . ltrim($script)</code> construct.</p>



	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts&amp;title=Migrating%20to%20Zend%20Framework%3A%20Legacy%20Scripts&amp;bodytext=Migrating%20an%20existing%20PHP%20application%20to%20Zend%20Framework%20can%20be%20a%20daunting%20task%2C%20especially%20if%20the%20migration%20must%20occur%20all%20at%20once.%20It%20is%20much%20easier%20to%20migrate%20the%20application%20in%20sections%20over%20a%20longer%20period%20of%20time.%20The%20approach%20outlined%20here%20allows%20developers%20to%20slowly%20integrate%20Zend%20Framework%20with%20an%20existing%20site%20while%20still%20serving%20legacy%20scripts%20without%20rewriting%20them%20as%20MVC%20components." title="Digg"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts&amp;title=Migrating%20to%20Zend%20Framework%3A%20Legacy%20Scripts" title="StumbleUpon"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://sphinn.com/index.php?c=post&amp;m=submit&amp;link=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts" title="Sphinn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/sphinn.png" title="Sphinn" alt="Sphinn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts&amp;title=Migrating%20to%20Zend%20Framework%3A%20Legacy%20Scripts&amp;notes=Migrating%20an%20existing%20PHP%20application%20to%20Zend%20Framework%20can%20be%20a%20daunting%20task%2C%20especially%20if%20the%20migration%20must%20occur%20all%20at%20once.%20It%20is%20much%20easier%20to%20migrate%20the%20application%20in%20sections%20over%20a%20longer%20period%20of%20time.%20The%20approach%20outlined%20here%20allows%20developers%20to%20slowly%20integrate%20Zend%20Framework%20with%20an%20existing%20site%20while%20still%20serving%20legacy%20scripts%20without%20rewriting%20them%20as%20MVC%20components." title="del.icio.us"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts&amp;title=Migrating%20to%20Zend%20Framework%3A%20Legacy%20Scripts&amp;source=Chris+Abernethy+.+com+&amp;summary=Migrating%20an%20existing%20PHP%20application%20to%20Zend%20Framework%20can%20be%20a%20daunting%20task%2C%20especially%20if%20the%20migration%20must%20occur%20all%20at%20once.%20It%20is%20much%20easier%20to%20migrate%20the%20application%20in%20sections%20over%20a%20longer%20period%20of%20time.%20The%20approach%20outlined%20here%20allows%20developers%20to%20slowly%20integrate%20Zend%20Framework%20with%20an%20existing%20site%20while%20still%20serving%20legacy%20scripts%20without%20rewriting%20them%20as%20MVC%20components." title="LinkedIn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend-framework-legacy-scripts%252F%26amp%3Bseed_title%3DMigrating%2Bto%2BZend%2BFramework%253A%2BLegacy%2BScripts&amp;t=Migrating%20to%20Zend%20Framework%3A%20Legacy%20Scripts" title="Facebook"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="" title="TwitThis"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/" title="TwitThis" alt="TwitThis" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend-framework-legacy-scripts%2F&amp;seed_title=Migrating+to+Zend+Framework%3A+Legacy+Scripts/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Using Module Templates with Zend Framework</title>
		<link>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend_framework_templates%2F&amp;seed_title=Using+Module+Templates+with+Zend+Framework</link>
		<comments>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend_framework_templates%2F&amp;seed_title=Using+Module+Templates+with+Zend+Framework#comments</comments>
		<pubDate>Fri, 30 Nov 2007 20:45:34 +0000</pubDate>
		<dc:creator>Brownoxford</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.chrisabernethy.com/2007/11/30/zend_framework_templates/</guid>
		<description><![CDATA[I've just finished watching some of the archived webinars related to Zend Framework over at <a href="http://www.zend.com/en/resources/webinars/framework">Zend.com</a>, and found some great information about rendering view output into a sitewide template in the <em>MVC applications with Zend Framework</em> webinar. This article extends the examples provided in the webinar to allow specifying per-module templates.]]></description>
			<content:encoded><![CDATA[<p>
I've just finished watching some of the archived webinars related to Zend Framework over at <a href="http://www.zend.com/en/resources/webinars/framework" rel="nofollow" >Zend.com</a>, and found some great information about rendering view output into a sitewide template in the <em>MVC applications with Zend Framework</em> webinar.
</p>

<p>
Since I'm currently developing a website with multiple modules, each having their own distinct look, I'd like to extend the examples provided in the webinar to allow specifying per-module templates. Here is what I came up with:
</p>
<span id="more-23"></span>
<p>First, modify the example to add private member variables <code>$_template</code> and <code>$_module</code> and add a constructor that accepts and stores values for these variables.

<pre lang="php" line="1">
class My_Plugin_RenderIntoTemplate extends Zend_Controller_Plugin_Abstract
{
  private $_template = null;
  private $_module   = null;
	
  public function __construct( $template, $module = 'default' )
  {
    $this->_template = $template;
    $this->_module   = $module;
  }
</pre>

<p>Next, modify the <code>dispatchLoopShutdown()</code> method in the example to add a check that returns immediately if the current module is not the module specified at instantiation time.</p>

<pre lang="php" line="11">
  public function dispatchLoopShutdown()
  {

    if( $this->_module != $this->getRequest()->module ) {
      return;
    }

    $view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;
    if (empty($view)) {
      return;
    }

    $response      = $this->getResponse();
    $content       = $response->getBody();
    $view->content = $content;

    $response->setBody($view->render($this->_template));
  }
}
</pre>

Finally, register instances of the plugin with the front controller in the bootstrap code:

<pre lang="php" line="1">
// Set up the Front controller.
require_once 'Zend/Controller/Front.php';
$front = Zend_Controller_Front::getInstance( );

$front->addModuleDirectory( '../application/modules' )
      ->registerPlugin( new My_Plugin_RenderIntoTemplate( 'foo-template.phtml', 'foo' ) )
      ->dispatch( );
</pre>

In my example, I am using the conventional modular directory structure as outline <a href="http://framework.zend.com/manual/en/zend.controller.modular.html" rel="nofollow" >here</a>. In this case, the script named in the plugin constructor should be located at the <code>application/modules/foo/views/scripts/foo-template.phtml.</code>



	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework&amp;title=Using%20Module%20Templates%20with%20Zend%20Framework&amp;bodytext=I%27ve%20just%20finished%20watching%20some%20of%20the%20archived%20webinars%20related%20to%20Zend%20Framework%20over%20at%20Zend.com%2C%20and%20found%20some%20great%20information%20about%20rendering%20view%20output%20into%20a%20sitewide%20template%20in%20the%20MVC%20applications%20with%20Zend%20Framework%20webinar.%20This%20article%20extends%20the%20examples%20provided%20in%20the%20webinar%20to%20allow%20specifying%20per-module%20templates." title="Digg"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework&amp;title=Using%20Module%20Templates%20with%20Zend%20Framework" title="StumbleUpon"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://sphinn.com/index.php?c=post&amp;m=submit&amp;link=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework" title="Sphinn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/sphinn.png" title="Sphinn" alt="Sphinn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework&amp;title=Using%20Module%20Templates%20with%20Zend%20Framework&amp;notes=I%27ve%20just%20finished%20watching%20some%20of%20the%20archived%20webinars%20related%20to%20Zend%20Framework%20over%20at%20Zend.com%2C%20and%20found%20some%20great%20information%20about%20rendering%20view%20output%20into%20a%20sitewide%20template%20in%20the%20MVC%20applications%20with%20Zend%20Framework%20webinar.%20This%20article%20extends%20the%20examples%20provided%20in%20the%20webinar%20to%20allow%20specifying%20per-module%20templates." title="del.icio.us"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework&amp;title=Using%20Module%20Templates%20with%20Zend%20Framework&amp;source=Chris+Abernethy+.+com+&amp;summary=I%27ve%20just%20finished%20watching%20some%20of%20the%20archived%20webinars%20related%20to%20Zend%20Framework%20over%20at%20Zend.com%2C%20and%20found%20some%20great%20information%20about%20rendering%20view%20output%20into%20a%20sitewide%20template%20in%20the%20MVC%20applications%20with%20Zend%20Framework%20webinar.%20This%20article%20extends%20the%20examples%20provided%20in%20the%20webinar%20to%20allow%20specifying%20per-module%20templates." title="LinkedIn"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.chrisabernethy.com%2Ffeeder%2F%3FFeederAction%3Dclicked%26amp%3Bfeed%3DArticles%2B%2528RSS2%2529%26amp%3Bseed%3Dhttp%253A%252F%252Fwww.chrisabernethy.com%252Fzend_framework_templates%252F%26amp%3Bseed_title%3DUsing%2BModule%2BTemplates%2Bwith%2BZend%2BFramework&amp;t=Using%20Module%20Templates%20with%20Zend%20Framework" title="Facebook"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="" title="TwitThis"><img src="http://www.chrisabernethy.com/wp-content/plugins/sociable/images/" title="TwitThis" alt="TwitThis" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://www.chrisabernethy.com/feeder/?FeederAction=clicked&amp;feed=Articles+%28RSS2%29&amp;seed=http%3A%2F%2Fwww.chrisabernethy.com%2Fzend_framework_templates%2F&amp;seed_title=Using+Module+Templates+with+Zend+Framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
