<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Blog entries tagged microphp :: mwop.net</title>
  <updated>2012-08-17T11:00:00-05:00</updated>
  <generator uri="https://getlaminas.org" version="2">Laminas_Feed_Writer</generator>
  <link rel="alternate" type="text/html" href="https://mwop.net/blog/tag/microphp"/>
  <link rel="self" type="application/atom+xml" href="https://mwop.net/blog/tag/microphp/atom.xml"/>
  <id>https://mwop.net/blog/tag/microphp</id>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[On Microframeworks]]></title>
    <published>2012-08-17T11:00:00-05:00</published>
    <updated>2012-08-17T11:00:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2012-08-17-on-microframeworks.html"/>
    <id>https://mwop.net/blog/2012-08-17-on-microframeworks.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>A number of months ago, <xhtml:a href="http://funkatron.com/">Ed
Finkler</xhtml:a> started a discussion in the PHP community about
<xhtml:a href="http://microphp.org/">"MicroPHP"</xhtml:a>; to summarize, the
movement is about:</xhtml:p>
<xhtml:ul>
<xhtml:li>Building small, single-purpose libraries.</xhtml:li>
<xhtml:li>Using small things that work together to solve larger
problems.</xhtml:li>
</xhtml:ul>
<xhtml:p>I think there are some really good ideas that have come out of
this, and also a number of questionable practices<xhtml:sup id="t1"><xhtml:a href="#f1">1</xhtml:a></xhtml:sup>.</xhtml:p>
<xhtml:p>One piece in particular I've focussed on is the concept of
so-called “microframeworks”.</xhtml:p>
<xhtml:h2>What is a microframework?</xhtml:h2>
<xhtml:p>PHP has had microframeworks for quite some time<xhtml:sup id="t2"><xhtml:a href="#f2">2</xhtml:a></xhtml:sup>, though I only really first saw the
term being used around 3 years ago. The “grand-daddy” of modern-day
microframeworks can actually be traced to Ruby, however, and
specifically <xhtml:a href="http://www.sinatrarb.com">Sinatra</xhtml:a>.</xhtml:p>
<xhtml:p>Sinatra is not so much a framework as it is a domain-specific
language (DSL). The language and structure it created, however,
have been re-created in the vast majority of microframeworks you
see currently in the PHP arena. Specifically, it describes how to
map HTTP request methods and paths to the code that will handle
them. It borrowed route matching ideas from <xhtml:a href="http://rubyonrails.org/">Ruby on Rails</xhtml:a>, and relied on the fact
that Ruby uses the last value of a block as the return value.</xhtml:p>
<xhtml:p>As some simple examples:</xhtml:p>
<xhtml:pre><xhtml:code class="language-ruby hljs ruby" data-lang="ruby">get <xhtml:span class="hljs-string">'/hello/:name'</xhtml:span> <xhtml:span class="hljs-keyword">do</xhtml:span> <xhtml:span class="hljs-params">|n|</xhtml:span>
    <xhtml:span class="hljs-string">"Hello <xhtml:span class="hljs-subst">#{n}</xhtml:span>!"</xhtml:span>
<xhtml:span class="hljs-keyword">end</xhtml:span>

post <xhtml:span class="hljs-string">'/address'</xhtml:span>
    <xhtml:span class="hljs-comment"># create address</xhtml:span>
<xhtml:span class="hljs-keyword">end</xhtml:span>

put <xhtml:span class="hljs-string">'/address/:id'</xhtml:span> <xhtml:span class="hljs-params">|i|</xhtml:span>
    <xhtml:span class="hljs-comment"># update address</xhtml:span>
<xhtml:span class="hljs-keyword">end</xhtml:span>

get <xhtml:span class="hljs-string">'/feed.?:format?'</xhtml:span>, <xhtml:span class="hljs-symbol">:provides</xhtml:span> =&gt; [<xhtml:span class="hljs-string">'rss'</xhtml:span>, <xhtml:span class="hljs-string">'atom'</xhtml:span>, <xhtml:span class="hljs-string">'xml'</xhtml:span>] <xhtml:span class="hljs-keyword">do</xhtml:span>
    builder <xhtml:span class="hljs-symbol">:feed</xhtml:span>
<xhtml:span class="hljs-keyword">end</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>The language is expressive, and allows the developer to focus on
two things:</xhtml:p>
<xhtml:ul>
<xhtml:li>What are the specific entry points (URIs) for the
application?</xhtml:li>
<xhtml:li>What needs to be done for each specific entry point?</xhtml:li>
</xhtml:ul>
<xhtml:p>I'd argue that the above two points are the defining
characteristics of modern microframeworks. Typically, the entry
points are given the term "routing", and the second corresponds to
"controllers".</xhtml:p>
<xhtml:h2>PHP implementations</xhtml:h2>
<xhtml:p>I'd argue one of the earliest microframework implementations,
though it wasn't termed as such, was <xhtml:a href="http://dev.horde.org/routes/">Horde Routes</xhtml:a><xhtml:sup id="t3"><xhtml:a href="#f3">3</xhtml:a></xhtml:sup> (which was itself inspired by
<xhtml:a href="http://routes.readthedocs.org/en/latest/index.html">Python
Routes</xhtml:a>, in turn inspired by the Rails routing system, like
Sinatra). It follows the two principles I outlined above: it allows
defining routes (entry points), and mapping them to controllers.
Controllers for Routes are simply classes, and a route must provide
both a controller and an action in the match, with the latter
corresponding to a method on the controller class.</xhtml:p>
<xhtml:p>Since around 2009, I've seen an increasing number of new PHP
microframeworks<xhtml:sup id="t4"><xhtml:a href="#f4">4</xhtml:a></xhtml:sup> that follow
in the steps of Sinatra and Horde. In the various implementations
I've looked at, instead of using a DSL, the authors have all opted
for either a procedural or OOP interface. Starting with PHP 5.3,
most authors have also primarily targetted any PHP callable as a
controller, favoring callbacks specifically. The fundamental ideas
remain the same as Sinatra, however:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-comment">/* Procedural */</xhtml:span>
get(<xhtml:span class="hljs-string">'/hello/:name'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($n)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-string">"Hello {$n}!"</xhtml:span>;
});

post(<xhtml:span class="hljs-string">'/address'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">()</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-comment">// create address</xhtml:span>
});

put(<xhtml:span class="hljs-string">'/address/:id'</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($i)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-comment">// update address</xhtml:span>
});

get(<xhtml:span class="hljs-string">'/feed.?:format?'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span><xhtml:span class="hljs-params">($feed, $format)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-keyword">return</xhtml:span> builder($feed, $format);
});

<xhtml:span class="hljs-comment">/* OOP */</xhtml:span>
$app-&gt;get(<xhtml:span class="hljs-string">'/hello/:name'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($n)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-string">"Hello {$n}!"</xhtml:span>;
});

$app-&gt;post(<xhtml:span class="hljs-string">'/address'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">()</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-comment">// create address</xhtml:span>
});
end

$app-&gt;put(<xhtml:span class="hljs-string">'/address/:id'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($i)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-comment">// update address</xhtml:span>
});

$app-&gt;get(<xhtml:span class="hljs-string">'/feed.?:format?'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($feed, $format)</xhtml:span> <xhtml:span class="hljs-title">use</xhtml:span> <xhtml:span class="hljs-params">($app)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-keyword">return</xhtml:span> $app-&gt;builder($feed, $format);
})-&gt;constraints([<xhtml:span class="hljs-string">'format'</xhtml:span> =&gt; <xhtml:span class="hljs-string">'/^(rss|atom|xml)$/'</xhtml:span>]);
</xhtml:code></xhtml:pre>
<xhtml:p>One key difference I've witnessed in the implementations is
surrounding how route matches are passed to the callback. In the
examples above, they are passed as individual arguments to the
handler. Some, however, opt for an approach more like Sinatra,
which passes a single "params" argument into the scope of the
handler. This approach tends to be more expedient both from an
implementation standpoint as well as a performance standpoint, as
it does not require reflection to determine name and position of
arguments, and makes handling wildcard arguments simpler. I've seen
this latter approach handled several ways:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-comment">// Pass in route match parameters as an argument.</xhtml:span>
$app-&gt;get(<xhtml:span class="hljs-string">'/feed.:format'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($params)</xhtml:span> </xhtml:span>{
    $format = $params[<xhtml:span class="hljs-string">'format'</xhtml:span>];
});

<xhtml:span class="hljs-comment">// Pass in the $app instance, and retrieve route </xhtml:span>
<xhtml:span class="hljs-comment">// match parameters from it.</xhtml:span>
$app-&gt;get(<xhtml:span class="hljs-string">'/feed.:format'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($app)</xhtml:span> </xhtml:span>{
    $format = $app-&gt;params(<xhtml:span class="hljs-string">'format'</xhtml:span>);
});

<xhtml:span class="hljs-comment">// Curry in the $app instance when desired, and </xhtml:span>
<xhtml:span class="hljs-comment">// retrieve route match parameters from it.</xhtml:span>
$app-&gt;get(<xhtml:span class="hljs-string">'/feed.:format'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">()</xhtml:span> <xhtml:span class="hljs-title">use</xhtml:span> <xhtml:span class="hljs-params">($app)</xhtml:span> </xhtml:span>{
    $format = $app-&gt;params(<xhtml:span class="hljs-string">'format'</xhtml:span>);
});
</xhtml:code></xhtml:pre>
<xhtml:p>Another difference I've seen is in how route constraints,
defaults, and names are handled. The most elegant solutions usually
allow chaining method calls in order to alter this data:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$app-&gt;get(<xhtml:span class="hljs-string">'/feed.:format'</xhtml:span>, <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-params">($app)</xhtml:span> </xhtml:span>{
    <xhtml:span class="hljs-comment">// ...</xhtml:span>
})-&gt;constraints([<xhtml:span class="hljs-string">'format'</xhtml:span> =&gt; <xhtml:span class="hljs-string">'/^(atom|xml|json)$/'</xhtml:span>])
  -&gt;name(<xhtml:span class="hljs-string">'feed'</xhtml:span>);
</xhtml:code></xhtml:pre>
<xhtml:p>One common feature I've seen is the ability to generate URLs
based on the defined routes. Most commonly, this is a function or
method <xhtml:code>urlTo()</xhtml:code>, which takes a route name, and an
associative array of replacements.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-keyword">echo</xhtml:span> $app-&gt;urlTo(<xhtml:span class="hljs-string">'feed'</xhtml:span>, [<xhtml:span class="hljs-string">'format'</xhtml:span> =&gt; <xhtml:span class="hljs-string">'atom'</xhtml:span>]);
</xhtml:code></xhtml:pre>
<xhtml:p>That's it in a nutshell: the ability to match HTTP request
methods and path information, and map it to controllers/handlers,
and to generate URLs based on those present in the application.</xhtml:p>
<xhtml:h2>What are they good for?</xhtml:h2>
<xhtml:p>In my research and experience, microframeworks have three
typical use cases:</xhtml:p>
<xhtml:ol>
<xhtml:li><xhtml:strong>Prototyping.</xhtml:strong> Because of their simplicity,
microframeworks are fantastic for prototyping a basic website. Very
often, in the early stages of a site, you have a limited number of
pages, and most often simply need to render a template with limited
variable substitutions. Microframeworks are a perfect fit for
this.</xhtml:li>
<xhtml:li><xhtml:strong>APIs</xhtml:strong>. API needs are usually quite
well-defined, and often involve a small, finite number of URLs. The
logic required is usually already encapsulated in business objects,
so the application layer is simply for filtering and returning a
representation. Microframeworks again offer a nice fit.</xhtml:li>
<xhtml:li><xhtml:strong>Small, mostly static sites</xhtml:strong>. Similar to the
first point, if you know the site will be relatively small and
mostly static, then the minimal overhead of a microframework is
often a good fit.</xhtml:li>
</xhtml:ol>
<xhtml:h2>Where do microframeworks fail?</xhtml:h2>
<xhtml:p>Because of the rather declarative nature of microframeworks, and
the typically 1:1 mapping of a route to a controller,
microframeworks do not tend to promote code re-use. Additionally,
this extends to how microframework applications are organized:
usually, there are no clear guidelines on how to organize routes
and controllers, much less separate them into multiple files. This
can lead to maintenance issues as the application grows, as well as
logistical issues whenever you need to add new routes and
controllers (do they go at the top, or bottom? are there other
routes that could potentially match as well? etc.).</xhtml:p>
<xhtml:p>Additionally, though many frameworks offer ways to alter the
workflow of the application either via hooks, events, or
“middleware”<xhtml:sup id="t5"><xhtml:a href="#f5">5</xhtml:a></xhtml:sup>, most of these
are limited in scope, often non-reusable, and often non-stackable.
As such, comprehensive manipulation of the application workflow is
out of reach.</xhtml:p>
<xhtml:p>One other area that is overlooked, however, is one I find
curious, particularly in light of the MicroPHP movement: so much of
the underlying plumbing is basically the same, yet every
microframework re-implements it. Specifically:</xhtml:p>
<xhtml:ul>
<xhtml:li>Routing is basically the same across most implementations,
following the same basic specifications outlined in Rails. There
are very few differences in the public APIs.</xhtml:li>
<xhtml:li>Request and Response object abstraction is largely the same as
well, providing access to query/post/cookie/session/etc. parameters
through roughly equivalent APIs.</xhtml:li>
<xhtml:li>Many implement their own view layers.<xhtml:sup id="t6"><xhtml:a href="#f6">6</xhtml:a></xhtml:sup></xhtml:li>
</xhtml:ul>
<xhtml:p>Most of this code should be considered commodity code at this
point. There are several outstanding view layers and templating
engines available (Smarty, Twig, Savant, <xhtml:code>Zend\View</xhtml:code>).
Standalone routing libraries exist such as Horde Routes, and even
those bundled with frameworks are often available separately via
Composer or Pyrus; the same is true with Request and Response
object abstraction. It seems to me that a few microframework
authors should be working on abstracting these concerns, and then
focussing their efforts on differentiators in their own
microframeworks.</xhtml:p>
<xhtml:h2>An experiment</xhtml:h2>
<xhtml:p>Building on my last point, I looked at the APIs of <xhtml:a href="http://limonade-php.github.com/">Limonade</xhtml:a> and <xhtml:a href="http://www.slimframework.com/">Slim Framework</xhtml:a>, and built up a
specification for a microframework. I then matched as many pieces
of it as possible to existing components in <xhtml:a href="http://packages.zendframework.com/">ZF2</xhtml:a>, and started
building.</xhtml:p>
<xhtml:p>In a matter of a few hours, I had written up a complete test
suite<xhtml:sup id="t7"><xhtml:a href="#f7">7</xhtml:a></xhtml:sup> and all code for a
microframework, featuring the following (this is basically the
testdox output from the unit test suite):</xhtml:p>
<xhtml:ul>
<xhtml:li>Lazy loads request</xhtml:li>
<xhtml:li>Lazy loads response</xhtml:li>
<xhtml:li>Request is injectible</xhtml:li>
<xhtml:li>Response is injectible</xhtml:li>
<xhtml:li>Halt should raise halt exception</xhtml:li>
<xhtml:li>Response should contain status provided to halt</xhtml:li>
<xhtml:li>Response should contain message provided to halt</xhtml:li>
<xhtml:li>Stop should raise halt exception</xhtml:li>
<xhtml:li>Response should remain unaltered after stop</xhtml:li>
<xhtml:li>Redirect should raise halt exception</xhtml:li>
<xhtml:li>Redirect should set 302 response status by default</xhtml:li>
<xhtml:li>Redirect should set response status based on provided status
code</xhtml:li>
<xhtml:li>Redirect should set location header</xhtml:li>
<xhtml:li>Map creates a segment route when provided with a string
route</xhtml:li>
<xhtml:li>Map can receive a route object</xhtml:li>
<xhtml:li>Passing invalid route raises exception</xhtml:li>
<xhtml:li>Map can receive a callable</xhtml:li>
<xhtml:li>Passing invalid controller to route does not immediately raise
exception</xhtml:li>
<xhtml:li>Accessing invalid controller raises exception</xhtml:li>
<xhtml:li>Passing invalid method to route via method raises
exception</xhtml:li>
<xhtml:li>Can set methods route responds to singly</xhtml:li>
<xhtml:li>Can set methods route responds to as array</xhtml:li>
<xhtml:li>Can set methods route responds to as multiple arguments</xhtml:li>
<xhtml:li>Can specify additional method types to respond to</xhtml:li>
<xhtml:li>Can specify route name</xhtml:li>
<xhtml:li>Adding route using method type creates route that responds to
that method type</xhtml:li>
<xhtml:li>Running with no matching routes raises page not found
exception</xhtml:li>
<xhtml:li>Routing sets list of named routes</xhtml:li>
<xhtml:li>Routing sets lists of routes by method</xhtml:li>
<xhtml:li>Successful routing dispatches controller</xhtml:li>
<xhtml:li>Unsuccessful routing triggers 404 event</xhtml:li>
<xhtml:li>Calling halt triggers halt event</xhtml:li>
<xhtml:li>Invalid controller triggers 501 event</xhtml:li>
<xhtml:li>Exception raised in controller triggers 500 event</xhtml:li>
<xhtml:li>Can pass to next matching route</xhtml:li>
<xhtml:li>Url for helper assembles url based on name provided</xhtml:li>
<xhtml:li>Url for helper assembles url based on name and params
provided</xhtml:li>
<xhtml:li>Url for helper assembles url based on current route match when
no name provided</xhtml:li>
<xhtml:li>Composes logger instance by default</xhtml:li>
<xhtml:li>Can inject specific logger instance</xhtml:li>
<xhtml:li>Mustache view is used by default</xhtml:li>
<xhtml:li>Can inject alternate view instance</xhtml:li>
<xhtml:li>Render renders a template to the response</xhtml:li>
<xhtml:li>View model returns mustache view model by default</xhtml:li>
<xhtml:li>Subsequent calls to view model return separate instances</xhtml:li>
<xhtml:li>Can provide view model prototype</xhtml:li>
</xhtml:ul>
<xhtml:p>I utilized ZF2's routing library from its MVC component, the
request and response objects from its HTTP component, its Log
component, and the Session component. These had a few other
dependencies, but nothing terribly onerous.</xhtml:p>
<xhtml:p>For the view, I used my own <xhtml:a href="http://weierophinney.github.com/phly_mustache">phly_mustache</xhtml:a>,
and provided a basic "view model" implementation that receives the
application instance, thus allowing the ability to call application
helpers (such as url generation).</xhtml:p>
<xhtml:p>To make installation simple, I used <xhtml:a href="http://getcomposer.org">Composer</xhtml:a> to manage my dependencies on
specific ZF2 components and for <xhtml:code>phly_mustache</xhtml:code>. The
microframework contains only the code it needs to get its work
done, leveraging the work of others whenever possible.</xhtml:p>
<xhtml:p>This post is not meant as a way to announce a new
microframework, however.<xhtml:sup id="t8"><xhtml:a href="#f8">8</xhtml:a></xhtml:sup> The
point of the experiment was to prove something: microframeworks are
trivially easy to write, <xhtml:em>particularly if you follow the
principals of MicroPHP, and re-use existing code</xhtml:em>. Just because
code comes from a framework or a third-party library does not make
it suspect or inferior; in fact, whenever possible, you should
leverage such code so you can focus on <xhtml:em>writing awesome
applications</xhtml:em>.</xhtml:p>
<xhtml:h2>Lessons learned</xhtml:h2>
<xhtml:p>I really like microframeworks for specific problems:
prototyping, APIs, and small, simple sites. I think they are
ideally suited for these tasks. That said, I'd love to see some
solid libraries targetting the fundamental, shared aspects of these
efforts: routing, request and response abstraction, etc. With
dependency management tools such as Composer and Pyrus, having
required dependencies is not a big deal anymore, and re-use should
be encouraged.</xhtml:p>
<xhtml:p>Also, writing a microframework is an excellent coding exercise.
It helps a developer appreciate the complexities of abstraction
while limiting the number of moving parts. I highly recommend it as
an exercise — but do it using available components, and be prepared
to throw it away and instead collaborate with others, or adopt
something which better solves both the problems you have and the
problems you anticipate.</xhtml:p>
<xhtml:p>In sum: <xhtml:em>Use the right tool for the job</xhtml:em>. If you foresee
expanding requirements in your project's future, you may want to
evaluate a full-stack framework,<xhtml:sup id="t9"><xhtml:a href="#f9">9</xhtml:a></xhtml:sup> or consider building something robust that suits
your specific project's needs. Use microframeworks where and when
they make sense.</xhtml:p>
<xhtml:h4>Afterword</xhtml:h4>
<xhtml:p>I'm well aware that Fabien Potencier has written <xhtml:a href="http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1">
a comprehensive series of posts on creating a microframework using
Symfony 2 components</xhtml:a>. I deliberately chose not to read them
until (a) ZF2 was almost ready to release, and (b) I'd had a chance
to formulate my own opinions on microframeworks. They're an
excellent read, however, and show a nice progression of development
from flat PHP to a fully functional microframework; click the link
and see for yourself.</xhtml:p>
<xhtml:h4>Footnotes</xhtml:h4>
<xhtml:ul>
<xhtml:li><xhtml:sup id="f1"><xhtml:a href="#t1">1</xhtml:a></xhtml:sup> In particular, I feel
that the movement (a) disparages components from larger libraries
simply because they originate from a larger library, and (b)
distrust any code that has additional dependencies. This latter I
find truly puzzling, as I'd think it fits the idea of “use small
things that work together to solve larger problems.” If the code
solves a particular problem and allows you to focus on a larger
problem, where it originates and the number of dependencies should
not be an issue.</xhtml:li>
<xhtml:li><xhtml:sup id="f2"><xhtml:a href="#t2">2</xhtml:a></xhtml:sup> In fact, my first foray
into MVC in PHP was writing a clone of Perl's <xhtml:a href="http://cgi-app.org/">CGI::Application</xhtml:a>, which in many ways is
also a microframework.</xhtml:li>
<xhtml:li><xhtml:sup id="f3"><xhtml:a href="#t3">3</xhtml:a></xhtml:sup> Trivia: Both authors of
Horde Routes worked at Zend when I first started at the company,
and Mike Naberezny wrote the very first lines of code for Zend
Framework.</xhtml:li>
<xhtml:li><xhtml:sup id="f4"><xhtml:a href="#t4">4</xhtml:a></xhtml:sup> I swear, you see new
ones on Github daily, and on <xhtml:a href="http://phpdeveloper.org/">PHP
Developer</xhtml:a> at least once a week.</xhtml:li>
<xhtml:li><xhtml:sup id="f5"><xhtml:a href="#t5">5</xhtml:a></xhtml:sup> <xhtml:a href="http://www.slimframework.com">Slim</xhtml:a> has this concept.
Basically, any callables placed between the route string and the
last callable when defining a route — i.e., the “middle” arguments,
and thus middleware — will be executed in order prior to attempting
to execute the controller.</xhtml:li>
<xhtml:li><xhtml:sup id="f6"><xhtml:a href="#t6">6</xhtml:a></xhtml:sup> <xhtml:a href="http://www.slimframework.com">Slim</xhtml:a> is an outlier here, as it
utilizes <xhtml:a href="http://twig.sensiolabs.org/">Twig</xhtml:a> by
default.</xhtml:li>
<xhtml:li><xhtml:sup id="f7"><xhtml:a href="#t7">7</xhtml:a></xhtml:sup> I'm sure that my TDD
experiment will warm the soul of <xhtml:a href="http://www.littlehart.net/atthekeyboard/">the Grumpy
Programmer</xhtml:a>.</xhtml:li>
<xhtml:li><xhtml:sup id="f8"><xhtml:a href="#t8">8</xhtml:a></xhtml:sup> That said, if you want
to look at the results, you can <xhtml:a href="http://github.com/weierophinney/phlyty">find Phlyty on
Github</xhtml:a>.</xhtml:li>
<xhtml:li><xhtml:sup id="f9"><xhtml:a href="#t9">9</xhtml:a></xhtml:sup> As you may guess, I'm
biased towards <xhtml:a href="http://framework.zend.com/">Zend
Framework</xhtml:a>. However, you should always carefully evaluate a
framework against your project's needs.</xhtml:li>
</xhtml:ul>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-08-17-on-microframeworks.html">On
Microframeworks</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2012-08-17T11:00:00-05:00">17 August
2012</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
</feed>
