<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <title>Blog entries tagged zf2 :: mwop.net</title>
    <description>Blog entries tagged zf2 :: mwop.net</description>
    <pubDate>Wed, 26 Mar 2014 15:30:00 -0500</pubDate>
    <generator>Laminas_Feed_Writer 2 (https://getlaminas.org)</generator>
    <link>https://mwop.net/blog/tag/zf2</link>
    <atom:link rel="self" type="application/rss+xml" href="https://mwop.net/blog/tag/zf2/rss.xml"/>
    <item>
      <title>Apigility: Using RPC with HAL</title>
      <pubDate>Wed, 26 Mar 2014 15:30:00 -0500</pubDate>
      <link>https://mwop.net/blog/2014-03-26-apigility-rpc-with-hal.html</link>
      <guid>https://mwop.net/blog/2014-03-26-apigility-rpc-with-hal.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>A few days ago, we <a href="http://bit.ly/ag-1-beta1">released our first beta of Apigility</a>.
We've started our documentation effort now, and one question has arisen a few
times that I want to address: How can you use Hypermedia Application Language
(HAL) in RPC services?</p>


<h2>HAL?</h2>
<p><a href="http://tools.ietf.org/html/draft-kelly-json-hal-06">Hypermedia Application Language</a>
is an IETF proposal for how to represent resources and their relations within
APIs.  Technically, it provides two mediatypes, <code>application/hal+json</code> and
<code>application/hal+xml</code>; however, Apigility only provides the JSON variant.</p>
<p>The important things to know about HAL are:</p>
<ul>
<li>
<p>It provides a standard way of describing relational links. All relational
links are under a <code>_links</code> property of the resource. That property is an
object. Each property of that object is a link relation; the value of each
link relation is an object (or array of such objects) describing the link
that must minimally contain an <code>href</code> proerty. The link object itself can
contain some additional metadata, such as a mediatype, a name (useful for
differentiating between multiple link objects assigned to the same relation).</p>
<p>While not required, the specification recommends resources contain a &quot;self&quot;
relational link, indicating the canonical location for the resource. This is
particularly useful when we consider embedding (the next topic).</p>
<p>Sound hard? It's not:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {
            <span class="hljs-string">"href"</span>: <span class="hljs-string">"/blog/2014-03-26-apigility-rpc-with-hal"</span>
        }
    }
}
</code></pre>
</li>
<li>
<p>Besides link relations, HAL also provides a standard way of describing
<em>embedded resources</em>. An embedded resource is any other resource you can
address via your API, and, as such, would be structured as a HAL resource —
in other words, it would have a <code>_links</code> property with relational links.
Essentially, any property of the resource you're returning that can itself be
addressed via the URI must be <em>embedded</em> in the resource. This is done via
the property <code>_embedded</code>.</p>
<p>Like <code>_links</code>, <code>_embedded</code> is an object. Each key in the object is the local
name by which the resource refers to the embedded resource. The value of such
keys can either be HAL resources or <em>arrays</em> of HAL resources; in fact, this
is how <em>collections</em> are represented in HAL!</p>
<p>As examples:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {
            <span class="hljs-string">"href"</span>: <span class="hljs-string">"/blog/2014-03-26-apigility-rpc-with-hal"</span>
        }
    },
    <span class="hljs-string">"_embedded"</span>: {
        <span class="hljs-string">"author"</span>: {
            <span class="hljs-string">"_links"</span>: {
                <span class="hljs-string">"self"</span>: {
                    <span class="hljs-string">"href"</span>: <span class="hljs-string">"/blog/author/matthew"</span>
                }
            },
            <span class="hljs-string">"id"</span>: <span class="hljs-string">"matthew"</span>,
            <span class="hljs-string">"name"</span>: <span class="hljs-string">"Matthew Weier O'Phinney"</span>,
            <span class="hljs-string">"url"</span>: <span class="hljs-string">"http://mwop.net"</span>
        },
        <span class="hljs-string">"tags"</span>: [
            {
                <span class="hljs-string">"_links"</span>: {
                    <span class="hljs-string">"self"</span>: {
                        <span class="hljs-string">"href"</span>: <span class="hljs-string">"/blog/tag/php"</span>
                    }
                },
                <span class="hljs-string">"id"</span>: <span class="hljs-string">"php"</span>
            },
            {
                <span class="hljs-string">"_links"</span>: {
                    <span class="hljs-string">"self"</span>: {
                        <span class="hljs-string">"href"</span>: <span class="hljs-string">"/blog/tag/rest"</span>
                    }
                },
                <span class="hljs-string">"id"</span>: <span class="hljs-string">"rest"</span>
            }
        ]
    }
}
</code></pre>
<p>The example above shows two embedded resources. The first is the author; the
second, a collection of tags. Note that <em>every</em> object under <code>_embedded</code> is a
HAL object!</p>
<p>You can go quite far with this — you can also have embedded resources inside
your embedded resources, arbitrarily deep.</p>
</li>
</ul>
<h2>RPC?</h2>
<p>RPC stands for Remote Procedure Call, and, when describing a web API, is
usually used to describe a web service that publishes multiple method calls at
a single URI using only <code>POST</code>; XML-RPC and SOAP are the usual suspects.</p>
<p>In Apigility, we use the term RPC in a much looser sense; we use it to describe
one-off services: actions like &quot;authenticate,&quot; or &quot;notify,&quot; or &quot;register&quot; would
all make sense here. They are actions that usually only need to respond to a
single HTTP method, and which may or may not describe a &quot;thing&quot;, which is what
we usually consider a &quot;resource&quot; when discussing REST terminology.</p>
<p>That said: what if what we want to return from the RPC call <em>are</em> REST
resources?</p>
<h2>Returning HAL from RPC Services</h2>
<p>In order to return HAL from RPC services, we need to understand (a) how Content
Negotiation works, and (b) what needs to be returned in order for the HAL
renderer to be able to create a representation.</p>
<p>For purposes of this example, I'm positing a <code>RegisterController</code> as an RPC
service that, on success, is returning a <code>User</code> object that I want rendered as
a HAL resource.</p>
<p>The <a href="https://github.com/zfcampus/zf-content-negotiation">zf-content-negotiation</a>
module takes care of content negotiation for Apigility. It introspects the
<code>Accept</code> header in order to determine if we can return a representation, and
then, if it can, will cast any <code>ZF\ContentNegotiation\ViewModel</code> returned from
a controller to the appropriate view model for the representation. From there,
a renderer will pick up the view model and do what needs to be done.</p>
<p>So, the first thing we have to do is return <code>ZF\ContentNegotiation\ViewModel</code>
instances from our controller.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractActionController</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">ZF</span>\<span class="hljs-title">ContentNegotiation</span>\<span class="hljs-title">ViewModel</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RegisterController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractActionController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">registerAction</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-comment">/* ... do some work ... get a user ... */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ViewModel(<span class="hljs-keyword">array</span>(<span class="hljs-string">'user'</span> =&gt; $user));
    }
}
</code></pre>
<p>The <a href="https://github.com/zfcampus/zf-hal">zf-hal</a> module in Apigility creates
the actual HAL representations. <code>zf-hal</code> looks for a &quot;payload&quot; variable in the
view model, and expects that value to be either a <code>ZF\Hal\Entity</code> (single item)
or <code>ZF\Hal\Collection</code>. When creating an <code>Entity</code> object, you need the object
being represented, as well as the identifier. So, let's update our return
value.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractActionController</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">ZF</span>\<span class="hljs-title">ContentNegotiation</span>\<span class="hljs-title">ViewModel</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">ZF</span>\<span class="hljs-title">Hal</span>\<span class="hljs-title">Entity</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RegisterController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractActionController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">registerAction</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-comment">/* ... do some work
         * ... get a $user
         * ... assume we have also now have an $id
         */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ViewModel(<span class="hljs-keyword">array</span>(<span class="hljs-string">'payload'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'user'</span> =&gt; <span class="hljs-keyword">new</span> Entity($user, $id),
        )));
    }
}
</code></pre>
<p><code>zf-hal</code> contains what's called a &quot;metadata map&quot;. This is a map of classes to
information on how <code>zf-hal</code> should render them: what route to use, what
additional relational links to inject, how to serialize the object, what field
represents the identifier, etc.</p>
<p>In most cases, you will have likely already defined a REST service for the
resource you want to return from the RPC service, in which case you will be
done. However, if you want, you can go in and manually configure the metadata
map in your API module's <code>config/module.config.php</code> file:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-comment">/* ... */</span>
    <span class="hljs-string">'zf-hal'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'metadata_map'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'User'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'route_name'</span> =&gt; <span class="hljs-string">'api.rest.user'</span>,
                <span class="hljs-string">'entity_identifier_name'</span> =&gt; <span class="hljs-string">'username'</span>,
                <span class="hljs-string">'route_identifier_name'</span> =&gt; <span class="hljs-string">'user_id'</span>,
                <span class="hljs-string">'hydrator'</span> =&gt; <span class="hljs-string">'Zend\Stdlib\Hydrator\ObjectProperty'</span>,
            ),
        ),
    ),
);
</code></pre>
<p>Finally, we need to make sure that the service is configured to actually return
HAL. We can do this in the admin if we want. Find the &quot;Content Negotiation&quot;
section of the admin, and the &quot;Content Negotiation Selector&quot; item, and set that
to &quot;HalJson&quot;; don't forget to save! Alternately, you can do this manually in
the API module's <code>config/module.config.php</code> file, under the
<code>zf-content-negotiation</code> section:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-comment">/* ... */</span>
    <span class="hljs-string">'zf-content-negotiation'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'controllers'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-comment">/* ... */</span>
            <span class="hljs-string">'RegisterController'</span> =&gt; <span class="hljs-string">'HalJson'</span>,
        ),
        <span class="hljs-comment">/* ... */</span>
    ),
);
</code></pre>
<p>Once your changes are complete, when you make a successful request to the URI
for your &quot;register&quot; RPC service, you'll receive a HAL response pointing to the
canonical URI for the user resource created!</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2014-03-26-apigility-rpc-with-hal.html">Apigility: Using RPC with HAL</a> was originally
    published <time class="dt-published" datetime="2014-03-26T15:30:00-05:00">26 March 2014</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>RESTful APIs with ZF2, Part 3</title>
      <pubDate>Mon, 25 Feb 2013 06:29:00 -0600</pubDate>
      <link>https://mwop.net/blog/2013-02-25-restful-apis-with-zf2-part-3.html</link>
      <guid>https://mwop.net/blog/2013-02-25-restful-apis-with-zf2-part-3.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>In my <a href="/blog/2013-02-11-restful-apis-with-zf2-part-1.html">previous</a>
<a href="/blog/2013-02-13-restful-apis-with-zf2-part-2.html">posts</a>, I covered basics
of JSON hypermedia APIs using Hypermedia Application Language (HAL), and
methods for reporting errors, including API-Problem and <code>vnd.error</code>.</p>
<p>In this post, I'll be covering <em>documenting</em> your API — techniques you can use
to indicate what HTTP operations are allowed, as well as convey the full
documentation on what endpoints are available, what they accept, and what you
can expect them to return.</p>
<p>While I will continue covering general aspects of RESTful APIs in this post, I
will also finally introduce several ZF2-specific techniques.</p>


<h2>Why Document?</h2>
<p>If you're asking this question, you've either never consumed software, or your
software is perfect and self-documenting. I frankly don't believe either one.</p>
<p>In the case of APIs, those consuming the API need to know how to use it.</p>
<ul>
<li>What endpoints are available? Which operations are available for each endpoint?</li>
<li>What does each endpoint expect as a payload during the request?</li>
<li>What can you expect as a payload in return?</li>
<li>How will errors be communicated?</li>
</ul>
<p>While the promise of hypermedia APIs is that each response tells you the next
steps available, you still, somewhere along the way, need more information —
what payloads look like, which HTTP verbs should be used, and more. If you're
<strong>not</strong> documenting your API, you're &quot;doing it wrong.&quot;</p>
<h2>Where Should Documentation Live?</h2>
<p>This is the much bigger question.</p>
<p>Of the questions I raised above, detailing what should be documented, there are
two specific types. When discussing what operations are available, we have a
technical solution in the form of the <code>OPTIONS</code> method and its counterpart, the
<code>Allow</code> header. Everything else falls under end-user documentation.</p>
<h2>OPTIONS</h2>
<p>The HTTP specification details the <code>OPTIONS</code> method as idempotent,
non-cacheable, and for use in detailing what operations are available for the
given resource specified by the request URI. It makes specific mention of the
<code>Allow</code> header, but does not limit what is returned for requests made via this
method.</p>
<p>The <code>Allow</code> header details the allowed HTTP methods for the given resource.</p>
<p>Used in combination, you make an <code>OPTIONS</code> request to a URI, and it should
return a response containing an <code>Allow</code> header; from that header value, you
then know what other HTTP methods can be made to that URI.</p>
<p>What this tells us is that our RESTful endpoint should do the following:</p>
<ul>
<li>When an <code>OPTIONS</code> request is made, return a response with an <code>Allow</code> header
that has a list of the available HTTP methods allowed.</li>
<li>For any HTTP method we do <em>not</em> allow, we should return a &quot;405 Not Allowed&quot;
response.</li>
</ul>
<p>These are fairly easy to accomplish in ZF2. <em>(See? I promised I'd get to some
ZF2 code in this post!)</em></p>
<p>When creating RESTful endpoints in ZF2, I recommend using
<code>Zend\Mvc\Controller\AbstractRestfulController</code>. This controller contains an
<code>options()</code> method which you can use to respond to an <code>OPTIONS</code> request. As
with any ZF2 controller, returning a response object will prevent rendering and
bubble out immediately so that the response is returned.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>\<span class="hljs-title">Controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractRestfulController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FooController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractRestfulController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">options</span><span class="hljs-params">()</span>
    </span>{
        $response = <span class="hljs-keyword">$this</span>-&gt;getResponse();
        $headers  = $response-&gt;getHeaders();

        <span class="hljs-comment">// If you want to vary based on whether this is a collection or an</span>
        <span class="hljs-comment">// individual item in that collection, check if an identifier from</span>
        <span class="hljs-comment">// the route is present</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;params()-&gt;fromRoute(<span class="hljs-string">'id'</span>, <span class="hljs-keyword">false</span>)) {
            <span class="hljs-comment">// Allow viewing, partial updating, replacement, and deletion</span>
            <span class="hljs-comment">// on individual items</span>
            $headers-&gt;addHeaderLine(<span class="hljs-string">'Allow'</span>, implode(<span class="hljs-string">','</span>, <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'GET'</span>,
                <span class="hljs-string">'PATCH'</span>,
                <span class="hljs-string">'PUT'</span>,
                <span class="hljs-string">'DELETE'</span>,
            )));
            <span class="hljs-keyword">return</span> $response;
        }

        <span class="hljs-comment">// Allow only retrieval and creation on collections</span>
        $headers-&gt;addHeaderLine(<span class="hljs-string">'Allow'</span>, implode(<span class="hljs-string">','</span>, <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'GET'</span>,
            <span class="hljs-string">'POST'</span>,
        )));
        <span class="hljs-keyword">return</span> $response;
    }
}
</code></pre>
<p>The next trick is returning the 405 response if an invalid option is used. For
this, you can create a listener in your controller, and wire it to listen at
higher-than-default priority. As an example:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>\<span class="hljs-title">Controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">EventManager</span>\<span class="hljs-title">EventManagerInterface</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractRestfulController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FooController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractRestfulController</span>
</span>{
    <span class="hljs-keyword">protected</span> $allowedCollectionMethods = <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'GET'</span>,
        <span class="hljs-string">'POST'</span>,
    );

    <span class="hljs-keyword">protected</span> $allowedResourceMethods = <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'GET'</span>,
        <span class="hljs-string">'PATCH'</span>,
        <span class="hljs-string">'PUT'</span>,
        <span class="hljs-string">'DELETE'</span>,
    );

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setEventManager</span><span class="hljs-params">(EventManagerInterface $events)</span>
    </span>{
        <span class="hljs-keyword">parent</span>::setEventManager($events);
        $events-&gt;attach(<span class="hljs-string">'dispatch'</span>, <span class="hljs-keyword">array</span>(<span class="hljs-keyword">$this</span>, <span class="hljs-string">'checkOptions'</span>), <span class="hljs-number">10</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkOptions</span><span class="hljs-params">($e)</span>
    </span>{
        $matches  = $e-&gt;getRouteMatch();
        $response = $e-&gt;getResponse();
        $request  = $e-&gt;getRequest();
        $method   = $request-&gt;getMethod();

        <span class="hljs-comment">// test if we matched an individual resource, and then test</span>
        <span class="hljs-comment">// if we allow the particular request method</span>
        <span class="hljs-keyword">if</span> ($matches-&gt;getParam(<span class="hljs-string">'id'</span>, <span class="hljs-keyword">false</span>)) {
            <span class="hljs-keyword">if</span> (!in_array($method, <span class="hljs-keyword">$this</span>-&gt;allowedResourceMethods)) {
                $response-&gt;setStatusCode(<span class="hljs-number">405</span>);
                <span class="hljs-keyword">return</span> $response;
            }
            <span class="hljs-keyword">return</span>;
        }

        <span class="hljs-comment">// We matched a collection; test if we allow the particular request </span>
        <span class="hljs-comment">// method</span>
        <span class="hljs-keyword">if</span> (!in_array($method, <span class="hljs-keyword">$this</span>-&gt;allowedCollectionMethods)) {
            $response-&gt;setStatusCode(<span class="hljs-number">405</span>);
            <span class="hljs-keyword">return</span> $response;
        }
    }
}
</code></pre>
<p>Note that I moved the allowed methods into properties; if I did the above, I'd
refactor the <code>options()</code> method to use those properties as well to ensure they
are kept in sync.</p>
<p>Also note that in the case of an invalid method, I return a response object.
This ensures that nothing else needs to execute in the controller; I discover
the problem and return early.</p>
<h2>End-User Documentation</h2>
<p>Now that we have the technical solution out of the way, we're still left with
the bulk of the work left to accomplish: providing end-user documentation
detailing the various payloads, errors, etc.</p>
<p>I've seen two compelling approaches to this problem. The first builds on the
<code>OPTIONS</code> method, and the other uses a hypermedia link in every response to
point to documentation.</p>
<p>The <code>OPTIONS</code> solution is this: <a href="http://zacstewart.com/2012/04/14/http-options-method.html">use the body of an <code>OPTIONS</code> response to provide documentation</a>.
(Keith Casey <a href="https://vimeo.com/49613738">gave an excellent short presentation about this at REST Fest 2012</a>).</p>
<p>The <code>OPTIONS</code> method allows for you to return a body in the response, and also
allows for content negotiation. The theory, then, is that you return
media-type-specific documentation that details the methods allowed, and what
they specifically accept in the body. While there is no standard for this at
this time, the first article I linked suggested including a description, the
parameters expected, and one or more example request bodies for each HTTP
method allowed; you'd likely also want to detail the responses that can be
expected.</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"POST"</span>: {
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Create a new status"</span>,
        <span class="hljs-string">"parameters"</span>: {
            <span class="hljs-string">"type"</span>: {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span>,
                <span class="hljs-string">"description"</span>: <span class="hljs-string">"Status type -- text, image, or url; defaults to text"</span>,
                <span class="hljs-string">"required"</span>: <span class="hljs-literal">false</span>
            },
            <span class="hljs-string">"text"</span>: {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span>,
                <span class="hljs-string">"description"</span>: <span class="hljs-string">"Status text; required for text types, optional for others"</span>,
                <span class="hljs-string">"required"</span>: <span class="hljs-literal">false</span>
            },
            <span class="hljs-string">"image_url"</span>: {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span>,
                <span class="hljs-string">"description"</span>: <span class="hljs-string">"URL of image for image types; required for image types"</span>,
                <span class="hljs-string">"required"</span>: <span class="hljs-literal">false</span>
            },
            <span class="hljs-string">"link_url"</span>: {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"string"</span>,
                <span class="hljs-string">"description"</span>: <span class="hljs-string">"URL of image for link types; required for link types"</span>,
                <span class="hljs-string">"required"</span>: <span class="hljs-literal">false</span>
            }
        },
        <span class="hljs-string">"responses"</span>: [
            {
                <span class="hljs-string">"describedBy"</span>: <span class="hljs-string">"http://example.com/problems/invalid-status"</span>,
                <span class="hljs-string">"title"</span>: <span class="hljs-string">"Submitted status was invalid"</span>,
                <span class="hljs-string">"detail"</span>: <span class="hljs-string">"Missing text field required for text type"</span>
            },
            {
                <span class="hljs-string">"id"</span>: <span class="hljs-string">"abcdef123456"</span>,
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"text"</span>,
                <span class="hljs-string">"text"</span>: <span class="hljs-string">"This is a status update"</span>,
                <span class="hljs-string">"timestamp"</span>: <span class="hljs-string">"2013-02-22T10:06:05+0:00"</span>
            }
        ],
        <span class="hljs-string">"examples"</span>: [
            {
                <span class="hljs-string">"text"</span>: <span class="hljs-string">"This is a status update"</span>
            },
            {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"image"</span>,
                <span class="hljs-string">"text"</span>: <span class="hljs-string">"This is the image caption"</span>,
                <span class="hljs-string">"image_url"</span>: <span class="hljs-string">"http://example.com/favicon.ico"</span>
            },
            {
                <span class="hljs-string">"type"</span>: <span class="hljs-string">"link"</span>,
                <span class="hljs-string">"text"</span>: <span class="hljs-string">"This is a description of the link"</span>,
                <span class="hljs-string">"link_url"</span>: <span class="hljs-string">"http://example.com/"</span>
            },
        ]
    }
}
</code></pre>
<p>If you were to use this methodology, you would alter the <code>options()</code> method
such that it does not return a response object, but instead return a view model
with the documentation.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>\<span class="hljs-title">Controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractRestfulController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FooController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractRestfulController</span>
</span>{
    <span class="hljs-keyword">protected</span> $viewModelMap = <span class="hljs-keyword">array</span>(<span class="hljs-comment">/* ... */</span>);

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">options</span><span class="hljs-params">()</span>
    </span>{
        $response = <span class="hljs-keyword">$this</span>-&gt;getResponse();
        $headers  = $response-&gt;getHeaders();

        <span class="hljs-comment">// Get a view model based on Accept types</span>
        $model    = <span class="hljs-keyword">$this</span>-&gt;acceptableViewModelSelector(<span class="hljs-keyword">$this</span>-&gt;viewModelMap);

        <span class="hljs-comment">// If you want to vary based on whether this is a collection or an</span>
        <span class="hljs-comment">// individual item in that collection, check if an identifier from</span>
        <span class="hljs-comment">// the route is present</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;params()-&gt;fromRoute(<span class="hljs-string">'id'</span>, <span class="hljs-keyword">false</span>)) {
            <span class="hljs-comment">// Still set the Allow header</span>
            $headers-&gt;addHeaderLine(<span class="hljs-string">'Allow'</span>, implode(
                <span class="hljs-string">','</span>, 
                <span class="hljs-keyword">$this</span>-&gt;allowedResourceMethods
            ));

            <span class="hljs-comment">// Set documentation specification as variables</span>
            $model-&gt;setVariables(<span class="hljs-keyword">$this</span>-&gt;getResourceDocumentationSpec());
            <span class="hljs-keyword">return</span> $model;
        }

        <span class="hljs-comment">// Allow only retrieval and creation on collections</span>
        $headers-&gt;addHeaderLine(<span class="hljs-string">'Allow'</span>, implode(
            <span class="hljs-string">','</span>,
            <span class="hljs-keyword">$this</span>-&gt;allowedCollectionMethods
        ));
        $model-&gt;setVariables(<span class="hljs-keyword">$this</span>-&gt;getCollectionDocumentationSpec());
        <span class="hljs-keyword">return</span> $model;
    }
}
</code></pre>
<p>I purposely didn't provide the implementations of the
<code>getResourceDocumentationSpec()</code> and <code>getCollectionDocumentationSpec()</code>
methods, as that will likely be highly specific to your application. Another
possibility is to use your view engine for this, and specify a template file
that has the fully-populated information. This would require a custom renderer
when using JSON or XML, but is a pretty easy solution.</p>
<p><strong>However, there's one cautionary tale to tell</strong>, something I already
mentioned: <code>OPTIONS</code>, per the specification, is <em>non-cacheable</em>. What this
means is that everytime somebody makes an <code>OPTIONS</code> request, any cache control
headers you provide will be ignored, which means hitting the server for each
and every request to the documentation. Considering documentation is static,
this is problematic; it has even prompted <a href="http://www.mnot.net/blog/2012/10/29/NO_OPTIONS">blog posts urging you not to use OPTIONS for documentation</a>.</p>
<p>Which brings us to the second solution for end-user documentation: a static
page referenced via a hypermedia link.</p>
<p>This solution is insanely easy: you simply provide a <code>Link</code> header in your
response, and provide a <code>describedby</code> reference pointing to the documentation
page:</p>
<pre><code class="language-http hljs http" data-lang="http"><span class="hljs-attribute">Link</span>: &lt;http://example.com/api/documentation.md&gt;; rel="describedby"
</code></pre>
<p>With ZF2, this is trivially easy to accomplish: create a route and endpoint for
your documentation, and then a listener on your controller that adds the <code>Link</code>
header to your response.</p>
<p>The latter, adding the link header, might look like this:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>\<span class="hljs-title">Controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">EventManager</span>\<span class="hljs-title">EventManagerInterface</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractRestfulController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FooController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractRestfulController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setEventManager</span><span class="hljs-params">(EventManagerInterface $events)</span>
    </span>{
        <span class="hljs-keyword">parent</span>::setEventManager($events);
        $events-&gt;attach(<span class="hljs-string">'dispatch'</span>, <span class="hljs-keyword">array</span>(<span class="hljs-keyword">$this</span>, <span class="hljs-string">'injectLinkHeader'</span>), <span class="hljs-number">20</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">injectLinkHeader</span><span class="hljs-params">($e)</span>
    </span>{
        $response = $e-&gt;getResponse();
        $headers  = $response-&gt;getHeaders();
        $headers-&gt;addHeaderLine(<span class="hljs-string">'Link'</span>, sprintf(
            <span class="hljs-string">'&lt;%s&gt;; rel="describedby"'</span>, 
            <span class="hljs-keyword">$this</span>-&gt;url(<span class="hljs-string">'documentation-route-name'</span>)
        ));
    }
}
</code></pre>
<p>If you want to ensure you get a fully qualified URL that includes the schema,
hostname, and port, there are a number of ways to do that as well; the above
gives you the basic idea.</p>
<p>Now, for the route and endpoint, there are tools that will help you simplify
that task as well, in the form of a couple of ZF2 modules:
<a href="https://github.com/weierophinney/PhlySimplePage">PhlySimplePage</a> and
<a href="https://github.com/Soflomo/Prototype">Soflomo\Prototype</a>. <em>(Disclosure: I'm
the author of PhlySimplePage.)</em></p>
<p>Both essentially allow you to specify a route and the corresponding template
name to use, which means all you need to do is provide a little configuration,
and a view template. <code>Soflomo\Prototype</code> has slightly simpler configuration, so
I'll demonstrate it here:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'soflomo_prototype'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'documentation-route-name'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'route'</span>    =&gt; <span class="hljs-string">'/api/documentation'</span>,
            <span class="hljs-string">'template'</span> =&gt; <span class="hljs-string">'api/documentation'</span>,
        ),
    ),
    <span class="hljs-string">'view_manager'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'template_map'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'api/documentation'</span> =&gt; <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/../view/api/documentation.phtml'</span>,
        ),
    ),
);
</code></pre>
<p>I personally have been using the <code>Link</code> header solution, as it's so simple to
implement. It does <em>not</em> write the documentation for you, but thinking about it
early and implementing it helps ensure you at least start writing the
documentation, and, if you open source your project, you may find you have
users who will write the documentation for you if they know where it lives.</p>
<h2>Conclusions</h2>
<p>Document your API, or either nobody will use it, or all you're hear are
complaints from your users about having to guess constantly about how to use
it. Include the following information:</p>
<ul>
<li>What endpoint(s) is (are) available.</li>
<li>Which operations are available for each endpoint.
<ul>
<li>What payloads are expected by the endpoint.</li>
<li>What payloads can a user expect in return.</li>
<li>What media types may be used for requests.</li>
<li>What media types may be expected in responses.</li>
</ul>
</li>
</ul>
<p>Additionally, make sure that you do the <code>OPTIONS</code>/<code>Allow</code> dance; don't just
accept any request method, and report the standard 405 response for methods
that you will not allow. Make sure you differentiate these for collections
versus individual resources, as you likely may allow replacing or updating an
individual resource, but likely will not want to do the same for a whole
collection!</p>
<h2>Next time</h2>
<p>So far, I've covered the basics of RESTful JSON APIS, specifically recommending
Hypermedia Application Language (HAL) for providing hypermedia linking and
relations. I've covered error reporting, and provided two potential formats
(API-Problem and vnd.error) for use with your APIs. Now, in this article, I've
shown a bit about documenting your API both for machine consumption as well as
end-users. What's left?</p>
<p>In upcoming parts, I'll talk about ZF2's <code>AbstractRestfulController</code> in more
detail, as well as how to perform some basic content negotiation. I've also had
requests about how one might deal with API versioning, and will attempt to
demonstrate some techniques for doing that as well. Finally, expect to see a
post showing how I've tied all of this together in a general-purpose ZF2 module
so that you can ignore all of these posts and simply start writing APIs.</p>
<h3>Updates</h3>
<p><em>Note: I'll update this post with links to the other posts in the series as I
publish them.</em></p>
<ul>
<li><a href="/blog/2013-02-11-restful-apis-with-zf2-part-1.html">Part 1</a></li>
<li><a href="/blog/2013-02-13-restful-apis-with-zf2-part-2.html">Part 2</a></li>
</ul>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2013-02-25-restful-apis-with-zf2-part-3.html">RESTful APIs with ZF2, Part 3</a> was originally
    published <time class="dt-published" datetime="2013-02-25T06:29:00-06:00">25 February 2013</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>RESTful APIs with ZF2, Part 2</title>
      <pubDate>Wed, 13 Feb 2013 07:40:00 -0600</pubDate>
      <link>https://mwop.net/blog/2013-02-13-restful-apis-with-zf2-part-2.html</link>
      <guid>https://mwop.net/blog/2013-02-13-restful-apis-with-zf2-part-2.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>In my <a href="/blog/2013-02-11-restful-apis-with-zf2-part-1.html">last post</a>, I
covered some background on REST and the Richardson Maturity Model, and some
emerging standards around hypermedia APIs in JSON; in particular, I outlined
aspects of Hypermedia Application Language (HAL), and how it can be used to
define a generic structure for JSON resources.</p>
<p>In this post, I cover an aspect of RESTful APIs that's often overlooked:
reporting problems.</p>


<h2>Background</h2>
<p>APIs are useful when they're working. But when they fail, they're only useful
if they provide us with meaningful information; if all I get is a status code,
and no indication of what caused the issue, or where I might look for more
information, I get frustrated.</p>
<p>In consuming APIs, I've come to the following conclusions:</p>
<ul>
<li>Error conditions need to provide detailed information as to what went wrong,
and what steps I may be able to take next. An error code with no context
gives me nothing to go on.</li>
<li>Errors need to be reported consistently. Don't report the error one way one
time, and another way the next.</li>
<li><strong>DO</strong> use HTTP status codes to indicate an error happened. Nothing is more
irksome than getting back a 200 status with an error payload.</li>
<li>Errors should be reported in a format I have indicated I will Accept (as in
the HTTP header). Perhaps the only think more irksome than a 200 status code
for an error is getting back an HTML page when I expect JSON.</li>
</ul>
<h2>Why Status Codes Aren't Enough</h2>
<p>Since REST leverages and builds on HTTP, an expedient solution for reporting
problems is to simply use <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP status codes</a>.
These are well understood by web developers, right?</p>
<p><code>4xx</code> error codes are errors made by the requestor, and are actually fairly
reasonable to use for reporting things such as lack of authorization tokens,
incomplete requests, unsupportable operations, or non-supported media types.</p>
<p>But what happens when the error is on the server — because something has gone
wrong such as inability to reach your persistence layer or credential storage?
The <code>5xx</code> series of status codes is sparse and wholly unsuited to reporting
errors of these types — <em>though you'll likely still want to use a <code>500</code> status
to report the failure</em>. But what do you present to the consumer so that they
know whether or not to try again, or what to report to you so that you can fix
the issue?</p>
<p>A status code simply isn't enough information most of the time. Yes, you want
to define standard status codes so that your clients can perform reasonable
branching, but you also need a way to communicate <em>details</em> to the end-user, so
that they can log the information for themselves, display information to their
own end-users, and/or report it back to you so you can do something to resolve
the situation.</p>
<h2>Custom Media Types</h2>
<p>The first step is to use a custom media type. Media types are typically both a
name as well as a structure — and the latter is what we're after when it comes
to error reporting.</p>
<p>If we return a response using this media type, the client then knows how to
parse it, and can then process it, log it, whatever.</p>
<p>Sure, you can make up your own format — as long as you are consistent in using
it, and you document it. But personally, I don't like inventing new formats
when standard formats exist already. Custom formats mean that custom clients
are required for working with the services; using a standard format can save
effort and time.</p>
<p>In the world of JSON, I've come across two error media types that appear to be
gaining traction: <code>application/api-problem+json</code> and
<code>application/vnd.error+json</code></p>
<h3>API-Problem</h3>
<p>This particular media type is <a href="http://tools.ietf.org/html/draft-nottingham-http-problem-02">via the IETF</a>.
Like HAL, it provides formats in both JSON and XML, making it a nice
cross-platform choice.</p>
<p>As noted already, the media type is <code>application/api-problem+json</code>. The
representation is a single resource, with the following properties:</p>
<ul>
<li><strong>describedBy</strong>: a URL to a document describing the error condition (required)</li>
<li><strong>title</strong>: a brief title for the error condition (required)</li>
<li><strong>httpStatus</strong>: the HTTP status code for the current request (optional)</li>
<li><strong>detail</strong>: error details specific to this request (optional)</li>
<li><strong>supportId</strong>: a URL to the specific problem occurrence (e.g., to a log message) (optional)</li>
</ul>
<p>As an example:</p>
<pre><code class="language-http hljs http" data-lang="http">HTTP/1.1 <span class="hljs-number">500</span> Internal Error
<span class="hljs-attribute">Content-Type</span>: application/api-problem+json

{
    "describedBy": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
    "detail": "Status failed validation",
    "httpStatus": 500,
    "title": "Internal Server Error"
}
</code></pre>
<p>The specification allows a large amount of flexibility — you can have your own
custom error types, so long as you have a description of them to link to. You
can provide as little or as much detail as you want, and even decide what
information to expose based on environment.</p>
<p>I personally like to point to the HTTP status code definitions, and then
provide request-specific detail; I find this gives quick and simple results
that I can later shape as I add more detail to my API. However, the
specification definitely encourages you to have unique error types with
discrete URIs that describe them — never a bad thing when creating APIs.</p>
<h3>vnd.error</h3>
<p>This is a <a href="https://github.com/blongden/vnd.error">proposed media type</a> within
the HAL community. Like HAL, it provides formats in both JSON and XML, making
it a nice cross-platform choice.</p>
<p>It differentiates from API-Problem in a few ways. First, it allows, and even
encourages, reporting collections of errors. If you consider PHP exceptions and
the fact that they support &quot;previous&quot; exceptions, this is a powerful concept;
you can report the entire chain of errors that led to the response. Second, it
encourages pushing detail out of the web service; errors include a &quot;logRef&quot;
property that points to where the error detail lives. This is probably better
illustrated than explained.</p>
<p>The response payload is an array of objects. Each object has the following
members:</p>
<ul>
<li><strong>logRef</strong>: a unique identifier for the specific error which can then be used
to identify the error within server-side logs (required)</li>
<li><strong>message</strong>: the error message itself (required)</li>
<li><strong>_links</strong>: HAL-compatible links. Typically, &quot;help&quot;, &quot;describes&quot;, and/or
&quot;describedBy&quot; relations will be defined here.</li>
</ul>
<p>As an example, let's consider the API-Problem example I had earlier, and
provide a <code>vnd.error</code> equivalent:</p>
<pre><code class="language-http hljs http" data-lang="http">HTTP/1.1 <span class="hljs-number">500</span> Internal Error
<span class="hljs-attribute">Content-Type</span>: application/vnd.error+json

[
    {
        "logRef": "someSha1HashMostLikely",
        "message": "Status failed validation",
        "_links": {
            "describedBy": {"href": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"}
        }
    }
]
</code></pre>
<p><code>vnd.error</code> basically begs you to create custom error types, with documentation
end-points that detail the source of the error and what you can do about it
(this is true of API-Problem as well).</p>
<p>The requirement to include a log reference (&quot;logRef&quot;) and have it be unique can
be a stumbling block to implementation, however, as it requires effort for
uniquely identifying requests, and logging. However, both the identification
and logging can be automated.</p>
<h2>Summary</h2>
<p>Error reporting in APIs is as important as the normal resource payloads
themselves. Without good error reporting, when an API raises errors, clients
have difficulty understanding what they can do next, and cannot provide you,
the API provider, with information that will allow you to debug on the server
side.</p>
<p>As noted at the beginning of the article, if you follow the rules below, you'll
make consumers of your API happier and more productive.</p>
<ul>
<li><strong>DO</strong> use appropriate HTTP status codes to indicate an error happened.</li>
<li>Report errors in a format I have indicated I will Accept (as in the HTTP
header).</li>
<li>Report errors consistently. Don't report the error one way one time, and
another way the next. Standardize on a specific error-reporting media type .
While you <em>can</em> create your own error structure, I recommend using
documented, accepted standards. This will make clients more re-usable, and
make many of your decisions for you.</li>
<li>Provide detailed information as to what went wrong, and what steps I may be
able to take next. Provide documentation for each type of error, and link to
that documentation from your error payloads.</li>
</ul>
<p>Which brings me to…</p>
<h2>Next time</h2>
<p>I realize I still haven't covered anything specific to ZF2, but I'll start next
time, when I cover the next topic: documenting your API. An undocumented API is
a useless API, so it's good to start baking documentation in immediately. I'll
survey some of the possibilities and how they can be implemented in ZF2 in the
next installment, and then we can get our hands dirty with actual API
development.</p>
<h3>Updates</h3>
<p><em>Note: I'll update this post with links to the other posts in the series as I
publish them.</em></p>
<ul>
<li><a href="/blog/2013-02-11-restful-apis-with-zf2-part-1.html">Part 1</a></li>
<li><a href="/blog/2013-02-25-restful-apis-with-zf2-part-3.html">Part 3</a></li>
</ul>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2013-02-13-restful-apis-with-zf2-part-2.html">RESTful APIs with ZF2, Part 2</a> was originally
    published <time class="dt-published" datetime="2013-02-13T07:40:00-06:00">13 February 2013</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>RESTful APIs with ZF2, Part 1</title>
      <pubDate>Wed, 13 Feb 2013 07:40:00 -0600</pubDate>
      <link>https://mwop.net/blog/2013-02-11-restful-apis-with-zf2-part-1.html</link>
      <guid>https://mwop.net/blog/2013-02-11-restful-apis-with-zf2-part-1.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>RESTful APIs have been an interest of mine for a couple of years, but due to
<a href="http://framework.zend.com/blog//zend-framework-2-0-0-stable-released.html">circumstances</a>,
I've not had much chance to work with them in any meaningful fashion until
recently.</p>
<p><a href="http://akrabat.com/">Rob Allen</a> and I proposed a workshop for
<a href="http://conference.phpbenelux.eu/2013/">PHP Benelux 2013</a> covering RESTful APIs
with ZF2.  When it was accepted, it gave me the perfect opportunity to dive in
and start putting the various pieces together.</p>


<h2>Background</h2>
<p>I've attended any number of conference sessions on API design, read countless
articles, and engaged in quite a number of conversations. Three facts keep
cropping up:</p>
<ol>
<li>JSON is fast becoming the preferred exchange format due to the ease with
which it de/serializes in almost every language.</li>
<li>The &quot;holy grail&quot; is <a href="http://martinfowler.com/articles/richardsonMaturityModel.html">Richardson Maturity Model</a> Level 3.</li>
<li>It's really hard to achieve RMM level 3 with JSON.</li>
</ol>
<h3>Richardson Maturity Model</h3>
<p>As a quick review, the Richardson Maturity Model has the following 4 levels:</p>
<ul>
<li>Level 0: &quot;The swamp of POX.&quot; Basically, a service that uses TCP for
transport, primarily as a form of remote procedure call (RPC). Typically,
these are not really leveraging HTTP in any meaningful fashion; most systems
will use HTTP POST for all interactions. Also, you will often have a single
endpoint for all interactions, regardless of whether or not they are strictly
related. XML-RPC, SOAP, and JSON-RPC fall under this category.</li>
<li>Level 1: &quot;Resources.&quot; In these services, you start breaking the service into
multiple services, one per &quot;resource,&quot; or, in object oriented terms, per
object. This means a distinct URL per object, which means each has its own
distinct identity on the web; this often extends not only to the collection
of objects, but to individual objects under the collection as well (e.g.,
<code>/books</code> as well as <code>/books/life-of-pi</code>). The service may still be RPC in
nature, however, and, at this level, often is still using a single HTTP
method for all interactions with the resource.</li>
<li>Level 2: &quot;HTTP Verbs.&quot; At this level, we start using HTTP verbs with our
services in the way the HTTP specification intends. GET is for safe
operations, and should be cacheable; POST is used for creation and/or
updating; DELETE can be used to delete a resource; etc. Rather than doing RPC
style methods, we leverage HTTP, occasionally passing additional parameters
via the query string or request body. Considerations such as HTTP caching and
idempotence are taken into account.</li>
<li>Level 3: &quot;Hypermedia Controls.&quot; Building on the previous level, our resource
representations now also include <em>links</em>, which indicate what we can <em>do
next</em>. At this level, our API becomes practically self-describing; given a
single end-point, we should be able to start crawling it, using the links in
a representation to lead us to the next actions.</li>
</ul>
<p>When I first started playing with web services around a decade ago, everything
was stuck at Level 0 or Level 1 — usually with Level 1 users downgrading to
Level 0 because Level 0 offerred consistency and predictability if you chose to
use a service type that had a defined envelope format (such as XML-RPC or
SOAP). (I even wrote the XML-RPC server implementation for Zend Framework
because I got sick of writing one-off parsers/serializers for custom XML web
service implementations. When you're implementing many services, predictability
is a huge win.)</p>
<p>A few years ago, I started seeing a trend towards Level 2. Web developers like
the simplicity of using HTTP verbs, as they map very well to
<a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> operations
— the bread and butter of web development. Couple this concept with JSON, and
it becomes trivially simple to both create a web service, as well as consume
it.</p>
<p><em>I'd argue that the majority of web developers are quite happy to be at Level 2
— and have no problem staying there. They're productive, and the concepts are
easy — both to understand and to implement.</em></p>
<p>Level 3, though, is where it becomes really interesting. The idea that I can
examine the represention <em>alone</em> in order to understand what I can do next is
very intriguing and empowering.</p>
<h3>JSON and Hypermedia</h3>
<p>With XML, hypermedia basically comes for free. Add some <code>&lt;link&gt;</code> elements to
your representation, and you're done — and don't forget the link <code>rel</code>ations!</p>
<p>JSON, however, is another story.</p>
<p>Where do the links go? <em>There is no single, defined way to represent a
hyperlink in JSON.</em></p>
<p>Fortunately, there are some emerging standards.</p>
<p>First is use of the <a href="http://www.w3.org/wiki/LinkHeader">&quot;Link&quot; HTTP header</a>.
While the page I linked shows only a single link in the header, you can have
multiple links separated by commas. GitHub uses this when providing pagination
links in their API. Critics will point out that the HTTP headers are not
technically part of the representation, however; strict interpetations of REST
and RMM indicate that the hypermedia links should be part of the resource
representation. Regardless, having the links in the HTTP headers is useful for
pre-traversal of a service, as you can perform HEAD requests only to discover
possible actions and workflows.</p>
<p><a href="http://amundsen.com/media-types/collection/format/">Collection+JSON</a> is
interesting, as it describes the entire JSON envelope. My one criticism is that
it details too much; whenever I see a format that dictates how to describe
types, I think of XML-RPC or SOAP, and get a little twitchy. It's definitely
worth a look, though.</p>
<p>What's captured my attention of late, however, is
<a href="http://stateless.co/hal_specification.html">Hypertext Application Language</a>,
or HAL for short. HAL has very few rules, but succinctly describes both how to
provide hypermedia in JSON as well as how to represent embedded resources — the
two things that most need standardized structure in JSON. It does this while
still providing a generic media type, and also describing a mirror image XML
format!</p>
<h3>HAL Media Types</h3>
<p>HAL defines two generic media types: <code>application/hal+xml</code> and
<code>application/hal+json</code>. You will use these as the response <code>Content-Type</code>, as
they describe the response representation; the client can simply request
<code>application/json</code>, and the response format remains compatible.</p>
<h3>HAL and Links</h3>
<p>HAL provides a very simple structure for JSON hypermedia links. First, all
resource representations must contain hypermedia links, and all links are
provided in a <code>_links</code> object:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
    }
}
</code></pre>
<p>Second, links are properties of this object. The property name is the link
relation, and the value is an object containing minimally an &quot;href&quot; property.</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1234"</span>}
    }
}
</code></pre>
<p>If a given relation can have multiple links, you provide instead an array of objects:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1234"</span>},
        <span class="hljs-string">"conversation"</span>: [
            {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1237"</span>},
            {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1241"</span>}
        ]
    }
}
</code></pre>
<p>Individual links can contain other attributes as desired — I've seen people
include the relation again so that it's self-contained in the link object, and
it's not uncommon to include a title or name.</p>
<h3>HAL and Resources</h3>
<p>HAL imposes no structure over resources other than requiring the hypermedia
links; even then, you typically do not include the hypermedia links when making
a request of the web service; the hypermedia links are included only in the
representations <em>returned</em> by the service.</p>
<p>So, as an example, you would POST the following:</p>
<pre><code class="language-http hljs http" data-lang="http"><span class="hljs-attribute">POST /api/status
Host</span>: example.com
<span class="hljs-attribute">Accept</span>: application/json
<span class="hljs-attribute">Content-Type</span>: application/json

{
    "status": "This is my awesome status update!",
    "user": "mwop"
}
</code></pre>
<p>And from that request, you'd receive the following:</p>
<pre><code class="language-http hljs http" data-lang="http"><span class="hljs-attribute">201 Created
Location</span>: http://example.com/api/status/1347
<span class="hljs-attribute">Content-Type</span>: application/hal+json

{
    "_links": {
        "self": {"href": "http://example.com/api/status/1347"}
    },
    "id": "1347",
    "timestamp": "2013-02-11 23:33:47",
    "status": "This is my awesome status update!",
    "user": "mwop"
}
</code></pre>
<h3>HAL and Embedded Resources</h3>
<p>The other important thing that HAL defines is how to <em>embed</em> resources. Why is
this important? If the resource references other resources, you will want to be
able to link to them so you can perform operations on them, too.</p>
<p>Embedded resources are represented inside an <code>_embedded</code> object of the
representation, and, as resources, contain their own <code>_links</code> object as well.
Each resource you embed is assigned to a property of that object, and if
multiple objects of the same type are returned, an array of resources is
assigned. In fact, this latter is how you represent <em>collections</em> in HAL.</p>
<p>Let's consider a simple example first. In previous code samples, I have a
&quot;user&quot; that's a string; let's make that an embedded resource instead.</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1347"</span>}
    },
    <span class="hljs-string">"id"</span>: <span class="hljs-string">"1347"</span>,
    <span class="hljs-string">"timestamp"</span>: <span class="hljs-string">"2013-02-11 23:33:47"</span>,
    <span class="hljs-string">"status"</span>: <span class="hljs-string">"This is my awesome status update!"</span>,
    <span class="hljs-string">"_embedded"</span>: {
        <span class="hljs-string">"user"</span>: {
            <span class="hljs-string">"_links"</span>: {
                <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/user/mwop"</span>}
            }
            <span class="hljs-string">"id"</span>: <span class="hljs-string">"mwop"</span>,
            <span class="hljs-string">"name"</span>: <span class="hljs-string">"Matthew Weier O'Phinney"</span>,
            <span class="hljs-string">"url"</span>: <span class="hljs-string">"http://mwop.net"</span>
        }
    }
}
</code></pre>
<p>I've moved the &quot;user&quot; out of the representation, and into the <code>_embedded</code>
object — because this is where you define embedded resources. Note that the
&quot;user&quot; is a standard HAL resource itself — containing hypermedia links.</p>
<p>Now let's look at a collection:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"_links"</span>: {
        <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status"</span>},
        <span class="hljs-string">"next"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status?page=2"</span>},
        <span class="hljs-string">"last"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status?page=100"</span>}
    },
    <span class="hljs-string">"count"</span>: <span class="hljs-number">2973</span>,
    <span class="hljs-string">"per_page"</span>: <span class="hljs-number">30</span>,
    <span class="hljs-string">"page"</span>: <span class="hljs-number">1</span>,
    <span class="hljs-string">"_embedded"</span>: {
        <span class="hljs-string">"status"</span>: [
            {
                <span class="hljs-string">"_links"</span>: {
                    <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/status/1347"</span>}
                },
                <span class="hljs-string">"id"</span>: <span class="hljs-string">"1347"</span>,
                <span class="hljs-string">"timestamp"</span>: <span class="hljs-string">"2013-02-11 23:33:47"</span>,
                <span class="hljs-string">"status"</span>: <span class="hljs-string">"This is my awesome status update!"</span>,
                <span class="hljs-string">"_embedded"</span>: {
                    <span class="hljs-string">"user"</span>: {
                        <span class="hljs-string">"_links"</span>: {
                            <span class="hljs-string">"self"</span>: {<span class="hljs-string">"href"</span>: <span class="hljs-string">"http://example.com/api/user/mwop"</span>}
                        }
                        <span class="hljs-string">"id"</span>: <span class="hljs-string">"mwop"</span>,
                        <span class="hljs-string">"name"</span>: <span class="hljs-string">"Matthew Weier O'Phinney"</span>,
                        <span class="hljs-string">"url"</span>: <span class="hljs-string">"http://mwop.net"</span>
                    }
                }
            }
            <span class="hljs-comment">/* ... */</span>
        ]
    }
}
</code></pre>
<p>Note that the &quot;status&quot; property is an array; semantically, all resources under
this key are of the same type. Also note that the parent resource has some
additional link relations — these are related to pagination, and allow a
client to determine what the next and last pages are (and, if we were midway
into the collection, previous and first pages). Since the collection is also a
resource, it has some interesting metadata — how many resources are in the
collection, how many we represent per page, and what the current page is.</p>
<p>Also note that you can nest resources — simply include an <code>_embedded</code> object
inside an embedded resource, with additional resources, as I've done with the
&quot;user&quot; resource inside the status resource shown here. It's turtles all the way
down.</p>
<h2>Next Time</h2>
<p>The title of this post indicates I'll be talking about building RESTful APIs
with ZF2 — but so far, I've not said anything about ZF2.</p>
<p>I'll get there. But there's another detour to take: reporting errors.</p>
<h3>Updates</h3>
<p><em>Note: I'll update this post with links to the other posts in the series as I
publish them.</em></p>
<ul>
<li><a href="/blog/2013-02-13-restful-apis-with-zf2-part-2.html">Part 2</a></li>
<li><a href="/blog/2013-02-25-restful-apis-with-zf2-part-3.html">Part 3</a></li>
</ul>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2013-02-11-restful-apis-with-zf2-part-1.html">RESTful APIs with ZF2, Part 1</a> was originally
    published <time class="dt-published" datetime="2013-02-12T05:42:00-06:00">12 February 2013</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Zend Server, ZF2, and Page Caching</title>
      <pubDate>Mon, 05 Nov 2012 15:25:00 -0600</pubDate>
      <link>https://mwop.net/blog/2012-11-05-zend-server-caching.html</link>
      <guid>https://mwop.net/blog/2012-11-05-zend-server-caching.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>Zend Server has a very cool <a href="https://www.youtube.com/watch_v=i2XXn2SA5zM.html">Page Caching feature</a>.
Basically, you can provide URLs or URL regular expressions, and tell Zend
Server to provide full-page caching of those pages. This can provide a
tremendous performance boost, without needing to change anything in your
application structure; simply enable it for a set of pages, and sit back and
relax.</p>


<p><img src="/images/blog/2012-11-04-Server-CachingRule.png" alt="Zend Server Page Caching" title="Zend Server Page Caching" /></p>
<p>However, this feature is not entirely straight-forward when using a framework
that provides its own routing, such as ZF2. The reason is because it assumes by
default that each match maps to a specific file on the filesystem, and prepares
the caching based on the actual <em>file</em> it hits. What this means for ZF2 and
other similar frameworks is that any page that matches will return the cached
version for the <em>first</em> match that also matches the same <em>file</em> — i.e.,
<code>index.php</code> in ZF2. That's every page the framework handles. As an example, if
I match on <code>/article/\d+</code>, it matches this to the file <code>index.php</code>, and then
any other match that resolves to <code>index.php</code> gets served that same page. Not
handy.</p>
<p>The good part is that there's a way around this.</p>
<p>When creating or modifying a caching rule, simply look for the text, &quot;Create a
separate cached page for each value of:&quot; and click the &quot;Add Parameter&quot; button.
Select <code>_SERVER</code> from the dropdown, and type <code>[REQUEST_URI]</code> for the value.
Once saved, each page that matches the pattern will be cached separately.</p>
<p><img src="/images/blog/2012-11-04-Server-Caching-Request.png" alt="Zend Server Page Caching by Request" title="Zend Server Page Caching by Request" /></p>
<p>Note: the <code>_SERVER</code> key may vary based on what environment/OS you're deployed
in. Additionally, it may differ based on how you define rewrite rules — some
frameworks and CMS systems will append to the query string, for instance, in
which case you may want to select the &quot;entire query string&quot; parameter instead
of <code>_SERVER</code>; the point is, there's likely a way for you to configure it.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-11-05-zend-server-caching.html">Zend Server, ZF2, and Page Caching</a> was originally
    published <time class="dt-published" datetime="2012-11-05T15:25:00-06:00">5 November 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>OpenShift, ZF2, and Composer</title>
      <pubDate>Thu, 01 Nov 2012 15:25:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html</link>
      <guid>https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I was recently shopping around for inexpensive cloud hosting; I want to try out
a couple of ideas that may or may not have much traffic, but which aren't
suited for my VPS setup (the excellent <a href="http://servergrove.com/">ServerGrove</a>);
additionally, I'm unsure how long I will maintain these projects. My budget for
this is quite small as a result; I'm already paying for hosting, and am quite
happy with it, so this is really for experimental stuff.</p>
<p>I considered Amazon, Orchestra.io, and a few others, but was concerned about
the idea of a ~$50/month cost for something I'm uncertain about.</p>
<p>When I asked in <a href="irc://irc.freenode.net/zftalk.dev">#zftalk.dev</a>, someone
suggested <a href="http://openshift.redhat.com/">OpenShift</a> as an idea, and
coincidentally, the very next day
<a href="http://www.zend.com/en/company/news/press/379_red-hat-expands-openshift-ecosystem-with-zend-partnership-to-offer-professional-grade-environment-for-php-developers">Zend announced a partnership with RedHat surrounding OpenShift</a>.
The stars were in alignment.</p>
<p>In the past month, in the few spare moments I've had (which included an
excellent OpenShift hackathon at ZendCon), I've created a quick application
that I've deployed and tested in OpenShift. These are my findings.</p>


<h2>ZF2</h2>
<p>I didn't really have to do anything different to have
<a href="http://framework.zend.com/">zf2</a> work; the standard <code>.htaccess</code> provided in
the skeleton application worked flawlessly the first time (I've worked with
some cloud environments where this is not the case).</p>
<p>The only frustration I had was the default directory structure OpenShift foists
upon us:</p>
<pre><code class="language-powershell hljs powershell" data-lang="powershell"><span class="hljs-keyword">data</span>/
libs/
misc/
php/
</code></pre>
<p>This is not terrible, by any stretch. However, it's attempting to dictate the
application structure, which I'm not terribly happy with — particularly as my
structure may vary based on the framework I'm using (or not!), and because I
may already have a project written that I simply want to deploy.</p>
<p>In particular, the <code>php</code> directory is galling — it's simply the document root.
Most frameworks I've used or seen call the equivalent directory <code>public</code>, or
<code>web</code>, or <code>html</code> — but never <code>php</code> (in large part because the only PHP file
under the document root in most frameworks is the <code>index.php</code> that acts as the
front controller). It would be nice if this were configurable.</p>
<p>This conflicts a bit with how a ZF2 app is structured. I ended up doing the
following:</p>
<ul>
<li>Removed <code>php</code> and symlinked my <code>public</code> directory to it.</li>
<li>Removed <code>libs</code> and symlinked my <code>vendor</code> directory to it.</li>
<li>Removed <code>misc</code> as I had no need to it.</li>
</ul>
<p>Nothing too big, thankfully — but problematic from the perspective of, &quot;I've
already developed this app, but now I have to make changes for it to work on a
specific cloud vendor.&quot;</p>
<h2>Composer</h2>
<p>My next question was how to use <a href="http://getcomposer.org/">Composer</a> during my
deployment process, and some some googling
<a href="https://openshift.redhat.com/community/content/support-for-git-clone-on-the-server-aka-support-php-composerphar">found some answers for me</a>.</p>
<p>Basically, I needed to create a <code>deploy</code> task that does two things:</p>
<ul>
<li>Unset the <code>GIT_DIR</code> environment variable. Evidently, the build process
operates as part of a git hook, and since Composer often uses git
repositories, this can lead to problems.</li>
<li>Change directory to <code>OPENSHIFT_REPO_DIR</code>, which is where the application root
(not document root!) lives.</li>
</ul>
<p>Once I did those, I could run my normal composer installation. The <code>deploy</code>
task looks like this:</p>
<pre><code class="language-bash hljs bash" data-lang="bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-comment"># .openshift/action_hooks/deploy</span>
( <span class="hljs-built_in">unset</span> GIT_DIR ; <span class="hljs-built_in">cd</span> <span class="hljs-variable">$OPENSHIFT_REPO_DIR</span> ; /usr/<span class="hljs-built_in">local</span>/zend/bin/php composer.phar install )
</code></pre>
<p>This leads into my next topic.</p>
<h2>Deployment</h2>
<p>First off, as you probably guessed from that last secton, there <strong>are</strong> hooks
for deployment — it doesn't have to be simply git. I like this, as I may have
additional things I want to do during deployment, such as retrieving and
installing site-specific configuration files, installing Composer-defined
dependencies (as already noted), etc.</p>
<p>Over all, this is pretty seamless, but it's not without issues. I've been told
that some of my issues are being worked on, so those I won't bring up here. The
ones that were a bit strange, and which caught me by surprise, though, were:</p>
<ul>
<li>Though the build process creates the site build from git, your <strong>submodules
are not updated recursively</strong>. This tripped me up, as I was using
<a href="https://github.com/EvanDotPro/EdpMarkdown">EdpMarkdown</a>, and had installed
it as a submodule. I ended up having to import it, and its own submodule,
directly into my project so that it would work.</li>
<li>I installed the <a href="http://www.mongodb.org/">MongoDB</a> cartridge. Ironically, it
was not then enabled in Zend Server, and I had to go do this. This should be
turnkey.</li>
<li><code>/usr/bin/php</code> is not the same as <code>/usr/local/zend/bin/php</code>. This makes no
sense to me if I've installed Zend Server as my base gear. Considering
they're different versions, this can be hugely misleading and lead to errors.
I understand there are reasons to have both — so simply be aware that if you
use the Zend Server gear, your tasks likely should use
<code>/usr/local/zend/bin/php</code>.</li>
</ul>
<h2>The good parts?</h2>
<ul>
<li><a href="https://openshift.redhat.com/community/faq/i-have-deployed-my-app-but-i-don%E2%80%99t-like-telling-people-to-visit-myapp-myusernamerhcloudcom-how-c">You can alias an application to a DNS
CNAME</a>
— meaning you can point your domain name to your OpenShift applications.
Awesome!</li>
<li>Simplicity of adding capabilities, such as Mongo, MySQL, Cron, and others. In
most cases, this is simply a &quot;click on the button&quot; and it's installed and
available.</li>
<li><a href="http://www.zend.com/en/products/server">Zend Server</a>. For most PHP
extensions, I can turn them on or off with a few mouse clicks. If I want
page-level caching, I don't have to do anything to my application; I can
simply setup some rules in the Zend Server interface and get on with it, and
enjoy tremendous boosts to performance. I used to enjoy taming and tuning
servers; most days anymore, I just want them to work.</li>
<li><a href="https://openshift.redhat.com/community/developers/remote-access">SSH</a> access
to the server, with a number of commands to which I've been given <code>sudoer</code>
access. If you're going to sandbox somebody, this is a fantastic way to do
it. Oh, also: SSH tunnels to services like Mongo and MySQL just work (via the
<code>rhc-port-forward</code> command).</li>
</ul>
<h2>Summary</h2>
<p>Over all, I'm quite pleased. While it took me a bit to find the various
incantations I needed, the service is quite flexible. For my needs, considering
I'm doing experimental stuff, the price can't be beat (the current developer
preview is free). Considering most stuff I do will fall into this or the basic
tier, and that most cartridges do not end up counting against your alotment of
gears, the pricing ($0.05/hour) is extremely competitive.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-11-01-openshift-zf2-composer.html">OpenShift, ZF2, and Composer</a> was originally
    published <time class="dt-published" datetime="2012-11-01T15:25:00-05:00">1 November 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ZF2 Modules Quickstart (Screencast)</title>
      <pubDate>Wed, 19 Sep 2012 13:10:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-09-19-zf2-module-screencast.html</link>
      <guid>https://mwop.net/blog/2012-09-19-zf2-module-screencast.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>One of the exciting features of the newly released Zend Framework 2 is the new module system.</p>
<p>While ZF1 had modules, they were difficult to manage. All resources for all
modules were initialized on each request, and bootstrapping modules was an
onerous task. Due to the difficulties, modules were never truly
&quot;plug-and-play&quot;, and thus no ecosystem ever evolved for sharing modules.</p>
<p>In Zend Framework 2, we've architected the MVC from the ground up to make
modular applications as easy as possible. Within ZF2, the MVC simply cares
about events and services — and controllers are simply one kind of service. As
such, modules are primarily about telling the MVC about services and wiring
event listeners.</p>
<p>To give you an example, in this tutorial, I'll show you how to install the Zend
Framework 2 skeleton application, and we'll then install a module and see how
easy it is to add it to the application and then configure it.</p>


<p>To keep things simple, I'm using a unix-like environment. As such, if you are
on Windows, you may not have the same command-line tools available. If you are
in such a situation, perhaps try this inside a Linux virtual machine.</p>
<p><a href="https://vimeo.com/49775540">Zend Framework 2 Module Quickstart</a></p>
<p>Let's start by creating a new project. We'll execute a few commands to download
a skeleton application archive and extract it.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ mkdir newproject
$ <span class="hljs-built_in">cd</span> newproject
$ wget https://github.com/zendframework/ZendSkeletonApplication/tarball/master \
&gt; -O ZendSkeletonApplication.tgz
$ tar xzf ZendSkeletonApplication.tgz --strip-components=1
</code></pre>
<p>The Zend Framework skeleton application can be downloaded directly off of
<a href="https://github.com">GitHub</a>. I'm showing using the download from master, but
you can also download a tarball or zipball for individual tags as well. Because
the download URL does not include an extension, I use the <code>-O</code> switch to tell
<code>wget</code> what filename to save to.</p>
<p><code>tar</code> has a nice option, <code>--strip-components</code>, which allows you to tell it
to descend a certain number of levels deep into the archive when deflating.
Since I know the tarball has a top-level directory named after the repository
and a sha1, I'm simply telling <code>tar</code> to skip that and give me the contents of
its child directory.</p>
<p>At this point you have the skeleton application, but it has no dependencies —
not even Zend Framework itself! Let's rectify that situation. We'll use the
dependency management tool <a href="https://getcomposer.org/">Composer</a> to do this. We
include the Composer phar file within the skeleton application to make this
fairly easy. Simply execute the following:</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ php composer.phar install
</code></pre>
<p>You may get a notice indicating that the composer version is older, and to run
<code>self-update</code>; you can ignore that for now.</p>
<p>If all goes well, you should now have Zend Framework installed. Let's test it
out. I'm going to use the built-in web server in PHP 5.4 to demonstrate.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p>If I browse to <code>http://localhost:8080</code> I should now see the landing page for
the skeleton application.</p>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-01-zsa.png" alt="" /></p>
<p>Let's add a module to the application. Many sites require a contact form. I've
written one as a module some time ago, and called it
<a href="https://github.com/weierophinney/PhlyContact">PhlyContact</a>. To install it,
I'll edit my project's <code>composer.json</code> and tell it about that dependency:</p>
<pre><code class="language-javascript hljs javascript" data-lang="javascript">{
    <span class="hljs-string">"require"</span>: {
        <span class="hljs-string">"php"</span>: <span class="hljs-string">"&gt;=5.3.3"</span>,
        <span class="hljs-string">"zendframework/zendframework"</span>: <span class="hljs-string">"dev-master"</span>,
        <span class="hljs-string">"phly/phly-contact"</span>: <span class="hljs-string">"dev-master"</span>
    }
}
</code></pre>
<p>I know the name of the component from <a href="http://packagist.org/">http://packagist.org/</a>,
and I'm telling Composer that I want to use whatever the latest version is on
its master branch on GitHub. I happen to also know that PhlyContact requires a
dev-master version of Zend Framework, so I'll alter that dependency for now.</p>
<p>Now, we need to tell composer to update our dependencies.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ php composer.phar update
</code></pre>
<p>After executing the command, we should now see that it has installed; this may
take a little while.</p>
<p>You need to inform the application about the module. This is so that we don't
have to perform expensive file-system scanning operations, but also to make it
explicit in your code what modules you're actually using. Enabling a module is
usually as easy as adding an entry to <code>config/application.config.php</code>:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-string">'modules'</span> =&gt; <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'Application'</span>,
    <span class="hljs-string">'PhlyContact'</span>,
),
</code></pre>
<p>This particular module provides some reasonable defaults. In particular, it
uses a CAPTCHA adapter that doesn't require additional configuration, and
assumes that you will want to use the default <code>Sendmail</code> mail transport. As
such, we can simply browse to it now. I happen to know that the module defines
a <code>/contact</code> end point. Let's fire up our PHP web server again, and browse to
that URL.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-02-contact.png" alt="" /></p>
<p>It just works!</p>
<p>One philosophy we have for distributable modules in Zend Framework 2 is that
you should not need to touch the code in modules you install in your
application. Instead, you should be able to configure and override behavior
within the application configuration or in your application's site-specific
modules. Let's alter the contact module to:</p>
<ul>
<li>first, change the URL it responds to, and</li>
<li>second, use the &quot;file&quot; mail transport.</li>
</ul>
<p>Let's look at the default configuration. I'll browse to
<code>vendor/phly/phly-contact/config/</code> and look at the <code>module.config.php</code> file.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'phly_contact'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'captcha'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span> =&gt; <span class="hljs-string">'dumb'</span>,
        ),
        <span class="hljs-string">'form'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'contact'</span>,
        ),
        <span class="hljs-string">'mail_transport'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span> =&gt; <span class="hljs-string">'Zend\Mail\Transport\Sendmail'</span>,
            <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
            )
        ),
        <span class="hljs-string">'message'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-comment">/*
            'to' =&gt; array(
                'EMAIL HERE' =&gt; 'NAME HERE',
            ),
            'sender' =&gt; array(
                'address' =&gt; 'EMAIL HERE',
                'name'    =&gt; 'NAME HERE',
            ),
            'from' =&gt; array(
                'EMAIL HERE' =&gt; 'NAME HERE',
            ),
             */</span>
        ),
    ),

    <span class="hljs-comment">/* ... */</span>

    <span class="hljs-string">'router'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'routes'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'contact'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/contact'</span>,
                    <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'__NAMESPACE__'</span> =&gt; <span class="hljs-string">'PhlyContact\Controller'</span>,
                        <span class="hljs-string">'controller'</span>    =&gt; <span class="hljs-string">'Contact'</span>,
                        <span class="hljs-string">'action'</span>        =&gt; <span class="hljs-string">'index'</span>,
                    ),
                ),
                <span class="hljs-string">'may_terminate'</span> =&gt; <span class="hljs-keyword">true</span>,
                <span class="hljs-string">'child_routes'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'process'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                        <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                            <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/process'</span>,
                            <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                                <span class="hljs-string">'action'</span> =&gt; <span class="hljs-string">'process'</span>,
                            ),
                        ),
                    ),
                    <span class="hljs-string">'thank-you'</span> =&gt; <span class="hljs-keyword">array</span>(
                        <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'Literal'</span>,
                        <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                            <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/thank-you'</span>,
                            <span class="hljs-string">'defaults'</span> =&gt; <span class="hljs-keyword">array</span>(
                                <span class="hljs-string">'action'</span> =&gt; <span class="hljs-string">'thank-you'</span>,
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
    <span class="hljs-comment">/* ... */</span>
);
</code></pre>
<p>Okay, that's interesting. I can define the captcha and options to use, the name
of the contact form, the mail transport I want to use, and even who the email
is sent from and who it goes to. In addition, it defines some routes.</p>
<p>I'll create a new file, <code>config/autoload/phly-contact.local.php</code>. This is a
local configuration file that will not be checked into my version control
system. Now, let's add some configuration. First, I'll configure my mail
transport.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'phly_contact'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'mail_transport'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'class'</span>   =&gt; <span class="hljs-string">'Zend\Mail\Transport\File'</span>,
            <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'path'</span> =&gt; <span class="hljs-string">'data/mail/'</span>,
            ),
        ),
    ),
);
</code></pre>
<p>I'm telling the module to use the <code>File</code> mail transport, and telling the
transport where I want messages written. By default, Zend Framework calls
<code>chdir()</code> to change directory to the project root, so I can reference a
directory relative to that. I'm simply going to write to a <code>data/mail/</code>
directory. Let's create that, and make it world-writable for now to ensure the
web server can write to it. (In production, you'd only want it writable by the
web server user.)</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ mkdir -p data/mail
$ chmod a+rwX data/mail
</code></pre>
<p>Now, let's change the base URL the contact form responds to; I want it to
respond to <code>/contact-us</code>. Another principle of re-usable modules in ZF2 is that
we recommend creating tree routes for each module, with the root of the tree
being a literal route. This makes it easy to alter the base for routing,
without needing to redefine all the routes in the module.</p>
<p>I'll add the following to my local configuration, then. I'll simply override
the parent route for my module, named &quot;contact&quot;, and point it at a different
URL.</p>
<pre><code class="language-php hljs php" data-lang="php">    <span class="hljs-string">'router'</span> =&gt; <span class="hljs-keyword">array</span>(
        <span class="hljs-string">'routes'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'contact'</span> =&gt; <span class="hljs-keyword">array</span>(
                <span class="hljs-string">'options'</span> =&gt; <span class="hljs-keyword">array</span>(
                    <span class="hljs-string">'route'</span> =&gt; <span class="hljs-string">'/contact-us'</span>,
                ),
            ),
        ),
    ),
</code></pre>
<p>Let's see if all this worked! Once again, I'll fire up PHP's built-in web
server.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ <span class="hljs-built_in">cd</span> public
$ php -S localhost:8080
</code></pre>
<p>Now, let's browse to <code>http://localhost:8080/contact-us</code> — looks good! Just as
an experiment, let's try the previously configured URL,
<code>http://localhost:8080/contact</code>. We get a 404 now!</p>
<p><img src="/images/screencasts/2012-09-19-zf2-module-screencast-03-config.png" alt="" /> <img src="/images/screencasts/2012-09-19-zf2-module-screencast-04-404.png" alt="" /></p>
<p>Now, let's submit the form. I'll fill in some information; it's asking for my
email address, a subject line, and a message, as well as for me to solve a
simple CAPTCHA. Once I've done all that, I can send it.</p>
<p>If all is well, we should now have a mail file in our data directory. Let's check.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ ls -l data/mail/
</code></pre>
<p>And now let's look at it.</p>
<pre><code class="language-bash hljs bash" data-lang="bash">$ cat data/mail/ZendMail_1347989389_1009740165.tmp
Date: Tue, 18 Sep 2012 12:29:49 -0500
From: me@mwop.net
Reply-To: me@mwop.net
Subject: [Contact Form] Suspense!

Suspenseful, isn<span class="hljs-string">'t it?
</span></code></pre>
<p>Looks good!</p>
<p>Zend Framework 2 provides a wonderful modular architecture that will enable an
ecosystem of 3rd party modules that should save you time and energy when
developing your applications. I've demonstrated a simple one, a contact form,
but many, many more already exist, and with a stable release now available, you
should see that number grow. This is truly a wonderful step forward for
developers, and I hope you find it as exciting as I do.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-09-19-zf2-module-screencast.html">ZF2 Modules Quickstart (Screencast)</a> was originally
    published <time class="dt-published" datetime="2012-09-19T13:10:00-05:00">19 September 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>On Microframeworks</title>
      <pubDate>Fri, 17 Aug 2012 11:00:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-08-17-on-microframeworks.html</link>
      <guid>https://mwop.net/blog/2012-08-17-on-microframeworks.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>A number of months ago, <a href="http://funkatron.com/">Ed Finkler</a> started a
discussion in the PHP community about <a href="http://microphp.org/">&quot;MicroPHP&quot;</a>; to
summarize, the movement is about:</p>
<ul>
<li>Building small, single-purpose libraries.</li>
<li>Using small things that work together to solve larger problems.</li>
</ul>
<p>I think there are some really good ideas that have come out of this, and also a
number of questionable practices<sup id="t1"><a href="#f1">1</a></sup>.</p>
<p>One piece in particular I've focussed on is the concept of so-called
“microframeworks”.</p>


<h2>What is a microframework?</h2>
<p>PHP has had microframeworks for quite some time<sup id="t2"><a href="#f2">2</a></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 <a href="http://www.sinatrarb.com">Sinatra</a>.</p>
<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
<a href="http://rubyonrails.org/">Ruby on Rails</a>, and relied on the fact that Ruby uses
the last value of a block as the return value.</p>
<p>As some simple examples:</p>
<pre><code class="language-ruby hljs ruby" data-lang="ruby">get <span class="hljs-string">'/hello/:name'</span> <span class="hljs-keyword">do</span> <span class="hljs-params">|n|</span>
    <span class="hljs-string">"Hello <span class="hljs-subst">#{n}</span>!"</span>
<span class="hljs-keyword">end</span>

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

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

get <span class="hljs-string">'/feed.?:format?'</span>, <span class="hljs-symbol">:provides</span> =&gt; [<span class="hljs-string">'rss'</span>, <span class="hljs-string">'atom'</span>, <span class="hljs-string">'xml'</span>] <span class="hljs-keyword">do</span>
    builder <span class="hljs-symbol">:feed</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>The language is expressive, and allows the developer to focus on two things:</p>
<ul>
<li>What are the specific entry points (URIs) for the application?</li>
<li>What needs to be done for each specific entry point?</li>
</ul>
<p>I'd argue that the above two points are the defining characteristics of modern
microframeworks. Typically, the entry points are given the term &quot;routing&quot;, and
the second corresponds to &quot;controllers&quot;.</p>
<h2>PHP implementations</h2>
<p>I'd argue one of the earliest microframework implementations, though it wasn't
termed as such, was <a href="http://dev.horde.org/routes/">Horde Routes</a><sup id="t3"><a href="#f3">3</a></sup>
(which was itself inspired by <a href="http://routes.readthedocs.org/en/latest/index.html">Python Routes</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.</p>
<p>Since around 2009, I've seen an increasing number of new PHP
microframeworks<sup id="t4"><a href="#f4">4</a></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:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-comment">/* Procedural */</span>
get(<span class="hljs-string">'/hello/:name'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($n)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello {$n}!"</span>;
});

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

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

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

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

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

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

$app-&gt;get(<span class="hljs-string">'/feed.?:format?'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($feed, $format)</span> <span class="hljs-title">use</span> <span class="hljs-params">($app)</span> </span>{
    <span class="hljs-keyword">return</span> $app-&gt;builder($feed, $format);
})-&gt;constraints([<span class="hljs-string">'format'</span> =&gt; <span class="hljs-string">'/^(rss|atom|xml)$/'</span>]);
</code></pre>
<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 &quot;params&quot; 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:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-comment">// Pass in route match parameters as an argument.</span>
$app-&gt;get(<span class="hljs-string">'/feed.:format'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($params)</span> </span>{
    $format = $params[<span class="hljs-string">'format'</span>];
});

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

<span class="hljs-comment">// Curry in the $app instance when desired, and </span>
<span class="hljs-comment">// retrieve route match parameters from it.</span>
$app-&gt;get(<span class="hljs-string">'/feed.:format'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> <span class="hljs-title">use</span> <span class="hljs-params">($app)</span> </span>{
    $format = $app-&gt;params(<span class="hljs-string">'format'</span>);
});
</code></pre>
<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:</p>
<pre><code class="language-php hljs php" data-lang="php">$app-&gt;get(<span class="hljs-string">'/feed.:format'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($app)</span> </span>{
    <span class="hljs-comment">// ...</span>
})-&gt;constraints([<span class="hljs-string">'format'</span> =&gt; <span class="hljs-string">'/^(atom|xml|json)$/'</span>])
  -&gt;name(<span class="hljs-string">'feed'</span>);
</code></pre>
<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 <code>urlTo()</code>, which
takes a route name, and an associative array of replacements.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">echo</span> $app-&gt;urlTo(<span class="hljs-string">'feed'</span>, [<span class="hljs-string">'format'</span> =&gt; <span class="hljs-string">'atom'</span>]);
</code></pre>
<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.</p>
<h2>What are they good for?</h2>
<p>In my research and experience, microframeworks have three typical use cases:</p>
<ol>
<li><strong>Prototyping.</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.</li>
<li><strong>APIs</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.</li>
<li><strong>Small, mostly static sites</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.</li>
</ol>
<h2>Where do microframeworks fail?</h2>
<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.).</p>
<p>Additionally, though many frameworks offer ways to alter the workflow of the
application either via hooks, events, or “middleware”<sup id="t5"><a href="#f5">5</a></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.</p>
<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:</p>
<ul>
<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.</li>
<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.</li>
<li>Many implement their own view layers.<sup id="t6"><a href="#f6">6</a></sup></li>
</ul>
<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, <code>Zend\View</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.</p>
<h2>An experiment</h2>
<p>Building on my last point, I looked at the APIs of
<a href="http://limonade-php.github.com/">Limonade</a> and
<a href="http://www.slimframework.com/">Slim Framework</a>, and built up a specification
for a microframework. I then matched as many pieces of it as possible to
existing components in <a href="http://packages.zendframework.com/">ZF2</a>, and started
building.</p>
<p>In a matter of a few hours, I had written up a complete test
suite<sup id="t7"><a href="#f7">7</a></sup> and all code for a microframework, featuring the
following (this is basically the testdox output from the unit test suite):</p>
<ul>
<li>Lazy loads request</li>
<li>Lazy loads response</li>
<li>Request is injectible</li>
<li>Response is injectible</li>
<li>Halt should raise halt exception</li>
<li>Response should contain status provided to halt</li>
<li>Response should contain message provided to halt</li>
<li>Stop should raise halt exception</li>
<li>Response should remain unaltered after stop</li>
<li>Redirect should raise halt exception</li>
<li>Redirect should set 302 response status by default</li>
<li>Redirect should set response status based on provided status code</li>
<li>Redirect should set location header</li>
<li>Map creates a segment route when provided with a string route</li>
<li>Map can receive a route object</li>
<li>Passing invalid route raises exception</li>
<li>Map can receive a callable</li>
<li>Passing invalid controller to route does not immediately raise exception</li>
<li>Accessing invalid controller raises exception</li>
<li>Passing invalid method to route via method raises exception</li>
<li>Can set methods route responds to singly</li>
<li>Can set methods route responds to as array</li>
<li>Can set methods route responds to as multiple arguments</li>
<li>Can specify additional method types to respond to</li>
<li>Can specify route name</li>
<li>Adding route using method type creates route that responds to that method type</li>
<li>Running with no matching routes raises page not found exception</li>
<li>Routing sets list of named routes</li>
<li>Routing sets lists of routes by method</li>
<li>Successful routing dispatches controller</li>
<li>Unsuccessful routing triggers 404 event</li>
<li>Calling halt triggers halt event</li>
<li>Invalid controller triggers 501 event</li>
<li>Exception raised in controller triggers 500 event</li>
<li>Can pass to next matching route</li>
<li>Url for helper assembles url based on name provided</li>
<li>Url for helper assembles url based on name and params provided</li>
<li>Url for helper assembles url based on current route match when no name provided</li>
<li>Composes logger instance by default</li>
<li>Can inject specific logger instance</li>
<li>Mustache view is used by default</li>
<li>Can inject alternate view instance</li>
<li>Render renders a template to the response</li>
<li>View model returns mustache view model by default</li>
<li>Subsequent calls to view model return separate instances</li>
<li>Can provide view model prototype</li>
</ul>
<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.</p>
<p>For the view, I used my own <a href="http://weierophinney.github.com/phly_mustache">phly_mustache</a>,
and provided a basic &quot;view model&quot; implementation that receives the application
instance, thus allowing the ability to call application helpers (such as url
generation).</p>
<p>To make installation simple, I used <a href="http://getcomposer.org">Composer</a> to
manage my dependencies on specific ZF2 components and for <code>phly_mustache</code>. The
microframework contains only the code it needs to get its work done, leveraging
the work of others whenever possible.</p>
<p>This post is not meant as a way to announce a new microframework,
however.<sup id="t8"><a href="#f8">8</a></sup> The point of the experiment was to prove something:
microframeworks are trivially easy to write, <em>particularly if you follow the
principals of MicroPHP, and re-use existing code</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
<em>writing awesome applications</em>.</p>
<h2>Lessons learned</h2>
<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.</p>
<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.</p>
<p>In sum: <em>Use the right tool for the job</em>. If you foresee expanding requirements
in your project's future, you may want to evaluate a full-stack
framework,<sup id="t9"><a href="#f9">9</a></sup> or consider building something robust that suits
your specific project's needs. Use microframeworks where and when they make
sense.</p>
<h4>Afterword</h4>
<p>I'm well aware that Fabien Potencier has written <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</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.</p>
<h4>Footnotes</h4>
<ul>
<li><sup id="f1"><a href="#t1">1</a></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.</li>
<li><sup id="f2"><a href="#t2">2</a></sup> In fact, my first foray into MVC in PHP was writing a
clone of Perl's <a href="http://cgi-app.org/">CGI::Application</a>, which in many ways
is also a microframework.</li>
<li><sup id="f3"><a href="#t3">3</a></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.</li>
<li><sup id="f4"><a href="#t4">4</a></sup> I swear, you see new ones on Github daily, and on
<a href="http://phpdeveloper.org/">PHP Developer</a> at least once a week.</li>
<li><sup id="f5"><a href="#t5">5</a></sup> <a href="http://www.slimframework.com">Slim</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.</li>
<li><sup id="f6"><a href="#t6">6</a></sup> <a href="http://www.slimframework.com">Slim</a> is an outlier here,
as it utilizes <a href="http://twig.sensiolabs.org/">Twig</a> by default.</li>
<li><sup id="f7"><a href="#t7">7</a></sup> I'm sure that my TDD experiment will warm the soul of
<a href="http://www.littlehart.net/atthekeyboard/">the Grumpy Programmer</a>.</li>
<li><sup id="f8"><a href="#t8">8</a></sup> That said, if you want to look at the results, you can
<a href="http://github.com/weierophinney/phlyty">find Phlyty on Github</a>.</li>
<li><sup id="f9"><a href="#t9">9</a></sup> As you may guess, I'm biased towards <a href="http://framework.zend.com/">Zend Framework</a>.
However, you should always carefully evaluate a framework against your
project's needs.</li>
</ul>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-08-17-on-microframeworks.html">On Microframeworks</a> was originally
    published <time class="dt-published" datetime="2012-08-17T11:00:00-05:00">17 August 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ZF2's New Controller::init()</title>
      <pubDate>Mon, 30 Jul 2012 21:00:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-07-30-the-new-init.html</link>
      <guid>https://mwop.net/blog/2012-07-30-the-new-init.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>In Zend Framework 1, controller's had an <code>init()</code> method, which was called
after the controller was instantiated. The reason for it was to encourage
developers not to override the constructor, and thus potentially break some of
the functionality (as a number of objects were injected via the constructor).
<code>init()</code> was useful for doing additional object initialization.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Zend_Controller_Action</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-comment">// do some stuff!</span>
    }
}
</code></pre>
<p>But this feature is missing from ZF2; how can we accomplish this sort of pattern?</p>


<h2>Constructor Overriding</h2>
<p>Why didn't we add the <code>init()</code> method in Zend Framework 2? Because we don't
have a constructor by default, and also to reduce overall method calls; if a
controller won't be overriding the method, there's no reason to make the call
in the first place. So, that means, in ZF2, unlike ZF1, to do the same thing,
you can simply define a constructor in your controller:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractActionController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractActionController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-comment">// do some stuff!</span>
    }
}
</code></pre>
<p>Except there's one specific and often-needed use case where this fails: if you
want to wire listeners to the controller's event manager.</p>
<h2>Events</h2>
<p>Why does this fail with the event manager? Because when we're in the
constructor, we don't yet have an <code>EventManager</code> instance! The event manager
instance is injected after instantiation. As such, we need to attach to it once
we know we have an event manager. Which is… when it's set. This can be done
very simply by overriding the <code>setEventManager()</code> method. In the next example,
we'll define a listener for the &quot;dispatch&quot; event that redirects if certain
criteria is not met.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">EventManager</span>\<span class="hljs-title">EventManagerInterface</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Mvc</span>\<span class="hljs-title">Controller</span>\<span class="hljs-title">AbstractActionController</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractActionController</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setEventManager</span><span class="hljs-params">(EventManagerInterface $events)</span>
    </span>{
        <span class="hljs-keyword">parent</span>::setEventManager($events);

        $controller = <span class="hljs-keyword">$this</span>;
        $events-&gt;attach(<span class="hljs-string">'dispatch'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($e)</span> <span class="hljs-title">use</span> <span class="hljs-params">($controller)</span> </span>{
            $request = $e-&gt;getRequest();
            $method  = $request-&gt;getMethod();
            <span class="hljs-keyword">if</span> (!in_array($method, <span class="hljs-keyword">array</span>(<span class="hljs-string">'PUT'</span>, <span class="hljs-string">'DELETE'</span>, <span class="hljs-string">'PATCH'</span>))) {
                <span class="hljs-comment">// nothing to do</span>
                <span class="hljs-keyword">return</span>;
            }

            <span class="hljs-keyword">if</span> ($controller-&gt;params()-&gt;fromRoute(<span class="hljs-string">'id'</span>, <span class="hljs-keyword">false</span>)) {
                <span class="hljs-comment">// nothing to do</span>
                <span class="hljs-keyword">return</span>;
            }

            <span class="hljs-comment">// Missing identifier! Redirect.</span>
            <span class="hljs-keyword">return</span> $controller-&gt;redirect()-&gt;toRoute(<span class="hljs-comment">/* ... */</span>);
        }, <span class="hljs-number">100</span>); <span class="hljs-comment">// execute before executing action logic</span>
    }
}
</code></pre>
<p>The beauty of this is that we only override when we need to, and we override in
the specific context we're trying to influence. Additionally, we're only
registering the event listener if this particular controller is instantiated —
which helps reduce our overall number of listeners, and thus shapes our call
graph based on the controller invoked.</p>
<h2>Other dependencies</h2>
<p>As you'll likely note, the event manager is not the only case where you may
need to follow a similar pattern. Any time your initialization logic may be
based on a dependency, you'll want to override the setter in which that
dependency is injected.</p>
<p><em>Got any ZF2 tips of your own to share? Blog them!</em></p>
<h2>Update: ServiceManager</h2>
<p>A few folks in the comments were remarking that the felt that omitting the
<code>init()</code> method makes it harder for developers to identify when and where to do
initialization logic, particularly when you may be working with multiple
dependencies.</p>
<p>Which made me realize there's another place I missed, one that's potentially
even better suited to initialization: the <code>ServiceManager</code>.</p>
<p>Basically, if you find yourself having complex initialization needs, or many
dependencies, you should be building a factory for your controller, and wiring
it to the <code>ServiceManager</code>. This can happen in one of several places, but my
preference is in my module's <code>Module</code> class, in the <code>getControllerConfig()</code>
method. This method returns configuration for the controller manager that
instantiates, validate, and injects controllers; it's basically a type of
<code>ServiceManager</code>, and, in fact, has access to the main application's instance.
I'll take the previous example, and wire it in the context of a factory:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>

<span class="hljs-title">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">EventManager</span>\<span class="hljs-title">EventManagerInterface</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Module</span>
</span>{
    <span class="hljs-comment">/*
     * Assume some other methods, such as getConfig(), etc.
     * Also assume that a route will return a controller named
     * "My\Controller\My" which we assume will reference a controller
     * within our current namespace.
     */</span>

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getControllerConfig</span><span class="hljs-params">()</span>
    </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>(<span class="hljs-string">'factories'</span> =&gt; <span class="hljs-keyword">array</span>(
            <span class="hljs-string">'My\Controller\My'</span> =&gt; <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($controllers)</span> </span>{
                $services   = $controllers-&gt;getServiceLocator();
                $controller = <span class="hljs-keyword">new</span> Controller\MyController();
                $events     = $services-&gt;get(<span class="hljs-string">'EventManager'</span>)

                $events-&gt;attach(<span class="hljs-string">'dispatch'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">($e)</span> <span class="hljs-title">use</span> <span class="hljs-params">($controller)</span> </span>{
                    $request = $e-&gt;getRequest();
                    $method  = $request-&gt;getMethod();
                    <span class="hljs-keyword">if</span> (!in_array($method, <span class="hljs-keyword">array</span>(<span class="hljs-string">'PUT'</span>, <span class="hljs-string">'DELETE'</span>, <span class="hljs-string">'PATCH'</span>))) {
                        <span class="hljs-comment">// nothing to do</span>
                        <span class="hljs-keyword">return</span>;
                    }

                    <span class="hljs-keyword">if</span> ($controller-&gt;params()-&gt;fromRoute(<span class="hljs-string">'id'</span>, <span class="hljs-keyword">false</span>)) {
                        <span class="hljs-comment">// nothing to do</span>
                        <span class="hljs-keyword">return</span>;
                    }

                    <span class="hljs-comment">// Missing identifier! Redirect.</span>
                    <span class="hljs-keyword">return</span> $controller-&gt;redirect()-&gt;toRoute(<span class="hljs-comment">/* ... */</span>);
                }, <span class="hljs-number">100</span>); <span class="hljs-comment">// execute before executing action logic</span>

                $controller-&gt;setEventManager($events);
                <span class="hljs-keyword">return</span> $controller;
            };
        ));
    }
}
</code></pre>
<p>The above will create the controller, grab an event manager instance, attach
the listener, and then inject the event manager into the controller. If you
wanted to do more complex work, you definitely could — and this would be the
place to do it.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-07-30-the-new-init.html">ZF2&#039;s New Controller::init()</a> was originally
    published <time class="dt-published" datetime="2012-07-30T15:40:00-05:00">30 July 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ZF2 Forms in Beta5</title>
      <pubDate>Thu, 05 Jul 2012 15:40:00 -0500</pubDate>
      <link>https://mwop.net/blog/2012-07-02-zf2-beta5-forms.html</link>
      <guid>https://mwop.net/blog/2012-07-02-zf2-beta5-forms.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>Forms are a nightmare for web development. They break the concept of separation
of concerns:</p>
<ul>
<li>They have a <em>display</em> aspect (the actual HTML form)</li>
<li>They have a <em>validation</em> aspect</li>
<li>And the two mix, as you need to display validation error messages.</li>
</ul>
<p>On top of that, the submitted data is often directly related to your domain
models, causing more issues:</p>
<ul>
<li>Not all elements will have a 1:1 mapping to the domain model — buttons,
CSRF protection, CAPTCHAs, etc. usually are application-level concerns, but
not domain issues.  Names valid for your domain model may not be valid
names for HTML entities.</li>
</ul>
<p>Add to this that the validation logic may be re-usable outside of a forms
context, and you've got a rather complex problem.</p>


<h2>Forms in ZF2</h2>
<p>Starting in 2.0.0beta4, we offerred a completely rewritten Form component. In
fact, it's not just a Form component — a new component, InputFilter, was also
added. InputFilter is a component that provides re-usable validation and
normalization logic, and can be used with forms or your domain model. The Form
component is basically a bridge between domain models/validation and the view
layer.</p>
<p>However, this means a bit more complexity for the end-user. You now must:</p>
<ul>
<li>Create your form, which consists of elements and fieldsets.</li>
<li>Create an input filter, consisting of inputs.</li>
<li>Inform the form of the input filter.</li>
</ul>
<p>It's a bit of work. And there's more: we wanted to simplify the process of
getting your validated values into your domain objects. For this, we added a
concept of <em>hydrators</em>, which map the validated form values to an object you
<em>bind</em> to the form. Now you have <em>three</em> pieces to keep track of — form (and
its elements), input filter (and its inputs), and a hydrator.</p>
<p>So, a few developers had an idea: use annotations on the domain model objects
to define these items, letting you keep it all in one place.</p>
<p>While I'm not normally a fan of annotations, I immediately saw the appeal in
this particular situation.</p>
<h2>An Example</h2>
<p>Let's consider a very simple example. The following domain object represents
data for a user, and includes a variety of elements we'd represent in a form.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">namespace</span> <span class="hljs-title">MyVendor</span>\<span class="hljs-title">Model</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Form</span>\<span class="hljs-title">Annotation</span>;

<span class="hljs-comment">/**
 * <span class="hljs-doctag">@Annotation</span>\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty")
 * <span class="hljs-doctag">@Annotation</span>\Name("user")
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>
</span>{
    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@Annotation</span>\Attributes({"type":"text" })
     * <span class="hljs-doctag">@Annotation</span>\Validator({"type":"Regex","options":{"regex":"/^[a-zA-Z][a-zA-Z0-9_-]{1,19}/"}})
     * <span class="hljs-doctag">@Annotation</span>\Options({"label":"Username:"})
     */</span>
    <span class="hljs-keyword">public</span> $username;

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@Annotation</span>\Required(false)
     * <span class="hljs-doctag">@Annotation</span>\Attributes({"type":"text" })
     * <span class="hljs-doctag">@Annotation</span>\Options({"label":"Your full name:"})
     */</span>
    <span class="hljs-keyword">public</span> $fullname;

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@Annotation</span>\Type("Zend\Form\Element\Email")
     * <span class="hljs-doctag">@Annotation</span>\Options({"label":"Your email address:"})
     */</span>
    <span class="hljs-keyword">public</span> $email;

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@Annotation</span>\Type("Zend\Form\Element\Url")
     * <span class="hljs-doctag">@Annotation</span>\Options({"label":"Your home page:"})
     */</span>
    <span class="hljs-keyword">public</span> $uri;
}
</code></pre>
<p>So, what does the above do?</p>
<ul>
<li>The &quot;name&quot; annotation gives a form or element a specific name.</li>
<li>The &quot;attributes&quot; annotation indicates what attributes to compose into the
form or element.</li>
<li>Similarly, the &quot;options&quot; annotation specifies options to compose into an
element. These typically include the label, but may include other
configuration that doesn't have an exact analog in the HTML attributes.</li>
<li>The &quot;validator&quot; annotation indicates a validator to compose for the input for
a given element. We also ship a &quot;filter&quot; annotation.</li>
<li>The &quot;type&quot; annotation indicates a class to use for that particular form or
element. In the specific cases used above, the elements actually provide
default filters and validators, simplifying setup further!</li>
<li>Last, but not least, the &quot;hydrator&quot; annotation indicates a
<code>Zend\Stdlib\Hydrator</code> implementation to use to relay data between the form
and the object. I'll cover this more shortly.</li>
</ul>
<p>So, let's now turn to creating a form and consuming it.</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">use</span> <span class="hljs-title">MyVendor</span>\<span class="hljs-title">Model</span>\<span class="hljs-title">User</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Zend</span>\<span class="hljs-title">Form</span>\<span class="hljs-title">Annotation</span>\<span class="hljs-title">AnnotationBuilder</span>;

$user    = <span class="hljs-keyword">new</span> User();
$builder = <span class="hljs-keyword">new</span> AnnotationBuilder();
$form    = $builder-&gt;createForm($user);

$form-&gt;bind($user);
$form-&gt;setData($dataFromSomewhere);
<span class="hljs-keyword">if</span> ($form-&gt;isValid()) {
    <span class="hljs-comment">// $user is now populated!</span>
    <span class="hljs-keyword">echo</span> $form-&gt;username;
    <span class="hljs-keyword">return</span>;
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// probably need to render the form now.</span>
}
</code></pre>
<p>You're not quite done, really — most likely, you'll need to include a submit
button of some sort, and it's always good practice to include a token to
prevent CSRF injections. But with the above, you've accomplished the major
headaches of setting up a form — and using the data — with minimal fuss.</p>
<h2>Much more!</h2>
<p>The form support in ZF2 offers a ton of other features, some of which are not
specific to forms even.</p>
<ul>
<li>
<p>ZF2 supports a variety of hydration strategies, which allow you to pass data
to and from objects. The example above uses one that suggests a 1:1 mapping
between the inputs and the object properties; other strategies include using
<code>ArrayObject</code>, using class mutator methods, and more.</p>
<p>At this point, you can hydrate an entire form, as well as individual fieldsets!</p>
</li>
<li>
<p>You can provide custom annotations. While this feature is not documented yet,
you can tell the <code>AnnotationBuilder</code> about additional annotation classes, as
well as provide listeners for those annotations so that they can interact
with the form construction process. As an example, one contributor has
already used these features to utilize <a href="http://doctrine-project.org">Doctrine</a>
annotations to inform the builder about the name of a property, as well as
indicate validators. (Side note: ZF2 now uses Doctrine's annotation syntax
and parser by default.)</p>
</li>
<li>
<p>There are a number of features targetting collections, so that your
client-side code can return arbitrary numbers of a specific fieldset type
(e.g., collecting addresses for an applicant), and the form will be able to
validate each. You can <a href="http://www.michaelgallego.fr/blog/?p=190">read more about those features from the author himself</a>.</p>
</li>
</ul>
<p>These features are all now available starting with the newly released
2.0.0beta5 version, which you can grab from the <a href="http://packages.zendframework.com/">ZF2 packages site</a>.</p>
<p>I'm really excited with the solutions we've created in ZF2, and even more
excited to see people put them to use!</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-07-02-zf2-beta5-forms.html">ZF2 Forms in Beta5</a> was originally
    published <time class="dt-published" datetime="2012-07-05T15:40:00-05:00">5 July 2012</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
  </channel>
</rss>
