<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Planet PHP</title><link rel="alternate" type="text/html" href="http://www.planet-php.net/"/><link rel="self" type="text/html" href="http://www.planet-php.net/atom/"/><subtitle>People blogging about PHP</subtitle><id>http://www.planet-php.net/</id><generator uri="http://planet-php.net/">
            Planet PHP Aggregator
            </generator><updated>2010-07-01T13:05:00Z</updated><link rel="hub" href="http://pubsubhubbub.appspot.com"/><entry><title type="text">Creating Zend_Tool Providers</title><link rel="alternate" type="text/html" href="http://weierophinney.net/matthew/archives/242-Creating-Zend_Tool-Providers.html" title="Creating Zend_Tool Providers"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~jvI" title="Shortlink to http://weierophinney.net/matthew/archives/242-Creating-Zend_Tool-Providers.html"/><author><name>Matthew Weier O'Phinney</name></author><id>http://weierophinney.net/matthew/archives/242-guid.html</id><updated>2010-07-01T13:05:00Z</updated><published>2010-07-01T13:05:00Z</published><content type="html"><![CDATA[
    <p>
    When I was at <a href="http://www.symfony-live.com/">Symfony Live</a> this
    past February, I assisted <a
        href="http://www.leftontheweb.com/">Stefan Koopmanschap</a>
    in a full-day workshop on integrating Zend Framework in Symfony
    applications. During that workshop, Stefan demonstrated creating Symfony
    "tasks". These are classes that tie in to the Symfony command-line
    tooling -- basically allowing you to tie in to the CLI tool in order to
    create cronjobs, migration scripts, etc.
</p>

<p>
    Of course, Zend Framework has an analogue to Symfony tasks in the <a
        href="http://framework.zend.com/manual/en/zend.tool.html">Zend_Tool</a>
    component's "providers". In this post, I'll demonstrate how you can create a
    simple provider that will return the most recent entry from an RSS or Atom
    feed. 
</p>
 <br /><a href="http://weierophinney.net/matthew/archives/242-Creating-Zend_Tool-Providers.html#extended">Continue reading "Creating Zend_Tool Providers"</a>
    ]]></content></entry><entry><title type="text">Switzerland, Microsoft and the JumpInCamp!</title><link rel="alternate" type="text/html" href="http://blog.echolibre.com/2010/04/switzerland-microsoft-and-the-jumpincamp/" title="Switzerland, Microsoft and the JumpInCamp!"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~jnY" title="Shortlink to http://blog.echolibre.com/2010/04/switzerland-microsoft-and-the-jumpincamp/"/><author><name>Echolibre</name></author><id>http://blog.echolibre.com/?p=898</id><updated>2010-04-15T16:13:00Z</updated><published>2010-04-15T16:13:00Z</published><content type="html"><![CDATA[<p style="text-align: justify;">As some of you may know from the tweets I’ve been posting for nearly 3 weeks now, I was invited to attend the very first edition of the <a title="Microsoft JumpInCamp" href="http://jumpincamp.com">JumpInCamp</a> organized by Microsoft in April 2010.</p>
<p style="text-align: justify;">The goal of this camp was to get the European PHP community leaders together and learn about the new products and new ideas Microsoft are working on. For those of you who read about the <a title="Microsoft Web Developer Summit" href="http://blog.echolibre.com/2009/12/microsoft-web-developer-summit/">Microsoft web developer summit</a> that took place in Redmond in December 2009 you might think it was the same thing however you would be utterly wrong.</p>
<p style="text-align: justify;">While the camp in Redmond was very informative and we are learnt a great deal of new features coming up with Microsoft, it was vastly different than the <a title="Microsoft JumpInCamp" href="http://jumpincamp.com">JumpinCamp</a> in Zurich where the focus of the camp was to get the developers to interact with the actual Microsoft developers instead of only learning about new features. The point of the JumpinCamp was to get your hands dirty in code so we all got a few hours of lectures, then sat down and worked on either implementing those solutions into our respective Open Source projects or even discussed and raised concerns we might have regarding some of their products.</p>
<p>I thought it might be nice to share some of the projects I’ve started working on while I was over there and what I had interests in:<br/><span id="more-898"/></p>
<h2 style="text-align: justify;">OData</h2>
<p style="text-align: justify;">After meeting with Claudio Caldato, the program manager for the Interoperability team, we went over the <a title="The Open Data Protocol" href="http://odata.org">OData</a> project and after looking at the position of <a title="The Open Data Protocol" href="http://odata.org">OData</a> and it’s potential, I decided to join the team and start by developing a <a title="PEAR PHP" href="http://pear.php.net">PEAR</a> package that will allow producers to publish valid OData <a title="Atom Pub" href="http://bitworking.org/projects/atom/rfc5023.html">Atom Pub feeds</a> and serve as a base driver for the PHP community (Which could be easily ported to <a title="Zend Framework" href="http://zendframework.com/">Zend Framework</a>, <a title="The Symfony Project" href="http://www.symfony-project.org/">Symfony</a>, <a title="Lithium Rad PHP Framework!" href="http://lithify.me">Lithium</a>, etc.)</p>
<p style="text-align: justify;">Obviously one of the reason for and OData producer package is to be able to make all the Frapi users potential OData producers. Moreover, as some of you know, sometimes I get into rants about web semantics and microformat. When I saw OData I realized that we could potentially bring some microformat standards within OData Atom Pub feeds (Or JSON Feeds).</p>
<p style="text-align: justify;">Another thing that lit me up was the JSON feed. As some of you may have read on this very blog a few months ago I wrote an article about having something called <a title="Practical Json Format Standard" href="http://blog.echolibre.com/2009/04/practical-json-format-standard/">PJSF</a> which basically is the concept or idea of defining a standard format for JSON feeds. When I saw that OData has the ability to generate JSON feeds, I obviously jumped on the occasion of making a difference in the semantics world <img src="http://blog.echolibre.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley"/></p>
<h2 style="text-align: justify;">Azure</h2>
<p style="text-align: justify;"><a title="Microsoft Azure" href="http://www.microsoft.com/windowsazure/ ">Azure</a> basically is a platform that offers a flexible, familiar environment for developers to create cloud applications and services. With Windows Azure, you can shorten your time to market and adapt as demand for your service grows.</p>
<p style="text-align: justify;">What does is really mean? Azure is an <strong>all-in-one cloud solution</strong>. Even though the concepts are a bit arduous to grasp, we can all thank <a title="Josh Holmes Blog And Azure Resource" href="http://www.joshholmes.com/blog/">Josh Holmes</a> and <a title="Maarten Balliauw Blog" href="http://blog.maartenballiauw.be">Maarten Balliauw</a> for their essential presence at this camp to help us with all the questions we had and their thorough understanding of their baby (Azure).</p>
<p style="text-align: justify;">Azure was another thing that sprung to my mind for <a title="Frapi Open Source API Framework" href="http://getfrapi.com">Frapi</a>. What if we could get our Frapi customers to be deployed directly into the cloud? Obviously it’s possible to hack around all the possible Amazon web services and to get somewhat arranged so our customers woul</p><p><i>Truncated by Planet PHP, read more at <a href="http://blog.echolibre.com/2010/04/switzerland-microsoft-and-the-jumpincamp/">the original</a> (another 4879 bytes)</i></p>]]></content></entry><entry><title type="text">Using PHP DOM With XPath</title><link rel="alternate" type="text/html" href="http://www.a-basketful-of-papayas.net/2010/04/using-php-dom-with-xpath.html" title="Using PHP DOM With XPath"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~jnd" title="Shortlink to http://www.a-basketful-of-papayas.net/2010/04/using-php-dom-with-xpath.html"/><author><name>Thomas Weinert</name></author><id>http://www.a-basketful-of-papayas.net/2010/04/using-php-dom-with-xpath.html</id><updated>2010-04-10T10:54:00Z</updated><published>2010-04-10T10:54:00Z</published><content type="html"><![CDATA[<p>Often I hear people say "We use SimpleXML, because DOM is so noisy and complex". Well, I don't think so. This article explains how you can parse a XML (an Atom feed) using the PHP DOM extension. No other libraries are involved.</p>

<h3>Load the feed</h3>
<p>To load the feed, you need to create an new DOMDocument document using it's load() method. This works with the PHP stream wrappers, so you can load local files or urls. DOMdocument, has dedicated methos for XML strings and html files and strings, too.</p>
<p>
<code>
$feed = new DOMDocument();<br/>
$feed->load('http://www.a-basketful-of-papayas.net/feeds/posts/default');<br/>
...<br/></code>
</p>
<p>If here is any problem with the resource, PHP will output error messages. You can use <tt>libxml_use_internal_errors()</tt> to block them. With <tt>libxml_clear_errors()</tt> the internal error list is cleared, <tt>libxml_get_errors()</tt> returns them so you could implemented you own error handling. Just ignore them for now:</p>
<p><code>
$errorSetting = libxml_use_internal_errors(TRUE);<br/>
$feed = new DOMDocument();<br/>
$feed->load('http://www.a-basketful-of-papayas.net/feeds/posts/default');<br/>
libxml_clear_errors();<br/>
libxml_use_internal_errors($errorSetting);<br/>
...<br/></code></p>
<p>In the next step you should check if you got some content. I use the documentElement property for this. If it is not here, the feed has to be invalid because any XML needs at least one element node.</p>
<p><code>
if (isset($feed->documentElement)) {<br/>
  ...<br/>
} else {<br/>
  echo 'Invalid feed.';<br/>
}<br/></code></p>
<h3>Initialize XPath</h3>
<p>Now a XPath object is needed to execute expressions. Atom feeds make use of namespaces, often declaring the atom namespace as default. But in XPath you have no default namespace, you need to register the namespace with an arbitrary prefix. It does not have to be the same prefix used in the XML file. It can't for the default namespace obviously because it has no prefix in the XML file.</p>
<p><code>
...<br/>
$xpath = new DOMXPath($feed);<br/>
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');<br/>
...<br/></code></p>
<p>If you load html into the DOMDocument using the special methods, all namespaces are ignored. You can skip the registration in this case.</p>

<h3>Executing XPath Expressions</h3>
<p>The DOMXPath object has two methods for executing xpath expressions. One is <tt>query()</tt>, it always returns a DOMNodelist. You should use the second one: <tt>evaluate()</tt>. It will return DOMNodelist objects by default, but depending on the expression it can return other types, too. With <tt>evaluate()</tt> you have direct access to the title text, it will return an empty string if the feed has no title.</p>
<p>The code selects the element nodes in the registered namespace and casts them to string.</p>
<p><code>
...<br/>
echo $xpath->evaluate('string(/atom:feed/atom:title)'), "\n";<br/>
echo $xpath->evaluate('string(/atom:feed/atom:subtitle)'), "\n";<br/>
...<br/></code></p>
<p>Next we will loop over all entries. A DOMNodelist works with foreach, the expression will return an empty list if it does not match, so no additional checking is needed. Inside the loop the entry node is used as a context argument for <tt>evaluate()</tt>.</p>
<p><code>
...<br/>
foreach ($xpath->evaluate('//atom:entry') as $entryNode) {<br/>
  echo $xpath->evaluate('string(atom:title)', $entryNode), "\n";<br/>
  echo $xpath->evaluate(<br/>
    'string(atom:link[@rel="alternate" and @type="text/html"][1]/@href)',<br/>
    $entryNode<br/>
    ), "\n";<br/>
  echo "\n";<br/>
}<br/>
...<br/></code></p>

<h3>Conditions</h3>

<p>XPath expression can be conditions. It can be used to check if a entry has categories (tags). The return value of the following expression is a boolean value.</p>
<p><code>
...
if ($xpath->evaluate('count(atom:category) > 0', $entryNode)) {
  ...
}
...
</code></p>

<h3>Loop over attributes</h3>

<p>Each entry can have several categories. The title of the category is in it's attribute "term". You can select these attributes directly into a list.</p>
<p><code>
echo 'Categories: ';<br/>
foreach ($xpath->evaluate('atom:category/@term', $entryNode) as $index => $categoryAttribute) {<br/>
  if ($index > 0) {<br/>
    echo ', ';<br/>
  }<br/>
  echo $categoryAttribute->value;<br/>
}<br/>
echo "\n";<br/></code></p>

<h3>Complete Example</h3>
<p>Here is the full script. Be aware that it outputs text. If you execute it using a webserver (and not the command line), you should add a <tt>header('Content-Type: text/plain')</tt> to the top.</p>
<p><code>
&lt;?php<br/>
$errorSetting = libxml_use_internal_errors(TRUE);<br/>
$feed = new DOMDocument();<br/>
$feed->load('http://www.a-basketful-of-papayas.net/feeds/posts/default');<br/>
libxml_clear_errors();<br/>
libxml_use_internal_errors($erro</code></p><p><i>Truncated by Planet PHP, read more at <a href="http://www.a-basketful-of-papayas.net/2010/04/using-php-dom-with-xpath.html">the original</a> (another 2150 bytes)</i></p>]]></content></entry><entry><title type="text">Pirum, the Simple PEAR Channel Server Manager</title><link rel="alternate" type="text/html" href="http://fabien.potencier.org/article/38/pirum-the-simple-pear-channel-server-manager" title="Pirum, the Simple PEAR Channel Server Manager"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~i9Y" title="Shortlink to http://fabien.potencier.org/article/38/pirum-the-simple-pear-channel-server-manager"/><author><name>Fabien Potencier</name></author><id>http://fabien.potencier.org/article/38/pirum-the-simple-pear-channel-server-manager</id><updated>2009-11-28T07:50:00Z</updated><published>2009-11-28T07:50:00Z</published><content type="html"><![CDATA[
    <p>Some weeks ago during the Zend Conference, I
<a href="http://twitter.com/fabpot/status/4969508481">quietly</a> released
<a href="http://www.pirum-project.org/">Pirum</a>, a simple PEAR channel server manager.
As some people talk about it on "social
<a href="http://twitter.com/s_bergmann/statuses/6121431277">networks</a>", I thought I
should write an official announcement on my blog to explain where I come from.</p>

<p>A PEAR channel server allows you to install PEAR packages with the PEAR
command line. You are probably already familiar with it as it comes bundled
with most PHP installations:</p>

<pre class="command-line"><code>$ pear install ...
</code></pre>

<p>Pirum comes from my frustration with the current state of PEAR channel
servers. Beside big Open-Source projects like
<a href="http://www.symfony-project.org/">symfony</a>, I'm also responsible for smaller
projects (like <a href="http://www.twig-project.org/">Twig</a>, or <a href="http://www.swiftmailer.org/">Swift Mailer</a>).
But for all my software, I like to provide different way
of installing them: directly from SVN via <code>svn:externals</code>,
from my <a href="http://www.github.com/fabpot">Git</a> mirrors, from an
archive to download, or with the PEAR command line.</p>

<p>Except for the PEAR package installation, the other ones are quite easy to
setup and automate. But providing a PEAR channel proves to be more involving.
The only serious PEAR channel server I'm aware of is
<a href="http://greg.chiaraquartet.net/archives/123-Setting-up-your-own-PEAR-channel-with-Chiara_PEAR_Server-the-official-way.html">Chiara_PEAR_Channel</a>
from Greg Beaver. This is the software I used for symfony for four years. It
works really well, but is a bit cumbersome to setup for smaller projects (it
needs a database, and you need to configure some categories, the contributors
for the project, and more). That's fine for <a href="http://pear.php.net">PEAR</a>
itself, but frankly, for the rest of us, that's just too much.</p>

<p>As a matter of fact, hosting a PEAR channel server is super simple. It's all
about static files. That's right, even if you need some sort of PHP scripts to
maintain a PEAR channel server, the frontend used by the PEAR command line
tool can only be static files (mainly XML ones). And <code>Chiara_PEAR_Server</code>
works exactly like this. The backend, done in PHP, is where you maintain your
packages, and it generates the frontend, a bunch of static files for the
frontend. That's a really great architecture as it allows to scale very
easily. For instance, you should probably be able to host a PEAR channel
server on a CDN line Amazon S3 in a matter of minutes.</p>

<p>Thanks to this decoupled and simple architecture, I wrote some PHP scripts to
manage a PEAR channel server for the symfony
<a href="http://www.symfony-project.org/plugins/">plugins</a> two years ago.</p>

<p>The idea for Pirum came when I started the
<a href="http://www.twig-project.org/">Twig</a> project. Obviously, I wanted a PEAR
channel server for Twig, but I really did not want to use
<code>Chiara_PEAR_Server</code>. So I started to hack my own and Pirum was born.</p>

<p>Pirum lets you setup PEAR channel servers in a matter of minutes. Pirum is
best suited when you want to create small PEAR channels for a few packages
written by a few developers.</p>

<p>Pirum consists of just one file, a command line tool, written in PHP. There is
no external dependencies, no not need for a database, no need to setup
credentials, and nothing need to be installed or configured.</p>

<p>Installing Pirum is as simple as downloading the
<a href="http://github.com/fabpot/Pirum/raw/master/pirum">pirum</a> file and saving it
where you see fit.</p>

<blockquote class="note"><p>
  Of course, Pirum itself uses Pirum to provide a PEAR channel
  <a href="http://pear.pirum-project.org/">server</a> for itself!</p>
</blockquote>

<p>Even if Pirum only consists of just one file, it comes with a lot of great
features:</p>

<p>Besides its size and simplicity, Pirum is packed with a lot of features:</p>

<ul>
<li><p>It creates a full-featured PEAR channel server useable by any PEAR CLI;</p></li>
<li><p>Each channel has an html page describing the server and the packages it
hosts;</p></li>
<li><p>New releases can be tracked by subscribing to an Atom feed.</p></li>
</ul>

<p>Of course, it also comes with some limitations:</p>

<ul>
<li><p>No support for fallback PEAR channel servers;</p></li>
<li><p>No category management (all packages are under a "default" category);</p></li>
<li><p>No web interface for managing the packages.</p></li>
</ul>

<p>You can find more information about using Pirum on its official
<a href="http://www.pirum-project.org/">website</a>.</p>

<p>Pirum is already used by the following Open-Source projects:</p>

<ul>
<li><p><a href="http://www.symfony-project.org/">Symfony</a></p></li>
<li><p><a href="http://pear.phpunit.de/">PHPUnit</a></p></li>
<li><p><a href="http://www.swiftmailer.org/">Swift Mailer</a></p></li>
<li><p><a href="http://www.twig-project.org/">Twig</a></p></li>
<li><p><a href="http://www.fluentdom.org/">FluentDOM</a></p></li>
<li><p><a href="http://www.pirum-project.org/">Pirum</a></p></li>
</ul>

<p>I hope that with Pirum, more Open-Source projects will start providing a PEAR
channel as a mean to install their software. If you start using Pirum for your
project, please send me an email so that I can update the list on the Pirum
website.</p>
  ]]></content></entry><entry><title type="text">POST vs. PUT</title><link rel="alternate" type="text/html" href="http://benramsey.com/archives/post-vs-put/" title="POST vs. PUT"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~i7U" title="Shortlink to http://benramsey.com/archives/post-vs-put/"/><author><name>Ben Ramsey</name></author><id>http://benramsey.com/archives/post-vs-put/</id><updated>2009-11-09T16:07:00Z</updated><published>2009-11-09T16:07:00Z</published><content type="html"><![CDATA[	<p>This morning, <a href="http://weierophinney.net/matthew/archives/228-Building-RESTful-Services-with-Zend-Framework.html">Matthew</a> writes about building <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">RESTful</a> services with the Zend Framework. I have a lot of thoughts on his post, and I might blog more about it later, but right now, I want to focus on <a href="http://weierophinney.net/matthew/archives/228-Building-RESTful-Services-with-Zend-Framework.html#c24586">David’s comment</a>:</p>

	<blockquote>
		<p>I think the next thing you should cover is how to retrieve put parameters and maybe even attempt to start a discussion on the different school of thoughts about POST vs PUT (Especially in the PHP world).</p>
	</blockquote>

	<p>I know I’m even guilty of mentioning different schools of thought on POST vs. PUT in my talks, but the truth is that REST doesn’t specify what to use for what actions. These are defined by HTTP and not by REST.</p>

	<p><a href="http://roy.gbiv.com/untangled/2009/it-is-okay-to-use-post">Roy Fielding</a> has this to say about the use of HTTP verbs in RESTful applications:</p>

	<blockquote>
		<p>Some people think that REST suggests not to use POST for updates. Search my dissertation and you won’t find any mention of CRUD or POST. The only mention of PUT is in regard to HTTP’s lack of write-back caching. The main reason for my lack of specificity is because the methods defined by HTTP are part of the Web’s architecture definition, not the REST architectural style. Specific method definitions (aside from the retrieval:resource duality of GET) simply don’t matter to the REST architectural style, so it is difficult to have a style discussion about them. The only thing REST requires of methods is that they be uniformly defined for all resources (i.e., so that intermediaries don’t have to know the resource type in order to understand the meaning of the request). As long as the method is being used according to its own definition, REST doesn’t have much to say about it.</p>
	</blockquote>

	<p>The POST vs. PUT debate, however, does rage on in different communities, and some protocols have defined their usage. For example, the Atom Publishing Protocol (<a href="http://tools.ietf.org/html/rfc5023">RFC 5023</a>) explicitly states in section 4.3 that “POST is used to create” and “PUT is used to edit.”</p>

	<p>The important thing to note is that REST doesn’t care how the HTTP verbs are used, as long as they are used properly according to how they are defined in the protocol you are using.</p>

	<p>For those interested, HTTP (<a href="http://tools.ietf.org/html/rfc2616">RFC 2616</a>) defines POST by saying:</p>

	<blockquote>
		<p>The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. […] The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.</p>
	</blockquote>

	<p>PUT is defined as:</p>

	<blockquote>
		<p>The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.</p>
	</blockquote>

	<p>With this line of thinking, you might come to the conclusion that POST is used for creation of a subordinate resource, while PUT could be used for both creation or modification of a resource. The important distinction is that POST identifies the resource for which the entity should be considered a subordinate; PUT does not.</p>


 <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/ramsey?a=ISVmsCejV8s:jRe2zK77SdU:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/ramsey?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ramsey?a=ISVmsCejV8s:jRe2zK77SdU:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/ramsey?i=ISVmsCejV8s:jRe2zK77SdU:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ramsey?a=ISVmsCejV8s:jRe2zK77SdU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/ramsey?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/ramsey?a=ISVmsCejV8s:jRe2zK77SdU:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/ramsey?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/ramsey/~4/ISVmsCejV8s" height="1" width="1"/>]]></content></entry><entry><title type="text">The Mysteries Of Asynchronous Processing With PHP - Part 1: Asynchronous Benefits, Task Identification and Implementation Methods</title><link rel="alternate" type="text/html" href="http://blog.astrumfutura.com/archives/417-The-Mysteries-Of-Asynchronous-Processing-With-PHP-Part-1-Asynchronous-Benefits,-Task-Identification-and-Implementation-Methods.html" title="The Mysteries Of Asynchronous Processing With PHP - Part 1: Asynchronous Benefits, Task Identification and Implementation Methods"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~i19" title="Shortlink to http://blog.astrumfutura.com/archives/417-The-Mysteries-Of-Asynchronous-Processing-With-PHP-Part-1-Asynchronous-Benefits,-Task-Identification-and-Implementation-Methods.html"/><author><name>P&#xE1;draic Brady</name></author><id>http://blog.astrumfutura.com/archives/417-guid.html</id><updated>2009-09-27T14:02:00Z</updated><published>2009-09-27T14:02:00Z</published><content type="html"><![CDATA[
    Imagine a world where clients will give up on receiving responses from your application in mere seconds, where failed emails will give rise to complaints and lost business, where there exist tasks that must be performed regularly regardless of how many requests your application receives. This is not a fantasy world, it's reality. In the real world your application must be responsive, reliable and capable of recovery from errors. These are obvious needs but all too often applications fail to realise them. Sometimes, developers even fail to realise they should even be concerned about them.<br/><br/>
To offer an opening real-world example, I'll borrow from a recent discussion I had concerning the Pubsubhubbub Protocol. If you are unfamiliar with Pubsubhubbub (PuSH), it's a protocol which implements a publish-subscribe model where the publishers of RSS and Atom feeds can "push" updates to a group of Subscribers. The pushing is handled by an intermediary called a Hub which is pinged by the Publisher when they update a feed, and which then distributes the update to many Subscribers using a Callback URL they each have declared.<br/><br/>
In that discussion, the original poster was having a problem. Whenever a Hub sent his Subscriber implementation an update, it seemed to do it repetitively for some mysterious reason. Eventually, the problem was identified. The Hub implements a five second timeout. If, after five seconds, the update request was not completed because the Subscriber failed to send a valid response, it was assumed to have failed. The Hub would then attempt it again, and again, until finally its configured number of retries was used up.<br/><br/>
Why was the five second timeout being exceeded by the Subscriber? What was taking it so long in returning a response and finishing the request? You see, the Subscriber was not simply acknowledging the receipt of an update as demanded by the protocol, it was actually processing the entire update for its own use including a number of potentially expensive database operations before it completed the request. This was taking more than five seconds.<br/><br/>
Here's the problem in a nutshell. The Subscriber was performing work that had absolutely nothing to do with returning a response to the Hub and it was having an impact on the time it took to complete the request. The Hub couldn't care less about the Subscriber's processing, it was expecting a quick confirmation that the update was received. Instead, the Subscriber was effectively making it wait while it did something completely unrelated to that response. Using Asynchronous Processing, the Subscriber should have offloaded the feed processing elsewhere leaving it free to quickly respond to the Hub.<br/><h3>What is Asynchronous Processing?</h3><br/>
Asynchronous processing is a method of performing tasks outside the loop of the current request. Basically, you offload the task to another process, leaving the process serving the request free to respond quickly and without delay. Of course, not all tasks are caused by a request. Some can performed without a request trigger, like some forms of maintenance or log parsing.<br/><br/>
Implementing asynchronous processing can take a few directions:<br/><br/>
1. A parent process can spawn a child process to complete a task in the background allowing the parent process continue uninterrupted.<br/>
2. You could add tasks to a Job Queue (or even Message Queue) relying on a background daemon or scheduled process to perform batch processing of outstanding tasks in the queue.<br/>
3. You could simply have a scheduled standalone task without the queue, and which is performed regardless of what  requests are received.<br/><br/>
There are, I'm sure, many more variations. Most readers will recognise at least one of these (hint: cron <img src="http://blog.astrumfutura.com/templates/default/img/emoticons/wink.png" alt=";-)" style="display: inline; vertical-align: bottom;" class="emoticon"/>). Once you understand the nature of asynchronous processing you can find many uses for it in the most unlikely of places.<br/><h3>What Problems Does Asynchronous Processing Solve?</h3><br/>
Our example demonstrates that resource intensive tasks can be detrimental to responsiveness, so much so that it can can become detrimental in turn to the client, whether it be a machine applying a configured timeout and being forced into retrying the same request over and over, or whether it be an actual person who has to stare at a blank page as the seconds tick by.<br/><br/>
Resource intensive tasks are not the only ones worth applying asynchronous processing to, though they are likely the most obvious given their impact on clients. Most tasks worth offloading can be grouped into categories:<br/><br/>
1. Tasks which are resource intensive, i.e. needing a lot of CPU cycles or memory to complete which will add to server load and delay client responses.<br/>
2. Tasks whi<p><i>Truncated by Planet PHP, read more at <a href="http://blog.astrumfutura.com/archives/417-The-Mysteries-Of-Asynchronous-Processing-With-PHP-Part-1-Asynchronous-Benefits,-Task-Identification-and-Implementation-Methods.html">the original</a> (another 8273 bytes)</i></p>]]></content></entry><entry><title type="text">What Do You Develop On?</title><link rel="alternate" type="text/html" href="http://blog.stuartherbert.com/php/2009/09/11/what-do-you-develop-on/" title="What Do You Develop On?"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~i0j" title="Shortlink to http://blog.stuartherbert.com/php/2009/09/11/what-do-you-develop-on/"/><author><name>Stuart Herbert</name></author><id>http://blog.stuartherbert.com/php/?p=156</id><updated>2009-09-11T13:25:00Z</updated><published>2009-09-11T13:25:00Z</published><content type="html"><![CDATA[<p>At work, we have quite a variety of kit that we use for development:</p>
<ol>
<li>Cheap and cheerful desktop machines w/ multiple monitors and plenty of RAM, normally with AMD CPUs. These machines mostly run some form of Linux … Ubuntu and Debian are both popular.</li>
<li>Various laptops, a fair mix of MacBook Pros and other kit running Linux.</li>
<li>Virtual machines running on the desktops and laptops, used for cross-browser testing.</li>
<li>Virtual machines running on HP servers and blades, used for system testing, release testing and production.</li>
</ol>
<p>It gives us a lot of flexibility, allows us to develop and test on standards-compliant environments (but still use Windows for testing IE), and most of the time the developer is the bottleneck not the equipment <img src='http://blog.stuartherbert.com/php/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Recently, I’ve added both a netbook and an Atom-based mini-itx machine into the mix, and this blog post is my attempt to recommend that you consider doing the same.</p>
<p>Netbooks are incredibly popular in the wider computer-owning population. Over here in the UK, they come free with many mobile broadband packages, making them cheaper than many low-end laptops. They’re sold in the supermarket and the high street. Their small form factor and relative lightweight makes them appealing to people who would never willingly cart a traditional laptop around. And they run Windows, which most people are familiar with.</p>
<p>After an initial explosion of innovation, the specs have settled around a 1.6GHz Atom processor, 1 GB of RAM and a 10″ 1024×600 resolution screen. That’s not a lot of power, and it isn’t a lot of screen estate. How do your websites look on a netbook? Does your home page or your landing pages make an impact at that size, or is your site’s message partially or completely below the fold? How do the rest of the pages look? If you’re creating an app, does the user have enough of a working area to comfortably do their tasks? Try using Google Reader or Zimbra on a netbook to see examples of what to avoid.</p>
<p>And how do your websites run on a netbook? Too much Javascript, and the pages won’t be snappy. The CPU won’t keep up, and the different latencies and throughput of mobile broadband make round-trips back to the server much more noticeable. Javascript that fires at regular intervals (e.g. rotating marketing spotlight images) can force the CPU to switch execution speeds, and so drain the netbook’s battery much quicker.</p>
<p>Testing on a netbook is one way you can spot and deal with these problems before your customers do.</p>
<p><em>Stuart is running a course in Manchester in October immediately before the PHPNW09 conference on how to setup and organise your PHP developers to ensure things run smoothly for you and your customers. <a href="http://www.methodosity.com/2009-oct/what.php">Learn more about the course</a>, or <a href="http://www.methodosity.com/2009-oct/signup.php">sign-up now</a>.</em></p>
]]></content></entry><entry><title type="text">Zend_Feed_Writer and Zend_PubSubHubbub In Proposal Queue</title><link rel="alternate" type="text/html" href="http://blog.astrumfutura.com/archives/409-Zend_Feed_Writer-and-Zend_PubSubHubbub-In-Proposal-Queue.html" title="Zend_Feed_Writer and Zend_PubSubHubbub In Proposal Queue"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~iUe" title="Shortlink to http://blog.astrumfutura.com/archives/409-Zend_Feed_Writer-and-Zend_PubSubHubbub-In-Proposal-Queue.html"/><author><name>P&#xE1;draic Brady</name></author><id>http://blog.astrumfutura.com/archives/409-guid.html</id><updated>2009-07-19T15:03:00Z</updated><published>2009-07-19T15:03:00Z</published><content type="html"><![CDATA[
    I have a few proposals with Zend Framework. I also have an established record of not finishing them very reliably, yay! Ok, so that's not a good thing. I seem to have established a weird tradition of finding myself in just the right scenario at the completely wrong time to hold me up. Luckily (it's a bit like thinking THIS year will see a real Summer in Ireland), I do have oddles of time to burn right now. The ZF book is finally climbing Reboot Hill (the translated versions are progressing, and I will get to the next chapter soon - lots happened in the ZF since the drafts were written). Zend_Feed_Reader is in the ZF trunk, and definitely will be in 1.9. Zend_Oauth has been reviewed by me and patches are incoming in the next day to finish it (that should make it's way into 1.10 along with Zend_Crypt).<br/><br/>
Before this all goes sour and I a) wind up hospitalised after a freak accident involving Stephen Fry running me down while sending a Tweet on an iphone, b) see Eircom attacked by mysterious hackers intent on the downfall of Brian Cowen because he shows his appreciation for free speech by introducing legislation with the new criminal act of "blasphemy" defined or c) I'm abducted by Kerrymen (just because...well...they're all mad down there), I've started pounding frantically on my keyboard for a new proposal called Zend_Feed_Writer.<br/><br/>
ZFW is the counterpart to Zend_Feed_Reader (as if that wasn't obvious). It's purpose is to, once again, offer an alternative to the current Zend_Feed component using similar principles to those applied in Zend_Feed_Reader:<br/><br/>
1. Use a simple, intuitive and limited API to eliminate guesswork and uncertainty.<br/>
2. Utilise PHP's DOM to handle the complex internal construction of feeds.<br/>
3. Adhere to standards: RSS 2.0 (based on the RSS Advisory Board 2.0.11 spec) and Atom 1.0 (RFC 4287)<br/>
4. Behind the scenes, implement support for commonly used RSS/Atom modules like Dublin Core/Slash/Atom Threads<br/>
5. Allow users to implement/register Extensions (i.e. plugins) to add support for other modules<br/>
6. Liberally throw tests at every conceivable (including the possibly insane) scenario for use.<br/><br/>
Just like Zend_Feed_Reader, there is obviously a question mark. Do we even need an alternative to Zend_Feed? ZFR had the major advantage that it was conceived of not only as a major simplification making developer's lives significantly easier, but also as something that understood feeds - it was able to sift through numerous alternatives for commonly queried data points until it found a match, removing the need for developers to take on that role with custom abstraction layers and interpretive work. Zend_Feed_Writer does something similar, only in reverse. It creates feeds based on the most commonly inputted data points which contain the most logical or specification defined elements. It removes the guesswork, the need to cram up on the RSS/Atom standards, the specifications and the specs for all the different modules used. It eliminates work - and that's always been the main goal. If you want to learn a bit more - look at the Zend Framework 1.9 Preview, and compare the documentation for Zend_Feed with that for Zend_Feed_Reader. It should highlight where both diverge in a meaningful way.<br/><br/>
I'm currently drafting the Zend_Feed_Writer proposal over at <a href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Feed_Writer+-+Padraic+Brady">Zend_Feed_Writer - Padraic Brady</a>.<br/><br/>
Which brings us to upcoming proposal number two, the colourfully named Zend_PubSubHubbub! Or Zend_Feed_PubSubHubbub depending on which name is most appropriate.<br/><br/>
To explain, PubSubHubbub defines a protocol where any subscriber (that's you) can subscribe to a hub server which notifies you when any feed you want to follow has changed. Wait for it... Publishers, the origin of the RSS/Atom feeds you want to follow, can then notify their hub server which in turn notifies you. It's a push system. Publisher adds new content, and notifies Hub immediately. The Hub can then push the update to you right away. There is no polling every 30 mins for new content - it's delivered to you, or you are told where to fetch it from, right away. It eliminates the delay between source and polling, the lack of which has given services like Twitter a major advantage in getting news/articles/videos out to hundreds of people almost instantaneously and seen traditional feeds lose some of their attraction. As the PubSubHubbub team put it:<br/><br/><blockquote>A simple, open, server-to-server web-hook-based pubsub (publish/subscribe) protocol as an extension to Atom.<br/><br/>
Parties (servers) speaking the PubSubHubbub protocol can get near-instant notifications (via webhook callbacks) when a topic (Atom URL) they're interested in is updated.<br/><br/>
The protocol in a nutshell is as follows:<br/><br/><strong> An Atom URL (a "topic")</strong></blockquote><p><i>Truncated by Planet PHP, read more at <a href="http://blog.astrumfutura.com/archives/409-Zend_Feed_Writer-and-Zend_PubSubHubbub-In-Proposal-Queue.html">the original</a> (another 3321 bytes)</i></p>]]></content></entry><entry><title type="text">Zend_Feed_Reader promoted to Zend Framework trunk (watch out for ZF 1.9!)</title><link rel="alternate" type="text/html" href="http://blog.astrumfutura.com/archives/408-Zend_Feed_Reader-promoted-to-Zend-Framework-trunk-watch-out-for-ZF-1.9!.html" title="Zend_Feed_Reader promoted to Zend Framework trunk (watch out for ZF 1.9!)"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~iTX" title="Shortlink to http://blog.astrumfutura.com/archives/408-Zend_Feed_Reader-promoted-to-Zend-Framework-trunk-watch-out-for-ZF-1.9!.html"/><author><name>P&#xE1;draic Brady</name></author><id>http://blog.astrumfutura.com/archives/408-guid.html</id><updated>2009-07-15T12:03:00Z</updated><published>2009-07-15T12:03:00Z</published><content type="html"><![CDATA[
    I'm happy to say that Zend_Feed_Reader has been made it through its two week cleanup effort and emerged from Matthew's review to join the Zend Framework trunk. Once the Zend Framework 1.9 release process spins up I look forward to more feedback how this component has turned out. Thanks to Jurriën Stutterheim (my co-conspirator), Matthew Weier O'Phinney for shepherding this through, and a special mention goes to Kawsar Saiyeed whose feedback while using Zend_Feed_Reader to build a feed aggregator over the past week was invaluable.<br/><br/>
Zend_Feed_Reader grew out of my need to have something that is not just capable of reading feeds, but was capable of understanding and interpreting them. If you've used Zend_Feed, you know that getting something simple like content, or a creation date, is a task that requires a bit of work. Feeds come in three distinctly different forms: RSS, RDF/RSS and Atom, all with multiple versions. Each has it's own way of presenting information. Each can also utilise extensions like RSS's popular Dublin Core 1.1 module or Atom's Threaded Extensions RFC. Getting a simple point of data can mean sifting through feeds to see what type and version they are, what elements to look for, what alternatives exist, and what alternatives should be prioritised over others. It's work that has led developers to write long classes designed to handle the task. Zend_Feed is also not without its flaws. Its API is inconsistent, its namespace handling questionable, and extending it is not as easy as it looks.<br/><br/>
So, is Zend_Feed_Reader any different? Well, I hope so <img src="http://blog.astrumfutura.com/templates/default/img/emoticons/wink.png" alt=";-)" style="display: inline; vertical-align: bottom;" class="emoticon"/>. But you'll have to dig a little deeper to see it. Here's a quick example from the documentation showing off the API briefly.<br/><br/><div class="php" style="text-align: left"><span style="color: #0000ff;">$feed</span> = Zend_Feed_Reader::<span style="color: #006600;">import</span><span style="color: #66cc66;">(</span><span style="color: #ff0000;">'http://www.planet-php.net/rdf/'</span><span style="color: #66cc66;">)</span>;<br/><span style="color: #0000ff;">$data</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><br/>    <span style="color: #ff0000;">'title'</span>        => <span style="color: #0000ff;">$feed</span>-><span style="color: #006600;">getTitle</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>    <span style="color: #ff0000;">'link'</span>         => <span style="color: #0000ff;">$feed</span>-><span style="color: #006600;">getLink</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>    <span style="color: #ff0000;">'dateModified'</span> => <span style="color: #0000ff;">$feed</span>-><span style="color: #006600;">getDateModified</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>    <span style="color: #ff0000;">'description'</span>  => <span style="color: #0000ff;">$feed</span>-><span style="color: #006600;">getDescription</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>    <span style="color: #ff0000;">'language'</span>     => <span style="color: #0000ff;">$feed</span>-><span style="color: #006600;">getLanguage</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>    <span style="color: #ff0000;">'entries'</span>      => <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/><span style="color: #66cc66;">)</span>;<br/><br/><span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">(</span><span style="color: #0000ff;">$feed</span> <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$entry</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span><br/>    <span style="color: #0000ff;">$edata</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">(</span><br/>        <span style="color: #ff0000;">'title'</span>        => <span style="color: #0000ff;">$entry</span>-><span style="color: #006600;">getTitle</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>,<br/>        <span style="color: #ff0000;">'description'</span>  => <span style="color: #0000ff;">$entry</span>-><span style=""/></div><p><i>Truncated by Planet PHP, read more at <a href="http://blog.astrumfutura.com/archives/408-Zend_Feed_Reader-promoted-to-Zend-Framework-trunk-watch-out-for-ZF-1.9!.html">the original</a> (another 14945 bytes)</i></p>]]></content></entry><entry><title type="text">Dutch PHP Conference 2009 wrapup</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/dragonbe-php/~3/FB8ahtFLyoM/dutch-php-conference-2009-wrapup.html" title="Dutch PHP Conference 2009 wrapup"/><link rel="shortlink" type="text/html" href="http://planet-php.org/~iQH" title="Shortlink to http://feedproxy.google.com/~r/dragonbe-php/~3/FB8ahtFLyoM/dutch-php-conference-2009-wrapup.html"/><author><name>Michelangelo van Dam</name></author><id>http://www.dragonbe.com/2009/06/dutch-php-conference-2009-wrapup.html</id><updated>2009-06-17T15:11:00Z</updated><published>2009-06-17T15:11:00Z</published><content type="html"><![CDATA[<p>A couple of days ago I came home from one of the best <a href="http://php.net" title="The Hypertext Preprocessor">PHP</a> conferences in the world, <strong><a href="http://www.phpconference.nl" title="Dutch PHP Conference 2009">Dutch PHP Conference 2009</a></strong> with again a very elite list of speakers.</p><br/><h2>Day 0: Tutorial Day</h2><p>Thursday, June 11 was tutorial day. A whole day dedicated at learning new things by the greatest <a href="http://php.net" title="The Hypertext Preprocessor">PHP</a> minds in the world.</p><p>I attended the <strong>"<a href="http://www.slideshare.net/weierophinney/zend-framework-workshop-dpc09" title="Zend Framework Workshop">Zend Framework Workshop</a>"</strong> by <strong><a href="http://weierophinney.net/matthew" title="Matthew Weier O' Phinney's blog">Matthew Weier O' Phinney</a></strong>, Chief Architect at <a href="http://framework.zend.com" title="Zend Framework">Zend Framework</a>.</p><br/><p>I went to see this tutorial session to see all the goodies that are put in <a href="http://framework.zend.com" title="Zend Framework">Zend Framework</a> 1.8 and to learn how to do stuff better. Great stuff like Zend_Tool, Zend_Application and other <a href="http://framework.zend.com" title="Zend Framework">Zend Framework</a> components are worth checking out.</p><br/><p>As it appears, I have to look into the Zend_Acl adapter using a configuration file or an external source and contribute my solutions to the <a href="http://framework.zend.com" title="Zend Framework">Zend Framework</a> wiki.</p><br/><p>Afterwards a Belgian delegation went down-town Amsterdam to have dinner at an Italian place and a drink afterwards at "Leidse Plein".</p><br/><h2>Day 1</h2><br/><p>Day one was a very hectic day for me since I was scheduled to speak at 10:30am. But we'll get there in a minute.</p><br/><h3>Opening keynotes</h3><p>Before the opening keynote of <strong><a href="http://blog.calevans.com" title="Cal Evans' blog">Cal Evans</a></strong>, Director of PCE at <a href="http://ibuildings.com" title="The PHP Professionals">Ibuildings</a>, an awesome <a href="http://vimeo.com/5165858" title="The intro movie for Dutch PHP Conference 2009">animated movie</a> was shown to the public.</p><p><strong><a href="http://blog.calevans.com" title="Cal Evans' blog">Cal Evans</a></strong> talked about what everyone could expect at the conference, what the rules of engagement were and what tags to use during the conference (a very important note).</p><p><strong><a href="http://gravitonic.com" title="Andrei Zmievski's Blog">Andrei Zmievski</a></strong> opened the conference officially talking about <strong>"PHP: people, code and ideas"</strong>. Too bad I had to flee the scene half way the presentation to set up my gear for my own talk about <a href="http://php.net/spl" title="The Standard PHP Library">SPL</a>.</p><br/><h3>Morning Sessions</h3><p>I hosted a talk called <strong>"<a href="http://www.slideshare.net/DragonBe/spl-not-a-bridge-too-far" title="SPL, not a bridge too far">SPL, not a bridge too far</a>"</strong> where I discussed on a low level (according to some, a bit too low) the funky features <a href="http://php.net/spl" title="The Standard PHP Library">SPL</a> brings to the table. And looking at the comments left on <a href="http://joind.in/586" title="Rate my talk on joind.in">joind.in</a> I actually got people interested in using <a href="http://php.net/spl" title="The Standard PHP Library">SPL</a> in their future development projects.<br/>Too bad I cut it short, like most people mentioned, because there's a whole lot to tell about <a href="http://php.net/spl" title="The Standard PHP Library">SPL</a>. Thanks everyone for you feedback, I will definitely keep it mind to make my presentation better.</p><br/><p><strong><a href="http://benramsey.com" title="Ben Ramsey's blog">Ben Ramsey</a></strong> showed us that <strong>"<a href="http://www.slideshare.net/benramsey/grokking-the-rest-architectural-style" title="Grokking the REST architectural style">Grokking the REST architectural style</a>"</strong> is worth thinking about when dealing with REST web services. He also talked about ATOM as a protocol, and he really got me interested in it to find out more. Thanks Ben, it was awesome.</p><br/><h3>Afternoon Sessions</h3><p><strong><a href="http://weierophinney.net/matthew" title="Matthew Weier O' Phinney's blog">Matthew Weier O' Phinney</a></strong> impressed us all again with another talk about <strong>"Contribute"</strong> and what we developers could do to make a difference.<br/>For everyone involved in open-source projects, a must see presentation and again lots of kudos to Matthew for bringing this point to the attention of the masses.</p><br/><p>Unfortunately I missed <strong><a href="http://www.suspekt.org" title="Stefan Esser's Blog">Stefan Esser</a>'s</strong> talk about <strong>"Secure Programming with the Zen</strong></p><p><i>Truncated by Planet PHP, read more at <a href="http://feedproxy.google.com/~r/dragonbe-php/~3/FB8ahtFLyoM/dutch-php-conference-2009-wrapup.html">the original</a> (another 7673 bytes)</i></p>]]></content></entry></feed>
