<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>Blog.feryn.eu</title>
	<atom:link href="http://blog.feryn.eu/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.feryn.eu</link>
	<description>Thijs Feryn's blog</description>
	<pubDate>Wed, 10 Mar 2010 21:32:24 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Having fun with gcc and make</title>
		<link>http://blog.feryn.eu/2010/03/having-fun-with-gcc-and-make/</link>
		<comments>http://blog.feryn.eu/2010/03/having-fun-with-gcc-and-make/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 21:32:24 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[C/C++]]></category>

		<category><![CDATA[IT]]></category>

		<category><![CDATA[gcc]]></category>

		<category><![CDATA[binary]]></category>

		<category><![CDATA[c]]></category>

		<category><![CDATA[compilation]]></category>

		<category><![CDATA[compiler]]></category>

		<category><![CDATA[g++]]></category>

		<category><![CDATA[gnu]]></category>

		<category><![CDATA[machine code]]></category>

		<category><![CDATA[make]]></category>

		<category><![CDATA[Makefile]]></category>

		<category><![CDATA[shared object]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=712</guid>
		<description><![CDATA[
Back to basics

I&#8217;ve been an IT professional for 6 year now and I&#8217;ve grown to love the scripting/programming language PHP. A lot of you use languages like these for easy and quick web development.
But we often forget that C/C++ is the foundation of these modern creations. Although I have had some C++ training in school [...]
]]></description>
			<content:encoded><![CDATA[<h2>Back to basics</h2>
<p><img alt="" src="http://gcc.gnu.org/img/gccegg-65.png" title="GCC" class="alignleft" width="109" height="130" /><br />
I&#8217;ve been an IT professional for 6 year now and I&#8217;ve grown to love the scripting/programming language <a href="http://www.php.net">PHP</a>. A lot of you use languages like these for easy and quick web development.</p>
<p>But we often forget that C/C++ is the foundation of these modern creations. Although I have had some C++ training in school but got alienated from it over the years. It was actually the love for PHP that got me back into C/C++. When compiling PHP and its set of extension I got into contact again with this fabulous language. </p>
<p>But this blog post isn&#8217;t entirely about C and C++. My goal is put <a href="http://gcc.gnu.org/">gcc</a> (the compiler <em>par exelence</em>) in the spotlight.<br />
<span id="more-712"></span></p>
<h2>Gcc 101</h2>
<p>Let&#8217;s start with the basic usage of gcc</p>
<h3>The binaries</h3>
<p>By default we use the <em>gcc</em> binary which is suited for compiling regular <em>C</em> programs. When programming in <em>C++</em> it&#8217;s better to use the <em>g++</em> binary.</p>
<h3>A simple C++ script</h3>
<p>It doesn&#8217;t get simpler than this: outputting <em>Hello world!</em>.</p>

<div class="wp_syntax"><div class="code"><pre class="cpp cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Hello world!&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span>;
    <span style="color: #0000ff;">return</span> <span style="color:#800080;">0</span>;
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>In PHP a simple <strong>echo</strong> would do, but in C++, you&#8217;ll need to initialize your tools:</p>
<ul>
<li>Include you Input/output stream library called <strong>iostream</strong>.
</li>
<li>Define a <strong>main</strong> function
</li>
<li>Call the <strong>cout</strong> language construct that resides in the <strong>std</strong> namespace
</li>
<li>Implement a proper return value for the main function
</li>
</ul>
<h3>Compiling it into a binary</h3>
<p>The easiest way to compile this script is by calling the <em>g++</em> binary and by passing the name of the source file:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ test.cc</pre></div></div>

<p>The g++ binary processes the <em>test.cc</em> source file and compiles it into machine code that is stored in a binary. Since we didn&#8217;t mention the name of the binary, g++ gives it the default name <strong>a.out</strong></p>
<h3>Running the binary</h3>
<p>Calling the binary is simple, just execute it as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">./a.out</pre></div></div>

<p>And you&#8217;ll get the expected output:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">Hello world!</pre></div></div>

<h2>Gcc options</h2>
<p>I&#8217;m just going to cover some basic gcc options. More information on gcc options can be found <a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Invoking-GCC.html#Invoking-GCC">here</a>.</p>
<h3>Output</h3>
<p>As mentioned, gcc defaults the name of its output binary to <em>a.out</em>. To control the name of the binary, use the <strong>-o</strong> option.</p>
<p>An example:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ test.cc -o test</pre></div></div>

<p>This generates a binary based on test.cc called <strong>test</strong>.</p>
<h3>Warnings</h3>
<p>The <strong>-W</strong> option allows you to define the warning levels. Most developers set this value to <strong>-Wall</strong>. Compiling a program with these parameters goes as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ -Wall test.cc</pre></div></div>

<h3>Binaries vs objects</h3>
<p>By default gcc generates a single binary containing the entire program. When using a fair amount of source files, a minor modification can result in slow compile times. To avoid this, you can compile every C/C++ source file into an object in machine code. This happens via the <strong>-c</strong> option.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ test.cc -c</pre></div></div>

<p>This command creates a file called <strong>test.o</strong> containing our simple program. This file is not executable, but can be linked into a binary when needed.</p>
<p>The upside is that you only have to recompile the source files in which modifications where made. Afterwards you can link the objects and create a binary.</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ test.o -o test</pre></div></div>

<p>This will start getting useful when you have a large number of source files.</p>
<h3>Libraries</h3>
<p>In most cases you won&#8217;t program all logic yourself unless you like to reinvent the wheel. You&#8217;ll probably include some third party code which is stored in the library folder of your operating system.</p>
<p>Let&#8217;s take the following example script I&#8217;ve found on the blog of <a href="http://www.luckyspin.org/?p=28">Todd Papaioannou</a>. It describes how to use the <a href="http://curl.haxx.se/">libcurl</a> library to perform <em>HTTP</em> calls in a simple C++ program:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;string&gt;  </span>
<span style="color: #339900;">#include &lt;iostream&gt;  </span>
<span style="color: #339900;">#include &quot;curl/curl.h&quot;  </span>
&nbsp;
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std;  
&nbsp;
<span style="color: #666666;">// Write any errors in here  </span>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">char</span> errorBuffer<span style="color: #008000;">&#91;</span>CURL_ERROR_SIZE<span style="color: #008000;">&#93;</span>;  
&nbsp;
<span style="color: #666666;">// Write all expected data in here  </span>
<span style="color: #0000ff;">static</span> string buffer;  
&nbsp;
<span style="color: #666666;">// This is the writer call back function used by curl  </span>
<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> writer<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>data, <span style="color: #0000ff;">size_t</span> size, <span style="color: #0000ff;">size_t</span> nmemb,  
                  std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> <span style="color: #000040;">*</span>buffer<span style="color: #008000;">&#41;</span>  
<span style="color: #008000;">&#123;</span>  
  <span style="color: #666666;">// What we will return  </span>
  <span style="color: #0000ff;">int</span> result <span style="color: #000080;">=</span> <span style="color:#800080;">0</span>;  
&nbsp;
  <span style="color: #666666;">// Is there anything in the buffer?  </span>
  <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>buffer <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>  
  <span style="color: #008000;">&#123;</span>  
    <span style="color: #666666;">// Append the data to the buffer  </span>
    buffer<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>append<span style="color: #008000;">&#40;</span>data, size <span style="color: #000040;">*</span> nmemb<span style="color: #008000;">&#41;</span>;  
&nbsp;
    <span style="color: #666666;">// How much did we write?  </span>
    result <span style="color: #000080;">=</span> size <span style="color: #000040;">*</span> nmemb;  
  <span style="color: #008000;">&#125;</span>  
&nbsp;
  <span style="color: #0000ff;">return</span> result;  
<span style="color: #008000;">&#125;</span>  
&nbsp;
<span style="color: #666666;">// You know what this does..  </span>
<span style="color: #0000ff;">void</span> usage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>  
<span style="color: #008000;">&#123;</span>  
  <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;curltest: <span style="color: #666666; font-weight: bold;">\n</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl;  
  <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;  Usage:  curltest url<span style="color: #666666; font-weight: bold;">\n</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> endl;  
<span style="color: #008000;">&#125;</span>   
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 
 * The old favorite 
 */</span>  
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>  
<span style="color: #008000;">&#123;</span>  
  <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>argc <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>  
  <span style="color: #008000;">&#123;</span>  
    string url<span style="color: #008000;">&#40;</span>argv<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>;  
&nbsp;
    <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Retrieving &quot;</span> <span style="color: #000080;">&lt;&lt;</span> url <span style="color: #000080;">&lt;&lt;</span> endl;  
&nbsp;
    <span style="color: #666666;">// Our curl objects  </span>
    CURL <span style="color: #000040;">*</span>curl;  
    CURLcode result;  
&nbsp;
    <span style="color: #666666;">// Create our curl handle  </span>
    curl <span style="color: #000080;">=</span> curl_easy_init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>;  
&nbsp;
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>curl<span style="color: #008000;">&#41;</span>  
    <span style="color: #008000;">&#123;</span>  
      <span style="color: #666666;">// Now set up all of the curl options  </span>
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_ERRORBUFFER, errorBuffer<span style="color: #008000;">&#41;</span>;  
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_URL, argv<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>;  
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_HEADER, <span style="color:#800080;">0</span><span style="color: #008000;">&#41;</span>;  
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_FOLLOWLOCATION, <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span>;  
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_WRITEFUNCTION, writer<span style="color: #008000;">&#41;</span>;  
      curl_easy_setopt<span style="color: #008000;">&#40;</span>curl, CURLOPT_WRITEDATA, <span style="color: #000040;">&amp;</span>buffer<span style="color: #008000;">&#41;</span>;  
&nbsp;
      <span style="color: #666666;">// Attempt to retrieve the remote page  </span>
      result <span style="color: #000080;">=</span> curl_easy_perform<span style="color: #008000;">&#40;</span>curl<span style="color: #008000;">&#41;</span>;  
&nbsp;
      <span style="color: #666666;">// Always cleanup  </span>
      curl_easy_cleanup<span style="color: #008000;">&#40;</span>curl<span style="color: #008000;">&#41;</span>;  
&nbsp;
      <span style="color: #666666;">// Did we succeed?  </span>
      <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>result <span style="color: #000080;">==</span> CURLE_OK<span style="color: #008000;">&#41;</span>  
      <span style="color: #008000;">&#123;</span>  
        <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> buffer <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;<span style="color: #666666; font-weight: bold;">\n</span>&quot;</span>;  
        <span style="color: #0000ff;">return</span> <span style="color:#800080;">0</span>;  
      <span style="color: #008000;">&#125;</span>  
      <span style="color: #0000ff;">else</span>  
      <span style="color: #008000;">&#123;</span>  
        <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Error: [&quot;</span> <span style="color: #000080;">&lt;&lt;</span> result <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;] - &quot;</span> <span style="color: #000080;">&lt;&lt;</span> errorBuffer;  
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span>;  
      <span style="color: #008000;">&#125;</span>  
    <span style="color: #008000;">&#125;</span>  
  <span style="color: #008000;">&#125;</span>  
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>As you might have noticed, Todd calls the <strong>curl.h</strong> header file located in the <strong>curl</strong> directory. This directory is located somewhere on your system. The exact directory depends on the version and distribution of your OS, but in my case the header file is located in <strong>/usr/include</strong>.</p>
<p>This is just the header, the actual <em>libcurl</em> library is stored in <strong>/usr/lib/</strong> and is called <strong>libcurl.so</strong>. The upside about using this <strong>.so</strong> file is that the compiler doesn&#8217;t compile the entire library in our small program. A <strong>shared object</strong> (so) shares its content at runtime and can be reused by several other programs. </p>
<p>This architecture results in smaller binaries, faster compile times and more flexibility when having to modify a library. Compiling it requires the <strong>-l</strong> option. Libraries are named <strong>libname.so</strong> where <em>name</em> is replaced by the actual name of the library.</p>
<p>Gcc only needs to know the name of the library and the following command does so:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">g++ -Wall test.cc -lcurl -o curltest</pre></div></div>

<p>Notice the fact that we don&#8217;t mention <strong>libcurl.so</strong>, but just <strong>curl</strong>. The binary we generate is called <strong>curltest</strong> and takes a command line argument that represents the URL of the website to which the HTTP request is sent.</p>
<h3>Static libraries</h3>
<p>In some cases your library isn&#8217;t stored in an <em>so</em> file or you just want all logic included in you binary. In that case you&#8217;ll want to compile your libraries in a <strong>static</strong> way.</p>
<p>When there&#8217;s no <strong>shared object</strong> to link dynamically, your library is called <strong>libname.a</strong>. Compiling it via the <strong>-l</strong> option will statically compile it into your program.</p>
<p>When specifying the <strong>-static</strong> option, you can force static compilation.</p>
<h2>Make makes it easy</h2>
<p>Most of you have probably used the <strong>make</strong> command on Linux. We take this for granted and often forget the complexity behind the compilation tasks this command executes. </p>
<h3>What does make do?</h3>
<p>Make is actually a build tool that cooperates quite well with gcc. The make command consists of easy tasks, that as a whole can represent a complex build. All input is retrieved from a file called <strong>Makefile</strong> which includes all actions to be performed.</p>
<p>The build actions are grouped in targets. By default the target that is first defined will be called when executing <strong>make</strong>. All other targets can be invoked by adding the target name as an argument. The <strong>make install</strong> is a common example of this.</p>
<h3>The Makefile</h3>
<p>This is an example of a Makefile. Before any of the targets are called, a set of variables can be set. These variables are used to setup gcc as gcc cycles through all source files and compiles them.</p>
<p>In this simple example I&#8217;ve set 2 variables:</p>
<ul>
<li><strong>CC=g++</strong>: specify that <strong>g++</strong> is our compiler binary
</li>
<li><strong>CFLAGS=-Wall</strong>: specify that the <strong>-Wall</strong> warning option should be passed to gcc
</li>
</ul>
<p>After the initial compilation phase when all source files are compiled into objects, the targets can be executed. Our Makefile contains 3 targets:</p>
<ul>
<li><strong>Main</strong>: the first target that is called by default. It links compiled objects into a single binary
</li>
<li><strong>Clean</strong>: deletes the main binary and all object files
</li>
<li><strong>Run</strong>: executes the binary
</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">CC=g++
CFLAGS=-Wall
main: main.o hello.o
        $(CC) main.o hello.o  -o main
clean:
        rm -f main main.o hello.o
run: main
        ./main</pre></div></div>

<p>Each of these targets has one or more dependencies. When the files <em>main.o</em> and <em>hello.o</em> don&#8217;t exist, the <em>main</em> target will not be executed and an error will occur. Similar patterns apply to the other targets.</p>
<p>We can now call:</p>
<ul>
<li>make
</li>
<li>make clean
</li>
<li>make run
</li>
</ul>
<h2>References</h2>
<p>This is merely an illustration of what <strong>gcc</strong> and <strong>make</strong> can do. I didn&#8217;t even cover 1% of the features. For a complete reference, please visit the following pages:</p>
<ul>
<li>GCC: <a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/">http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/</a>
</li>
<li>Make: <a href="http://www.gnu.org/software/make/manual/make.html">http://www.gnu.org/software/make/manual/make.html</a>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2010/03/having-fun-with-gcc-and-make/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Speaking at DPC10</title>
		<link>http://blog.feryn.eu/2010/02/speaking-at-dpc10/</link>
		<comments>http://blog.feryn.eu/2010/02/speaking-at-dpc10/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 19:30:29 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[Conferences]]></category>

		<category><![CDATA[amsterdam]]></category>

		<category><![CDATA[combell]]></category>

		<category><![CDATA[community]]></category>

		<category><![CDATA[dpc]]></category>

		<category><![CDATA[dpc10]]></category>

		<category><![CDATA[dpcon]]></category>

		<category><![CDATA[dutch php conference]]></category>

		<category><![CDATA[hoster]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[the netherlands]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=701</guid>
		<description><![CDATA[
Today the schedule for the Dutch PHP Conference 2010 (AKA DPC10) was officially released. And I&#8217;m happy to announce that I&#8217;m part of it.

My talk is called PHP through the eyes of a hoster and will portray PHP from an entirely different point of view than the usual developer, designer, QA, manager way we&#8217;re all [...]
]]></description>
			<content:encoded><![CDATA[<p>Today the schedule for the <a href="http://www.phpconference.nl">Dutch PHP Conference 2010</a> (AKA <a href="http://search.twitter.com/search?q=dpc10">DPC10</a>) was officially released. And I&#8217;m happy to announce that I&#8217;m part of it.<br />
<span id="more-701"></span><br />
My talk is called <em><strong>PHP through the eyes of a hoster</strong></em> and will portray PHP from an entirely different point of view than the usual developer, designer, QA, manager way we&#8217;re all used to.</p>
<p>The concept for this talk originates from my (give or take) 6 years experience within the <a href="http://www.combell.com">Combell </a>support team. Over the years I&#8217;ve seen tons of crazy cases which have thought me a lot about PHP.</p>
<p>For those who don&#8217;t know us, we&#8217;re the largest independent hosting company in Belgium and we have positioned ourselves in the quality segment. We have a lot of different types of customers, ranging from small one man businesses to large enterprises. Each of these have their own expectations, but also a different way in which they deal with hosting and PHP.</p>
<p>The funny thing is that we have the same goals as regular developers:</p>
<ul>
<li>It has to work
</li>
<li>It has to work fast
</li>
<li>It has to scale
</li>
<li>it has to be secure
</li>
</ul>
<p>But we use different instruments to achieve our goal:</p>
<ul>
<li>We don&#8217;t write code
</li>
<li>We sometimes interprete code
</li>
<li>We install PHP
</li>
<li>We tweak runtime configurations
</li>
<li>We analyze logs &amp; error messages
</li>
<li>We migrate applications
</li>
<li>We perform monitoring &amp; profiling
</li>
<li>We perform disastery recovery
</li>
<li>We deal with hacked sites &amp; abuse
</li>
<li>We offer customers general best practices
</li>
</ul>
<p>Come see me in Amsterdam June 11th. I&#8217;ll be speaking at 13h30 in track 3. <a href="http://phpconference.nl/schedule/">Check out the schedule</a> for more info.</p>
<p>Thanks to <a href="http://www.lornajane.net/">Lorna </a>and the DPC crew for this lovely opportunity.<br />
<img src="http://blog.feryn.eu/wp-content/uploads/2010/02/dpc09_speaker.jpg" alt="DPC 10 speaker" title="DPC 10 speaker" width="159" height="108" class="aligncenter size-medium wp-image-705" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2010/02/speaking-at-dpc10/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHPBenelux Conference 2010 in retrospect</title>
		<link>http://blog.feryn.eu/2010/01/phpbenelux-conference-2010-in-retrospect/</link>
		<comments>http://blog.feryn.eu/2010/01/phpbenelux-conference-2010-in-retrospect/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 17:47:35 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[antwerpen]]></category>

		<category><![CDATA[best western]]></category>

		<category><![CDATA[community]]></category>

		<category><![CDATA[conference]]></category>

		<category><![CDATA[edegem]]></category>

		<category><![CDATA[hotel]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[phpbenelux]]></category>

		<category><![CDATA[phpbnl10]]></category>

		<category><![CDATA[ter elst]]></category>

		<category><![CDATA[vagant]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=678</guid>
		<description><![CDATA[
The day after a PHP conference is the day you are most excited about PHP and the community. This statement also applies to me: I am very excited about PHP and the community after a fantastic PHPBenelux Conference (aka phpbnl10). Ter Elst in Edegem (Antwerpen) was the venue and hosting an international PHP conference was [...]
]]></description>
			<content:encoded><![CDATA[<p><a href="http://conference.phpbenelux.eu"><img alt="" src="http://phpbenelux.eu/files/phpbenelux_logo.png" title="PHPBenelux" class="alignleft" width="211" height="82" /></a>The day after a PHP conference is the day you are most excited about PHP and the community. This statement also applies to me: I am very excited about PHP and the community after a fantastic PHPBenelux Conference (aka <a href="http://search.twitter.com/search?q=%23phpbnl10">phpbnl10</a>). <a href="http://www.terelst.be">Ter Elst</a> in Edegem (Antwerpen) was the venue and hosting an international PHP conference was the goal.</p>
<p>The enthousiams for me is even greater because for the first time I assisted in organizing a conference. In fact it&#8217;s the first time this conference is organized.<br />
<span id="more-678"></span></p>
<h2>Organizing it</h2>
<h3>Who&#8217;s who</h3>
<p>After the merge between <em>PHPBelgium</em> and <em>phpGG</em> it was made very clear that our goal was to organize a real conference. We all had our experiences with user group meetings, but this was a different thing.</p>
<p>I have always felt like &#8220;the new guy&#8221; in the group and I feel fortunate to be surrounded by a group of very experienced people.</p>
<ul>
<li>There are community icons like <a href="http://www.dragonbe.com/">Michelangelo van Dam</a>(aka <em>dragonbe</em>) and <a href="http://www.leftontheweb.com/">Stefan Koopmanschap</a> (aka <em>skoop</em>).
</li>
<li>There are expert open source contributors like <a href="http://walhalla.wordpress.com">Paul Borgermans</a> and <a href="http://patrickallaert.blogspot.com/">Patrick Allaert</a>
</li>
<li>There are the incredibly dedicated and talented Dutch co-members <a href="http://www.velt.org/">Rein Velt</a>, <a href="http://www.missyeh.nl/">Kana Yeh</a> and <a href="http://www.wolerized.com/">Gerrit te Sligte</a> (aka <em>Remi</em>)
</li>
<li>And of course there&#8217;s my partner in (PHP) crime <a href="http://felix.phpbelgium.be/blog/">Felix De Vliegher</a>
</li>
</ul>
<p>I know I put in a lot of work and energy, but it&#8217;s nothing compared to what Mike and Stefan put in. They are community animals, so this stuff comes natural to them, but nevertheless: thank you for doing this.</p>
<h3>The practical stuff</h3>
<p>There&#8217;s so much stuff that you have to take into account:</p>
<ul>
<li>The venue
</li>
<li>The sponsors
</li>
<li>The printwork
</li>
<li>The announcements &#038; communication
</li>
<li>The speakers
</li>
<li>The call for papers
</li>
<li>The hotel
</li>
<li>The income and expenses
</li>
<li>The pricing
</li>
<li>The website
</li>
<li>The attendees
</li>
<li>&#8230;
</li>
</ul>
<p>It took us a while to figure all of it out, but (as it seems) we didn&#8217;t do that bad of a job. I admit, some things were done absolutely last minute, but hey: it got done. I&#8217;m sure that due to the experience we now have, the <em>phpbnl11</em> conference will be even better.</p>
<h2>Pre-conference</h2>
<h3>Friday preparations</h3>
<p>After lots of Skype meetings, group mails and discussions, it was finally time to meet up and make it happen. </p>
<p>I ordered the goodie bags, the sponsors brought all the goodies and Mike made sure there were prints to attach to the bags. Rein took care of the lanyards whereas Remi had the badges covered. You should have seen it: a real chain gang.</p>
<h3>Picking the speakers up</h3>
<p>When you&#8217;re organizing an international conference, you need international speakers and those people need to be picked up from airports and railway stations. There was even some carpooling going on.</p>
<p>My task was picking up <a href="http://fabien.potencier.org/">Fabien Potencier</a> which I had already picked up some time ago during the Symfony Bug Hunt Day. Apparently this proved to be a challenge.</p>
<p>I won&#8217;t bother you with the complete story, but I managed to show up in at the Central Station in Antwerp at 3 occasions without finding Fabien. Apparently there was a communication problem and the time of arrival proved to be the time of departure. During my 3 visits to the station there was one little gap I couldn&#8217;t cover due to transportation and parking and that was the exact moment Fabien did arrive.</p>
<p>Luckily Fabien showed up safely the day after and had to take a taxi from the station to the hotel. Although I was a little annoyed with the situation, I was actually happy to see Fabien show up. If you&#8217;re reading this, Fabien: don&#8217;t worry, I&#8217;m perfectly cool with the situation and will definitely pick you up again when there&#8217;s another PHPBenelux event.</p>
<h3>Speakers dinner</h3>
<p>The speakers dinner is always good fun and this one proved to be no different. We decided to eat at <a href="http://www.dagiovanni.be/">Da Giovanni</a> , a colourful Italian restaurant near De Groenplaats and the cathedral.</p>
<p>The funny thing about this place (do check <a href="http://www.dagiovanni.be">their website</a> to see for yourself) is that <strong>everything</strong> in the place has a white/red squared design. The waiters have an attitude and know how to use. In fact, almost none of the waiters are Italians (most of them are Morrocans or so), but they all pretend to be full blown Italians. Lots of <em>prego&#8217;s</em> and <em>gracie&#8217;s</em>.</p>
<p>Good food, good company and a feeling that I&#8217;m slowly being part of the <em>PHP community clique</em>.</p>
<h3>Drinks</h3>
<p>After a lovely dinner, we went to <a href="http://www.devagant.be/">De Vagant</a>, apparently an established <a href="http://en.wikipedia.org/wiki/Jenever">jenever</a> bar.</p>
<p>It was rather quiet out there and except for the speakers and crew only a couple of attendees. We did have some fun and had a couple of drinks. But everyone agreed that going to the hotel was a good idea. We had to be on top of our game for the conference and there was still some last minute details that needed to be figured out.</p>
<p>On the way back to the hotel, I offered <a href="http://kore-nordmann.de">Kore Nordmann</a> a drive. I only knew him as a speaker and PHP expert, but I had the opportunity to get to know him as a person too. Cool dude, I must say!</p>
<h2>Conference day</h2>
<h3>T-minus one hour</h3>
<p>I got up at 7 am (which was quite an effort), enjoyed a nice breakfast and joined the ever so charming <a href="http://blog.calevans.com/">Cal Evans</a>. This guy hopped into a plane from the US to present the closing keynote at our conference and had to leave the day after. Talk about dedication. I knew my fellow PHPBenelux co-members had a high opinion of him, but now I can confirm this myself. Thanks for making it to Antwerpen, Cal !</p>
<p>After a quick breakfast, we had to bring in all the goodie bags. In the meanwhile Stefan was already assisting the sponsors with their boot setups. Things looked very promising at that moment. </p>
<p>Only one thing caught us (or should I say the attendees) off guard: the night before the conference it had snowed and a lot of roads weren&#8217;t cleared yet. This forced us to kick off with a 15 minute delay.</p>
<h3>Kickoff</h3>
<h4>Opening keynote</h4>
<p><a href="http://derickrethans.nl/">Derick Rethans</a> was our opening keynote speakers. This guy needs <strong>NO</strong> introduction. I&#8217;ve seen a lot of his talks, even a couple of keynotes, but for this occasion he had prepared an entirely new keynote called <em>The PHP universe</em>. Really good stuff about how the so called <em>PHP ecosystem</em>.</p>
<h4>Track 1</h4>
<p>After the opening keynote, the schedule was split up into 2 tracks. I decided to stay in track 1 for a while where I assisted with the room management. </p>
<p>Fabien Potencier was first up with a brilliant talk about <em>dependency injection</em> in PHP 5.2 and 5.3. The new features in PHP 5.3 he used to illustrate his point were excellent. I did not know that <em>lambda functions</em> and <em>closures</em> could be so convenient when using dependency injection and avoiding overhead.</p>
<p><a href="http://blog.wombert.de/">David Zülke</a> was next with a talk about the state of <em>SOAP</em>. I have been using a lot of SOAP webservices the last couple of years, so I was very interested. This talk confirmed lots of things I did know about SOAP and taught me a couple of new things as well. Besides being a real PHP expert and a cool guy, David&#8217;s English is exceptionally good.</p>
<h4>Track two</h4>
<p>I would have loved to see Juliette Reinders Folmer&#8217;s talk about <em>regular expressions</em>, but I felt I had to support <a href="http://patrickallaert.blogspot.com">Patrick Allaert</a> and <a href="http://davidemendolia.blogspot.com">Davide Mendolia</a>. Their talk was about <em>APM</em> and <em>Pinba</em>: two open source projects that deal with monitoring. It&#8217;s not about monitoring the server itself, but more about monitoring it from a PHP point of view.</p>
<p>Very interesting talk, but unfortunately, the message dissolved in the chaos that emerged from the technical failures. I really felt bad for you guys, but I hope you&#8217;ll learn from your mistakes.</p>
<p>And Juliette: I promise I will attend your regex talk in London next month. I&#8217;ll have a front row seat!</p>
<p>After lunch (which was great actually, much better than the luches we usually get at conferences) I decided to check out Kore Nordmann&#8217;s talk about <em>CouchDb</em> and <em>PHPillow</em>. Really advanced shizzle! I already saw a similar talk he gave at <em>PHPVikinger</em>, so I knew what to expect. For people who aren&#8217;t familiar with non-relational databases, this seemed like rocket science. I will definitely try some <em>PHPillow</em> myself.</p>
<h4>Back to track one</h4>
<p>Next up was <a href="http://www.lornajane.net/">Lorna Mitchell</a>. Lorna is <strong>the</strong> community liaison for Ibuildings and she has built up a rocksolid reputation in a very short time. Here talk was great and dealt with the so called <em>Joel test</em>. Unfortunately, I had to leave early because Fabien needed a ride back to the station.</p>
<p>I&#8217;m really excited with the fact that Lorna will be in charge of <a href="http://phpconference.nl/">The Dutch PHP Conference</a> this year. It has always been a top conference and I&#8217;m sure this year will be a great edition as well. Good luck!</p>
<h3>Nearing the end</h3>
<p>We were nearing the end of the conference and I learned that Eric Ritchie couldn&#8217;t make it to Antwerpen. He got stuck somewhere, but luckily technology saved us. He managed to give his talk remotely and the audio/video was broadcasted into the conference room. I even heared that there was a microphone in the room that allowed the crowd to give real time feedback. </p>
<p>The closing keynote was the much anticipated <a href="http://blog.calevans.com/2009/08/06/open-teams/">Open teams</a> talk by Cal Evans. Cal illustrated in his signature style how corporate development teams can benefit by adopting open source development principals.</p>
<p>I must say: I like his ideas and I would love to see this in action, but I thing a lot of managers will be frightened by some of his propositions. Nevertheless, it can happen, we only need a couple of courageous companies to lead the way.</p>
<h2>The end</h2>
<h3>Conference social</h3>
<p>As Cal stated: he was the one thing standing between the conference attendees and an open bar. After his keynote there was still the obligatory conference closing statement which Stefan did very well. Everyone involved received a nice <em>thank you</em> and gifts were handed out to the speakers.</p>
<p>After those formalities, people rushed to the open bar (thank you <a href="http://www.ibuildings.nl">Ibuildings</a> for sponsoring this).</p>
<p>I had to leave quite early, but I heared the bowling event was a great success.</p>
<h3>Cool people I met</h3>
<ul>
<li>The entire PHPBenelux crew
</li>
<li>Cal Evans
</li>
<li>Kore Nordmann
</li>
<li>David Zülke
</li>
<li>Derick Rethans
</li>
<li>Juliette Reinders Folmer
</li>
<li>Katrien de Graeve at Microsoft
</li>
<li>Rick Buitenman and Ronald Kleverlaan at WEBclusive
</li>
<li>Tom Claus and Stijn Janssen at Inventis
</li>
<li>Christian Durel at Zend
</li>
<li>Nick Belhomme
</li>
<li>Andries Seutens
</li>
<li>Paul Delbar
</li>
<li>Ivo Jansch, Lorna Mitchell, Felix De Vliegher and Harrie Verveer at IBuildings
</li>
<li>Jachim Coudenys and Jochen Vandendriessche at Guideline
</li>
<li>Filip Forrez and Jeroen Serpieters at Ausy
</li>
<li>Davide Mendolia
</li>
<li>Jeremy Coates
</li>
<li>And lots of other people I forgot to mention
</li>
</ul>
<h3>See you next year</h3>
<p>See you next year for <a href="http://search.twitter.com/search?q=%23phpbnl11">phpbnl11</a> !</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2010/01/phpbenelux-conference-2010-in-retrospect/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Learning from your mistakes: mixed character sets in MySQL</title>
		<link>http://blog.feryn.eu/2009/12/learning-from-your-mistakes-mixed-character-sets-in-mysql/</link>
		<comments>http://blog.feryn.eu/2009/12/learning-from-your-mistakes-mixed-character-sets-in-mysql/#comments</comments>
		<pubDate>Sun, 06 Dec 2009 20:22:28 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[MySQL]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[--skip-extend-insert]]></category>

		<category><![CDATA[character set]]></category>

		<category><![CDATA[charset]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[encoding]]></category>

		<category><![CDATA[iconv]]></category>

		<category><![CDATA[iso]]></category>

		<category><![CDATA[ISO-8859-1]]></category>

		<category><![CDATA[migration]]></category>

		<category><![CDATA[mixed]]></category>

		<category><![CDATA[mysqldump]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[preg_match]]></category>

		<category><![CDATA[regex]]></category>

		<category><![CDATA[regular expression]]></category>

		<category><![CDATA[set names]]></category>

		<category><![CDATA[set names utf8]]></category>

		<category><![CDATA[skip extended insert]]></category>

		<category><![CDATA[utf-8]]></category>

		<category><![CDATA[utf8]]></category>

		<category><![CDATA[utf8_encode]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=659</guid>
		<description><![CDATA[
Character sets are a big thing these days and luckily we&#8217;re slowly evolving to a world where UTF-8 rules. In the meanwhile we&#8217;re stuck in a transitional phase where the ISO-8859-1 encoding is still used.
MySQL followed this trend and introduced character set support in version 4.1. Importing data from older versions is easy and SET [...]
]]></description>
			<content:encoded><![CDATA[<p>Character sets are a big thing these days and luckily we&#8217;re slowly evolving to a world where <strong>UTF-8</strong> rules. In the meanwhile we&#8217;re stuck in a transitional phase where the <strong>ISO-8859-1</strong> encoding is still used.</p>
<p>MySQL followed this trend and introduced character set support in version 4.1. Importing data from older versions is easy and <strong>SET NAMES &#8216;utf8&#8242;</strong> is quite useful to ensure special characters are correctly encoded in the new databases.</p>
<p>But I learned first hand that the <em>SET NAMES &#8216;utf8</em> trick is not a cure for every disease.<br />
<span id="more-659"></span></p>
<h2>The story</h2>
<p>Moving up is easy, but moving down is a real nightmare if you don&#8217;t take the necessary precautions. I had a case where a database had to be moved from a <em>MySQL 3.23</em> server to a <em>MySQL 5.0 server</em>. We decided to store all data in UTF-8 encoding which worked out well.</p>
<p>We also knew that the upgrade was a temporary measure: the 5.0 was installed on a high performance dedicated box to handle a peak. Once we were passed the peak, we decided to move back to the old server, which was a shared box. I was always under the assumption that the old server had a <em>MySQL 4.1</em>, but little did I know that I was dealing with an old school 3.23.</p>
<h2>The problem</h2>
<p>Unaware of any risk, I quickly took a <strong>mysqldump</strong> and imported the data on the old server. Apparently I had saved UTF-8 data in a database server that was only ISO aware. The consequences weren&#8217;t that clear in the beginning since Dutch &#038; English characters are usually the basic ISO characters.</p>
<p>Once I noticed that French characters were suddenly malformatted, I knew something was wrong. I quickly recreated the hosting on a 4.1 server and imported the data again. When reloading the page I was stunned: the old UTF-8 data was correctly displayed, but apparently all the new data since the migration from the dedicated server was still ISO.</p>
<h2>The solution</h2>
<h3>Attempts that failed</h3>
<p>The conclusion was that I had tables with records partially in UTF-8 &#038; partially in ISO. I figured this was easy to solve by writing a script that reads every line from the dump and converts it to UTF-8. By doing this, I would be sure all characters were the same.</p>
<p>Again I was faced with a big surprise: converting ISO data to UTF-8 works fine via <a href="http://www.php.net/utf8_encode">&#8216;utf8_encode&#8217; in PHP</a> , but UTF-8 stored in an ISO database cannot be converted to valid UTF-8 via this function.</p>
<p>Later I figured <a href="http://www.php.net/manual/en/function.iconv.php">iconv</a> could to the trick for me, but again the results where negative.</p>
<h3>The solution that actually worked</h3>
<p>Desperate for a solution, I continued browsing <a href="http://www.php.net/manual/en/">http://www.php.net/manual/en/</a> and stumbled upon <a href="http://be2.php.net/manual/en/function.iconv.php#80838">a user comment</a> describing a function to detect UTF-8 strings. That function, written by a guy named <strong>Anton Vakulchik</strong>, contained a fancy regular expression that does all the heavy lifting.</p>
<p>So I created a script containing the regular expression, started reading every line from my dumpfile and converted the string to UTF-8 where the <strong>preg_match</strong> returned false. To my surprise, it worked perfectly and I managed to output the data line by line in valid UTF-8</p>
<h2>The script</h2>
<p>The script below reads from <strong>stdin</strong> line by line and processes it. It detects UTF-8 data and converts lines to UTF-8 when necessary. This CLI script outputs every line to the <strong>stdout</strong>.</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">function</span> detectUTF8<span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="">'%(?:
	[\xC2-\xDF][\x80-\xBF]        # non-overlong 2-byte
	|\xE0[\xA0-\xBF][\x80-\xBF]               # excluding overlongs
	|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}      # straight 3-byte
	|\xED[\x80-\x9F][\x80-\xBF]               # excluding surrogates
	|\xF0[\x90-\xBF][\x80-\xBF]{2}    # planes 1-3
	|[\xF1-\xF3][\x80-\xBF]{3}                  # planes 4-15
	|\xF4[\x80-\x8F][\x80-\xBF]{2}    # plane 16
	)+%xs'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> readStdInArray<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$stdin</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="">'php://stdin'</span><span style="color: #339933;">,</span> <span style="">'r'</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #000088;">$out</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">is_resource</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stdin</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">feof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stdin</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$in</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">fgets</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stdin</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
			<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$in</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&gt;</span><span style="color:#800080;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
				<span style="color: #000088;">$out</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span> <span style="color: #000088;">$in</span>;
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$stdin</span><span style="color: #009900;">&#41;</span>;
	<span style="color: #b1b100;">return</span> <span style="color: #000088;">$out</span>;
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$std</span> <span style="color: #339933;">=</span> readStdInArray<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$std</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>detectUTF8<span style="color: #009900;">&#40;</span><span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">echo</span> <span style="color: #000088;">$line</span><span style="color: #339933;">.</span>PHP_EOL;
	<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">echo</span> <span style="color: #990000;">utf8_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>PHP_EOL;
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Using the script</h2>
<p>The combination of <strong>stdin</strong> and <strong>stdout</strong> allow the use of pipes in Linux which makes it really easy to convert data between 2 MySQL servers.</p>
<p>There are several ways to use the script. Every method consists of 3 steps:</p>
<ol>
<li>Dump mixed data from the old MySQL server
</li>
<li>Convert mixed data into UTF-8 data
</li>
<li>Import UTF-8 data into the new MySQL server
</li>
</ol>
<p>You can choose to store to results in a dumpfile or immediately transfer it from source to destination server with the conversion script in between. Here are a couple of examples:</p>
<h3>Direct transfer between 2 database servers</h3>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">mysqldump -hOldHost -uUsername -pPassword -Q -A --skip-extended-insert | php -q utf8.php | mysql -hNewHost -uUsername -pPassword</pre></div></div>

<h3>Storing the dumps in dumfiles</h3>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">mysqldump -hOldHost -uUsername -pPassword -Q -A --skip-extended-insert -pPassword &gt; mixeddump.sql</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">cat mixeddump.sql | php -q utf8.php &gt; utf8dump.sql</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">cat utf8dump.sql | mysql -hNewHost -uUsername -pPassword</pre></div></div>

<h3>Script restriction</h3>
<p>The script is quite powerful, but has one big restriction: <strong>it can only determine the charset of a line</strong>. So every line must be encoded in a single character set. To enforce this, I had to make sure that every database record was stored on 1 single line. The <strong>mysqldump &#8211;skip-extended-insert parameter</strong> helped me to achieve this. So please do use it!</p>
<p>Of course, I could have performed a UTF-8 check on every character, but that wouldn&#8217;t have been so resource friendly when using 100+ MB dumpfiles.</p>
<p>Check out the <a href="http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html">mysqldump manual</a> for more information on <strong>mysqldump command line parameters</strong>.</p>
<h2>Conclusion</h2>
<p>What I&#8217;ve learned is that working with character sets can get tricky. I will definitely by more cautious in the future, but a least I have a conversion script that can take care of hairy situations.</p>
<p>Thank you Anton Vakulchik for writing the kick-ass regular expressions</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/12/learning-from-your-mistakes-mixed-character-sets-in-mysql/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Preparing for Symfony BugHuntDay</title>
		<link>http://blog.feryn.eu/2009/11/preparing-for-symfony-bughuntday/</link>
		<comments>http://blog.feryn.eu/2009/11/preparing-for-symfony-bughuntday/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 22:54:07 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Symfony]]></category>

		<category><![CDATA[bhd]]></category>

		<category><![CDATA[bug]]></category>

		<category><![CDATA[bughuntday]]></category>

		<category><![CDATA[fix]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[intracto]]></category>

		<category><![CDATA[lime]]></category>

		<category><![CDATA[patch]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[phpbelgium]]></category>

		<category><![CDATA[phpbenelux]]></category>

		<category><![CDATA[phpgg]]></category>

		<category><![CDATA[test]]></category>

		<category><![CDATA[testing]]></category>

		<category><![CDATA[unit test]]></category>

		<category><![CDATA[unittest]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=633</guid>
		<description><![CDATA[

That&#8217;s right, the title says it all: we&#8217;re having another BugHuntDay. After the success of the previous one, we (PHPBenelux) decided to host another one. Last time around it was all about Zend Framework. This time we feel that we should dedicate some attention to the Symfony framework.
To be perfectly honest, we were discussing it [...]
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.symfony-project.org"><img class="alignleft" title="Symfony" src="http://www.symfony-project.org/downloads/logos/symfony.gif" alt="Symfony" width="225" height="61" /></a><br />
That&#8217;s right, the title says it all: we&#8217;re having another BugHuntDay. After the success of <a href="http://www.phpbenelux.eu/en/node/950">the previous one</a>, we (<a href="http://www.phpbenelux.eu">PHPBenelux</a>) decided to host another one. Last time around it was all about <a href="http://framework.zend.com">Zend Framework</a>. This time we feel that we should dedicate some attention to the <a href="http://www.symfony-project.org">Symfony</a> framework.</p>
<p>To be perfectly honest, we were discussing it for a while, but we didn&#8217;t reach the planning stage. That was until the kind people at <a href="http://www.intracto.be">Intracto</a> decided to take the lead. I knew they were pretty fond of Symfony, but now they decided it was time to give back to the community by sponsoring and hosting the event.<br />
<a href="http://www.phpbenelux.eu"><img class="alignright" title="PHPBenelux" src="http://phpbenelux.eu/files/images/PHP-BENELUX-Logo.preview.png" alt="PHPBenelux" width="247" height="96" /></a><br />
The event takes place Saturday November 14th at <em>Frame21</em> in Herentals. More details can be found on the <a href="http://www.phpbenelux.eu/nl/symfonyBugHuntDay">PHPBenelux website</a>. You can still <strong>register</strong> for this event and we kindly invite you to do so by filling up <a href="http://www.phpbenelux.eu/en/bhdregistration">the following form</a>.</p>
<p>This blog post will assist you in preparing for the actual event. You shouldn&#8217;t be a rocket scientist to participate. A <strong>good knowledge of PHP and an open mind</strong> will get you a long way.<br />
<span id="more-633"></span></p>
<h2>About Symfony BugHuntDay</h2>
<p>A BugHuntDay is a <strong>community event</strong> where people gather to <strong>find/fix bugs</strong> in open source software. As I already mentioned, we picked the <strong>Symfony framework</strong> which is a well known PHP framework which delivers a full stack  MVC solution. Our goal is to find/fix as many bugs as possible for the <strong>upcoming 1.3 release</strong>.</p>
<p>Finding bugs is quite easy, <a href="http://trac.symfony-project.org/report">the Trac issue tracker</a> that Symfony uses has a nice overview of all tickets. But finding a bug that you are able to fix is a different story all together.</p>
<h2>Getting to know Symfony</h2>
<h3>The framework</h3>
<p>You can get to know the Symfony framework by downloading and installing <a href="http://www.symfony-project.org/get/sf_sandbox_1_3.tgz">the Symfony sandbox</a>. The sandbox offers a <strong>pre-packaged Symfony project</strong> you can play and experiment with. It includes the application default document structure and the complete Symfony framework library. </p>
<p>There&#8217;s also plenty of <strong>documentation</strong> available. Go to <a href="http://www.symfony-project.org/doc/1_3/">the Symfony documentation pages</a> to read all about it. If you have difficulties installing Symfony or the sandbox, you should consult <a href="http://www.symfony-project.org/getting-started/1_3/en/03-Symfony-Installation">the Symfony installation guide</a>.</p>
<h3>The source</h3>
<p>Once you&#8217;ve gained some basic experience, it&#8217;s time to take a look at the source code. Since we are working on the upcoming 1.3 release, you should <a href="http://svn.symfony-project.com/branches/1.3">check out the 1.3 Subversion branch</a>. You can also view this branch <a href="http://trac.symfony-project.org/browser/branches/1.3">via the Trac panel</a>.</p>
<h2>Coaching</h2>
<p>Once you know your way around the framework, it&#8217;s time to find yourself a nice bug to fix. That will not be so easy. You are free to browse the tickets, but I guess some <strong>coaching</strong> will be required. </p>
<p>The good thing about PHPBenelux is that we have <strong>lots of contacts in the PHP community</strong>. We managed to invite some people who are important to the Symfony project. They will coordinate the event and provide proper coaching. We have confirmed the following Symfony team members:</p>
<ul>
<li><a href="http://www.leftontheweb.com/">Stefan Koopmanschap</a> is the community manager for the Symfony project. He&#8217;s also one of our board members, so it was quite easy to confirm him.
</li>
<li><a href="http://fabien.potencier.org/">Fabien Potencier</a> is the project leader for Symfony. It&#8217;s a real honor to have him at the event.
</li>
<li><a href="http://blog.hma-info.de">Fabian Lange</a> is the release manager for the 1.2 release. His presence is also greatly appreciated.
</li>
</ul>
<p>Not only will they help us with the issues we encounter, but they&#8217;ll <strong>make a selection of bugs</strong> that are quite manageable to fix. It&#8217;s also a great opportunity for them to have a group of people who will contribute to the project. If you have difficulties finding the right bug to fix, talk to the coaches, they will guide you.</p>
<p>For those of you who can&#8217;t make it to Herentals: you can also participate over the internet. The entire event will also be <strong>hosted on the internet via IRC</strong>. It will be the main communication channel to get in touch with the coaches and the onsite contributors.</p>
<h2>Fixing a bug</h2>
<p>Once you have found a bug that you can fix, you still need to take some things into account before you start coding away. It&#8217;s very important to read <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony">the wiki article on how to contribute</a>.</p>
<p>The <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#Submittingpatches">Submitting patches</a> chapter is an essential part that describes:<br />
- <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#CodingStandards">Coding standards</a><br />
- <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#Patchstyle">Patch styles</a><br />
- <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#Unitandfunctionaltests">Commit procedure</a><br />
- <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#UnitandfunctionaltestsTesting">procedure</a></p>
<p>When it comes to preparing, this is a crucial step that cannot be skipped. If you really want to commit a patch It will have to be according the standards.</p>
<h2>Testing</h2>
<p><em>When can you really guarantee a bug is fixed? And can you guarantee that your patch hasn&#8217;t triggered another bug?</em></p>
<p><strong>Unit tests</strong> are the answer to that question. The <strong>assumption</strong> that your patch is absolutely flawless <strong>is not enough</strong>. It&#8217;s very easy to trip over a proverbial wire and <strong>trigger</strong> one or more <strong>additional bugs</strong>. Unit tests allow you to test your patches via a <strong>set of fixtures</strong>.</p>
<p>An initial testcase should make your testcase fail and should reproduce the actual bug. This is a solid way of proving that the bug is actually a bug and not a feature. Again, assumptions aren&#8217;t enough.</p>
<p>After fixing the bug, the testcase will succeed and this should be a proof that the patch is a valid bugfix. If the patch makes other unit tests fail, you&#8217;ve obviously did something horribly wrong and you should review the patch before submitting it.</p>
<p>It&#8217;s obvious that unit tests are <strong>saveguards</strong> that protect the integrity of the project. There are many tools to perform unit tests. The people at Symfony have created there own testing framework which is called <strong>The Lime Testing Framework</strong>. Again, the <a href="http://trac.symfony-project.org/wiki/LimeTestingFramework">Trac wiki</a> provides the necessary information on how to use this testing framework.</p>
<h2>Hope to see you there</h2>
<p>Don&#8217;t be afraid to participate, even if you aren&#8217;t that experienced. It will be a great opportunity to learn a lot about the framwork, about bugfixing and about PHP in general.</p>
<p>You will meet lots of interesting people and if your not part of the PHP community yet, this is your chance to take the first step.</p>
<p>See you there !<br />
Thijs</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/11/preparing-for-symfony-bughuntday/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Avoiding Tarball extraction overkill with 2 simple tricks</title>
		<link>http://blog.feryn.eu/2009/08/avoiding-tarball-extraction-overkill-with-2-simple-tricks/</link>
		<comments>http://blog.feryn.eu/2009/08/avoiding-tarball-extraction-overkill-with-2-simple-tricks/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 10:13:54 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[IT]]></category>

		<category><![CDATA[Linux]]></category>

		<category><![CDATA[archive]]></category>

		<category><![CDATA[branch]]></category>

		<category><![CDATA[compression]]></category>

		<category><![CDATA[extract]]></category>

		<category><![CDATA[gz]]></category>

		<category><![CDATA[gzip]]></category>

		<category><![CDATA[tar]]></category>

		<category><![CDATA[tar.gz]]></category>

		<category><![CDATA[tarball]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=560</guid>
		<description><![CDATA[
Intro
Hello readers
It&#8217;s been a while: I&#8217;ve been busy at work, going on vacation and been lazy when at home. It&#8217;s more than about time to get into my blogging routine again.
This one is actually a short one on Tarball archives. You know, the (compressed) archiving you use to pack your files with. For people unaware [...]
]]></description>
			<content:encoded><![CDATA[<h2>Intro</h2>
<p>Hello readers</p>
<p>It&#8217;s been a while: I&#8217;ve been busy at work, going on vacation and been lazy when at home. It&#8217;s more than about time to get into my blogging routine again.</p>
<p>This one is actually a short one on <em>Tarball archives</em>. You know, the (compressed) archiving you use to pack your files with. For people unaware of this technology: you can compare it to <em>ZIP</em> and <em>RAR</em> archives but with a little more punch.<br />
<span id="more-560"></span></p>
<h2>Basic usage</h2>
<p>Everyone who&#8217;s used to working with Linux or other Unix-like systems knows how to create and extract a Tarball archive. But for those who are new to it, here&#8217;s an example</p>
<h3>Creating an archive</h3>
<p>The simplest way to create a Tarball archive is with the following command:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar cvf myTarArchive.tar folderToArchive</pre></div></div>

<ul>
<li>Tar: the command used to archive a specified folder
</li>
<li>Options:
<ul>
<li>C: create an archive
</li>
<li>V: verbose
</li>
<li>F: filename to use
</li>
</ul>
</li>
<li>myTarArchive.tar: the name of the new tar archive
</li>
<li>folderToArchive: the folder that will be archived and packed into the <em>myTarArchive.rar</em> file
</li>
</ul>
<p>In most cases you will want your Tarball archive to be compressed. The <em>tar</em> command allows <em>GZIP</em> compression by adding the <em>Z</em> option:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar cvzf myTarArchive.tar.gz folderToArchive</pre></div></div>

<ul>
<li>Tar: the command used to archive a specified folder
</li>
<li>Options:
<ul>
<li>C: create an archive
</li>
<li>V: verbose
</li>
<li>Z: compress using GZIP compression algorithm
</li>
<li>F: filename to use
</li>
</ul>
</li>
<li>myTarArchive.tar.gz: the name of the new tar archive (with the GZ suffix)
</li>
<li>folderToArchive: the folder that will be archived and packed into the <em>myTarArchive.rar</em> file
</li>
</ul>
<h3>Extracting an archive</h3>
<p>The exact purpose of this article is facilitating extraction and before we can get into that, I need to show you how basic Tarball extraction works:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar xvf myTarArchive.tar</pre></div></div>

<ul>
<li>Tar: the command used to unpack a specified tar archive
</li>
<li>Options:
<ul>
<li>X: extract an archive
</li>
<li>V: verbose
</li>
<li>F: filename to use
</li>
</ul>
</li>
<li>myTarArchive.tar: the name of the tar archive to extract
</li>
</ul>
<p>If your Tarball archive was compressed, you will need to specify the <em>Z</em> option as well:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar xvzf myTarArchive.tar.gz</pre></div></div>

<ul>
<li>Tar: the command used to unpack a specified tar archive
</li>
<li>Options:
<ul>
<li>X: extract an archive
</li>
<li>V: verbose
</li>
<li>Z: apply GZIP decompression
</li>
<li>F: filename to use
</li>
</ul>
</li>
<li>myTarArchive.tar.gz: the name of the tar archive to extract (with GZ suffix)
</li>
</ul>
<h2>The tricks</h2>
<p>Without further ado, I will immediately continue with the actual tricks. Let&#8217;s say you have an automatic backup schedule of some crucial folders on your server. A cronjob launches a <em>tar</em> command that archives a specified folder every night.</p>
<h3>Extracting a single branch</h3>
<p>The reason one backups his files, is to eventually recover lost/corrupt data in case of emergency situations. If that archive happens to be a couple of giga&#8217;s, your server will require a lot of computing power to decompress and unarchive the data you want. In a number of cases you don&#8217;t want to recover your entire archive since you only a single subfolder. </p>
<p>In that case it would be nice to only extract a single branch of your entire folder tree. For all you GUI users out there, this is peanuts, you just drag and drop. On the command line, it requires an extra argument.</p>
<p>Take for example this folder tree:</p>
<ul>
<li>folder_1
<ul>
<li>subfolder_1
<ul>
<li>subfolder_1_1
</li>
<li>subfolder 1_2
</li>
</ul>
</li>
<li>subfolder_2
</li>
</ul>
</li>
<li>folder 2
</li>
</ul>
<p>Let&#8217;s say you only want to extract &#8216;&#8217;subfolder_1_2&#8243;. It would be overkill to extract the entire archive, wasting disk, resources and most important: your time. To extract this single branch, you can issue the following statement</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar xvzf myTarArchive.tar.gz folder_1/subfolder_1/subfolder_1_2</pre></div></div>

<p>What will happen is that in the current working directory a number a folder tree will be created containing only the files of &#8216;&#8217;subfolder_1_2&#8243;. Of course it will reside in the hierarchy of the folder tree.</p>
<h3>Extracting to a different folder</h3>
<p>If can be quite annoying if you want to extract an archive containing files that already exist in your current working directory. These files will be overwritten and you don&#8217;t always want to create dummy folders where you can extract you archive. Sometimes you just want extract a file, a folder or an entire branch to a specified folder. The <em>-C</em> option does all that:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar -C /path/to/selected/folder -xvzf myTarArchive.tar.gz</pre></div></div>

<p>So this on will extract the <em>myTarArchive.tar.gz</em> archive in the path specified after the <em>-C</em> option.</p>
<h3>Combining both tricks</h3>
<p>Needless to say you can combine both tricks:</p>

<div class="wp_syntax"><div class="code"><pre class="text text" style="font-family:monospace;">tar -C /path/to/selected/folder -xvzf myTarArchive.tar.gz folder1/subfolder_1/subfolder_1_2</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/08/avoiding-tarball-extraction-overkill-with-2-simple-tricks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A DPC 08 review for DPC 09</title>
		<link>http://blog.feryn.eu/2009/06/a-dpc-08-review-for-dpc-09/</link>
		<comments>http://blog.feryn.eu/2009/06/a-dpc-08-review-for-dpc-09/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 21:57:35 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Review]]></category>

		<category><![CDATA[amsterdam]]></category>

		<category><![CDATA[aulke]]></category>

		<category><![CDATA[bergmann]]></category>

		<category><![CDATA[chay]]></category>

		<category><![CDATA[combell]]></category>

		<category><![CDATA[conference]]></category>

		<category><![CDATA[dpc]]></category>

		<category><![CDATA[dpc08]]></category>

		<category><![CDATA[dpc09]]></category>

		<category><![CDATA[dpcon]]></category>

		<category><![CDATA[dutch]]></category>

		<category><![CDATA[fabien]]></category>

		<category><![CDATA[fabien potencier]]></category>

		<category><![CDATA[felix]]></category>

		<category><![CDATA[felix de vliegher]]></category>

		<category><![CDATA[felixdv]]></category>

		<category><![CDATA[feryn]]></category>

		<category><![CDATA[gaylord]]></category>

		<category><![CDATA[gaylord aulke]]></category>

		<category><![CDATA[holland]]></category>

		<category><![CDATA[ibuildings]]></category>

		<category><![CDATA[ivo]]></category>

		<category><![CDATA[ivo jansch]]></category>

		<category><![CDATA[jansch]]></category>

		<category><![CDATA[lorna]]></category>

		<category><![CDATA[lorna mitchell]]></category>

		<category><![CDATA[marco]]></category>

		<category><![CDATA[marco tabini]]></category>

		<category><![CDATA[mitchell]]></category>

		<category><![CDATA[netherlands]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[potencier]]></category>

		<category><![CDATA[rai]]></category>

		<category><![CDATA[sebastian]]></category>

		<category><![CDATA[sebastian bergmann]]></category>

		<category><![CDATA[suraski]]></category>

		<category><![CDATA[tabini]]></category>

		<category><![CDATA[terry]]></category>

		<category><![CDATA[terry chay]]></category>

		<category><![CDATA[thijs]]></category>

		<category><![CDATA[Thijs Feryn]]></category>

		<category><![CDATA[werck]]></category>

		<category><![CDATA[zeev]]></category>

		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=516</guid>
		<description><![CDATA[
Better late than never: since DPC 09 is coming up this week, this is the ideal occasion for a review of the 2008 edition.
The trip to Amsterdam started off in Gent where I traveled along with Felix De Vliegher &#038; Steve Roelens. Comfortably cruising along the Belgian &#038; Dutch motorways, we where looking for some [...]
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.phpconference.nl"><img class="alignleft size-full wp-image-517" title="Dutch PHP Conference" src="http://blog.feryn.eu/wp-content/uploads/2009/06/logodpc09b.png" alt="Dutch PHP Conference" width="312" height="214" /></a>Better late than never: since DPC 09 is coming up this week, this is the ideal occasion for a review of the 2008 edition.</p>
<p>The trip to Amsterdam started off in Gent where I traveled along with <a href="http://felix.phpbelgium.be/blog/">Felix De Vliegher</a> &#038; Steve Roelens. Comfortably cruising along the Belgian &#038; Dutch motorways, we where looking for some good times and some expert opinions on common PHP topics. In retrospect, we got both in spades!<br />
<span id="more-516"></span></p>
<h2>Welcome to Amsterdam</h2>
<p>We all booked rooms in Novotel nearby the <a href="http://www.rai.nl">RAI</a> venue and after the obligatory checkin, we quickly decided to head off to town. Everyone knows that Amsterdam is a pretty wild city, but add the fact that Holland was playing an <a href="http://en.wikipedia.org/wiki/UEFA_Euro_2008">UEFA European Cup game</a> versus France that weekend and you have yourself a full blown circus.</p>
<p>The Dutch are pretty dedicated, emotional and loudmouth fans and the entire city was covered in orange ornaments. They where excited about their weekend, but so where we. After some late night shopping and a quick fastfood stop, we quickly turned to the number one tourist attraction in Amsterdam: the famous red light disctrict known as <a href="http://en.wikipedia.org/wiki/De_Wallen">De Walletjes</a>.</p>
<p>As strange as it might sound, but there are families strolling around looking at the entire phenomenon: girls luring guys in, pimps on the lookout and drug dealers hustling. Your typical family night out, right? Very exciting, but extremely fake I must add.</p>
<h2>Tutorial Day</h2>
<p>After a final fastfood stop, we headed back to the hotel and hit the hay. Make no mistake: Amsterdam is a nice city the visit, but the real reason for our stay was the PHP conference. The first day was tutorial day and I had signed up for the <a href="http://www.phpunit.info">PHPUnit</a> tutorial by <a href="http://sebastian-bergmann.de">Sebastian Bergmann</a>. The good thing about this tutorial is that you&#8217;re not dealing with some speaker or coach, but the guys who actually developed the software. It doesn&#8217;t get much better than that.</p>
<p>Really interesting stuff and this was only the beginning. There where plenty of opportunities for networking as well and I actually met a lot of customers, so I obviously had to represent <a href="http://www.combell.com">Combell</a>.</p>
<div class="wp-caption alignnone" style="width: 343px"><a href="http://farm4.static.flickr.com/3060/2580376798_5c40bd64f5.jpg?v=0"><img title="Dutch PHP Conference 2008 (by Felix De Vliegher)" src="http://farm4.static.flickr.com/3060/2580376798_5c40bd64f5.jpg?v=0" alt="Dutch PHP Conference 2008 (by Felix De Vliegher)" width="333" height="500" /></a><p class="wp-caption-text">Dutch PHP Conference 2008 (by Felix De Vliegher)</p></div>
<h2>Good Stuff</h2>
<p>If knew right from the start that this was a good conference, the organisation was superb:</p>
<ul>
<li>Great topics
</li>
<li>World class speakers
</li>
<li>Good venue
</li>
<li>Decent catering
</li>
<li>Kick-ass afterparty (courtesy of the Dutch national football team)
</li>
</ul>
<h2>Afterparty</h2>
<p>Let me get into more details about that friday night afterparty: all attendants were kindly invited to the <a href="http://www.werck.nl">Werck</a> bar at the Prinsengracht. There was a happy our (thanks to <a href="http://www.ibuildings.com">IBuildings</a>) and the atmosphere was ecstatic. The bar also had a dining area which was exclusively reserved for IBuildings staff. Since IBuildings has lots of employees and even a UK branch, there were lots of people.</p>
<p>So we had a packed bar, lots of drinks and tons of football fans. Need I say more? Ow yeah, I do: Holland crushed France that night and it was the most lovely football experience ever. Seconds after the first Dutch goal, it felt like a bomb was dropped on Amsterdam: in the bar everyone went nuts, but outside you could here the roars from an entire city. Imagine asking a million people to yell at the same time and you&#8217;d have the same effect.</p>
<p>Poor <a href="http://fabien.potencier.org">Fabien Potencier</a> who supported the French team. The game didn&#8217;t just leave an impression on him or me, because Europeans knew what they&#8217;re getting themselves into. But the Americans, they were absolutely stunned ! But at least now they know what <em>Hup Holland Hup</em> means. Some American speakers even made remarks on that during their talks</p>
<div class="wp-caption alignnone" style="width: 510px"><a href="http://www.flickr.com/photos/derickrethans/2623337271/in/set-72157605892006980/"><img alt="Adieu les blues (by Derick Rethans)" src="http://farm4.static.flickr.com/3153/2623337271_6c4350dd6d.jpg?v=0" title="Adieu les blues (by Derick Rethans)" width="500" height="332" /></a><p class="wp-caption-text">Adieu les blues (by Derick Rethans)</p></div>
<h2>Conference Day</h2>
<h3>Intro</h3>
<p>After tutorial day and the parties it was time for some real deal PHP shizzle. <a href="http://www.jansch.nl">Ivo Jansch</a> was the guy that put us on track with a short introduction.</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008ivojanschintro-1213700469053027-9"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008ivojanschintro-1213700469053027-9" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Zeev Suraski</h3>
<p>After the intro it was time for a keynote by <a href="http://suraski.net/blog">Zeev Suraski</a>, the co-founder of <a href="http://www.zend.com">Zend</a> called <em>State Of PHP</em>. He talked about the state and evolution of PHP. It is definitely a cool thing to see how PHP evolved from PHP/FI and a small university project into to enterprise product it is nowadays.</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008zeevsuraskistateofphp-1213862850226459-8"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008zeevsuraskistateofphp-1213862850226459-8" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Marco Tabini</h3>
<p>Two keynotes in a row: we were in for a real treat! Next up was <a href="http://mtabini.blogspot.com">Marco Tabini</a>, the co-founder of <a href="http://phparch.com/">PHP|architect</a>. He brought us a presentation called <em>Software And The Taste Of Mayo</em>. The title seems quite mysterious and vague, but in fact he explains that good software is a mixture of the right ingredients, just like mayonaise.</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008marcotabinisoftwareandthetasteofmayo-1213862996514918-8"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008marcotabinisoftwareandthetasteofmayo-1213862996514918-8" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Gaylord Aulke</h3>
<p>I also enjoyed the talk by Gaylord Aulke called <em>An Infrastructure For Team Development</em> which covers best practices when working with multiple developers on one project. Gaylord went over the common tools professional PHP developers use these days and also specified how to use them when working in teams. Good stuff there!</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008gaylordaulkeinfrastructureforteamdevelopment-1213700512581251-9"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008gaylordaulkeinfrastructureforteamdevelopment-1213700512581251-9" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Lorna Mitchell</h3>
<p>Content wise, this was the most interesting talk on the bill. <a href="http://www.lornajane.net/">Lorna Mitchell&#8217;s</a> talk called <em>Deployment With Subversion</em> dealt with best practices to make deployment a little easier. It even involved a little bunny called <a href="http://www.nabaztag.com">Nabaztag</a> that goes nuts when Subversion commits fail. Simply awesome!</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008lornamitchelldeploymentwithsvn-1213862871843314-8"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008lornamitchelldeploymentwithsvn-1213862871843314-8" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Ivo Jansch</h3>
<p>Off course I had to see <a href="http://www.jansch.nl">Ivo</a> in action. His talk covered practical items, but was actually quite evangelistic. It was called <em>Enterprise PHP Development</em> and shows how PHP is <em>enterprise ready</em> as a technology. He wrote <a href="http://phparch.com/c/books/id/9780973862188">a book</a> about it and even the fiercest non-believers would crawl up in some deep dark hole after seeing this.</p>
<p>I strongly believe that PHP can be used in an enterprise environment and I have <a href="http://www.slideshare.net/combell/professional-php-an-opensource-alternative-for-enterprise-development-presentation-809322">talked about it on some occasions</a> myself. This talk inspired me to spread the word.</p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008ivojanschenterprisephpdevelopment-1213700171445915-8"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=dpc2008ivojanschenterprisephpdevelopment-1213700171445915-8" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
<h3>Terry Chay</h3>
<p>Needless to say that a <a href="http://terrychay.com/blog/">Terry Chay</a> talk leaves an impression. He knows what he&#8217;s talking about, he has proven to be an expert in his domain and he&#8217;s not afraid to kick the oposition in the nuts. Did he screw with Rails? Ow yeah he did! Did he curse a zillion times? Fuck yeah he did!</p>
<p>His talk was called &#8221;The Internet Is An Ogre&#8221; and was beautifully illustrated with some great slides, animations and movies. Terry, please come back to Europe some time!</p>
<h2>DPC09</h2>
<p>I hope this brings back some memories for the people who were there. I am convinced that this year&#8217;s edition will be as successful and I hope to see you guys there for a little chat.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/06/a-dpc-08-review-for-dpc-09/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Zend_Cache_Frontend_Page &amp; Google Analytics cookies</title>
		<link>http://blog.feryn.eu/2009/06/zend_cache_frontend_page-google-analytics-cookies/</link>
		<comments>http://blog.feryn.eu/2009/06/zend_cache_frontend_page-google-analytics-cookies/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 19:13:46 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Zend Framework]]></category>

		<category><![CDATA[analytics]]></category>

		<category><![CDATA[backend]]></category>

		<category><![CDATA[cache]]></category>

		<category><![CDATA[cookie]]></category>

		<category><![CDATA[cookies]]></category>

		<category><![CDATA[file]]></category>

		<category><![CDATA[framework]]></category>

		<category><![CDATA[frontend]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[memcache]]></category>

		<category><![CDATA[memcached]]></category>

		<category><![CDATA[page]]></category>

		<category><![CDATA[zend]]></category>

		<category><![CDATA[Zend_Cache_Backend_File]]></category>

		<category><![CDATA[Zend_Cache_Backend_Memcached]]></category>

		<category><![CDATA[Zend_Cache_Frontend_Page]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=486</guid>
		<description><![CDATA[

<pre>
Last week I was optimizing the caching strategy for one of my projects and I was under the false impression that caching was accelerating my website. 
</pre>
At that time I was using Zend_Cache_Backend_File as my backend and cache files were created. My goal was to boost the performance by implementing the Zend_Cache_Backend_Memcached backend. Again [...]
]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.feryn.eu/wp-content/uploads/2009/01/zend-framework.png" alt="zend-framework" title="zend-framework" width="185" height="187" class="alignleft size-full wp-image-138" /> Last week I was optimizing the caching strategy for one of my projects and I was under the false impression that caching was accelerating my website. </p>
<p>At that time I was using <a href="http://framework.zend.com/manual/en/zend.cache.backends.html#zend.cache.backends.file">Zend_Cache_Backend_File</a> as my backend and cache files were created. My goal was to boost the performance by implementing the <a href="http://framework.zend.com/manual/en/zend.cache.backends.html#zend.cache.backends.memcached">Zend_Cache_Backend_Memcached</a> backend. Again everything seemed to be working fine because my Memcached logging displayed activity of some sort.</p>
<p>I was stunned to hear that in fact all of those cache files where created, but never read. So here I am optimizing everything, but in reality I was creating extra overhead. So I started my quest and found the solution (sorry for the spoiler).<br />
<span id="more-486"></span></p>
<h2>Page caching</h2>
<p>We use <a href="http://framework.zend.com/manual/en/zend.cache.frontends.html#zend.cache.frontends.page">Zend_Cache_Frontend_Page</a> as the frontend of our caching mechanism because it is so simple to use:</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$cache</span> <span style="color: #339933;">=</span> Zend_Cache<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #009900;">&#40;</span><span style="">'Page'</span><span style="color: #339933;">,</span>
    <span style="">'File'</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$frontendOptions</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$backendOptions</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #000088;">$cache</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>The <em>start</em> method just triggers the caching mechanism and doesn&#8217;t need any more attention. It just takes care of itself. The output buffering stores the output in the caching backend. Caching keys are used to identify cached records. Via <em>save()</em> and <em>load()</em> we can interact with the caching backend.</p>
<h2>The frontend options</h2>
<p>In the previous example I didn&#8217;t specify the frontend options, but actually they are essential to this blog post. That&#8217;s why I dedicate a chapter to it.</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$frontendOptions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="">'lifetime'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">86400</span><span style="color: #339933;">,</span>
    <span style="">'default_options'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'cache'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">false</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'regexps'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'^/(nl|fr|en)(.*)$'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'cache'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'cache_with_get_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'cache_with_session_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'cache_with_cookie_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'make_id_with_get_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'make_id_with_session_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
            <span style="">'make_id_with_cookie_variables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">false</span>
            <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
        <span style="">'debug_header'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">false</span>
    <span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>The code example above illustrates the extra options that were passed to the <em>frontendOptions</em> array. The <em>cache_with_&#8230;</em> option keys are quite important because they make sure that caching is still enabled when <em>cookies</em> or <em>get variables</em> are passed. Sometimes you want to caching to be disabled when there&#8217;s dynamic content involved. We decided to continue caching when there are cookies.</p>
<p>The <em>make_id_with_&#8230;</em> option keys don&#8217;t decide if caching is enabled or disabled, but they decide how dynamic content is stored. The next chapter explains how Zend_Cache_Frontend_Page stores its data.</p>
<h2>Behind the scenes</h2>
<p>To understand how Zend Framework works with page caching and how I ran into my problem, we should dig into the framework code.</p>
<h3>Data storage</h3>
<p>As mentioned, the <em>start</em> method takes care of everything and below you&#8217;ll find the source code of that method.</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> start<span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$doNotDie</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cancel <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span>;
    <span style="color: #000088;">$lastMatchingRegexp</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">null</span>;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_specificOptions<span style="color: #009900;">&#91;</span><span style="">'regexps'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$regexp</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$conf</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;`$regexp`&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$lastMatchingRegexp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$regexp</span>;
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_specificOptions<span style="color: #009900;">&#91;</span><span style="">'default_options'</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$lastMatchingRegexp</span> <span style="color: #339933;">!==</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$conf</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_specificOptions<span style="color: #009900;">&#91;</span><span style="">'regexps'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lastMatchingRegexp</span><span style="color: #009900;">&#93;</span>;
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$conf</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span>;
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'cache'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">false</span>;
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$id</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_makeId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">false</span>;
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$id</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #339933;">!==</span> <span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$array</span><span style="color: #009900;">&#91;</span><span style="">'data'</span><span style="color: #009900;">&#93;</span>;
        <span style="color: #000088;">$headers</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$array</span><span style="color: #009900;">&#91;</span><span style="">'headers'</span><span style="color: #009900;">&#93;</span>;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">headers_sent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$headers</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$headerCouple</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$name</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$headerCouple</span><span style="color: #009900;">&#91;</span><span style="color:#800080;">0</span><span style="color: #009900;">&#93;</span>;
                <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$headerCouple</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span>;
                <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;$name: $value&quot;</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_specificOptions<span style="color: #009900;">&#91;</span><span style="">'debug_header'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #990000;">echo</span> <span style="">'DEBUG HEADER : This is a cached page !'</span>;
        <span style="color: #009900;">&#125;</span>
        <span style="color: #990000;">echo</span> <span style="color: #000088;">$data</span>;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$doNotDie</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;
        <span style="color: #009900;">&#125;</span>
        <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="">'_flush'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #990000;">ob_implicit_flush</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">false</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>A couple of things that are worth mentioning about this method:</p>
<ul>
<li>Via <em>$this->_makeId();</em> an identifier is created and the identifier is the storage key
</li>
<li>The <em>$this->load($id);</em> method loads the cached data using the key which was returned by the <em>makeId</em> method
</li>
<li>Via <em>ob_start(array($this, &#8216;_flush&#8217;));</em> output buffering is started. The <em>_flush()</em> method is a callback method that is triggered when the output buffer is flushed.
</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> _flush<span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cancel<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$data</span>;
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$contentType</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">null</span>;
    <span style="color: #000088;">$storedHeaders</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$headersList</span> <span style="color: #339933;">=</span> headers_list<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_specificOptions<span style="color: #009900;">&#91;</span><span style="">'memorize_headers'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$headerName</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$headersList</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$headerSent</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">split</span><span style="color: #009900;">&#40;</span><span style="">':'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$headerSent</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #000088;">$headerSentName</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_shift</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$headerName</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$headerSentName</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$headerSentValue</span> <span style="color: #339933;">=</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="">':'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tmp</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>;
                <span style="color: #000088;">$storedHeaders</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$headerSentName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$headerSentValue</span><span style="color: #009900;">&#41;</span>;
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'data'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$data</span><span style="color: #339933;">,</span>
        <span style="">'headers'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$storedHeaders</span>
    <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #339933;">,</span> <span style="color: #000000; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'tags'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'specific_lifetime'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'priority'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$data</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The <em>_flush()</em> method we were talking about does most of the storage: when the output buffer is flushed (which happens at the end of the script execution) the <em>save</em> method is called and this one also triggers the saving mechanism of the backend.</p>
<h2>The actual problem</h2>
<p>After some intense debugging I noticed that the reason why caching went all wrong was because every <em>page hit</em> resulted in a new <em>cache key</em>. Result: 0% cache hits !</p>
<h3>Making id&#8217;s</h3>
<p>To figure out why the previous key isn&#8217;t re-used, we should take a look at the <em>_makeId()</em> method that is responsible for creating those id&#8217;s:</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">protected <span style="color: #000000; font-weight: bold;">function</span> _makeId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="">'?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tmp</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span>;
  	<span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$array</span><span style="color: #009900;">&#91;</span><span style="color:#800080;">0</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Get'</span><span style="color: #339933;">,</span> <span style="">'Post'</span><span style="color: #339933;">,</span> <span style="">'Session'</span><span style="color: #339933;">,</span> <span style="">'Files'</span><span style="color: #339933;">,</span> <span style="">'Cookie'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$arrayName</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    	<span style="color: #000088;">$tmp2</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_makePartialId<span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrayName</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'cache_with_'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrayName</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="">'_variables'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_activeOptions<span style="color: #009900;">&#91;</span><span style="">'make_id_with_'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arrayName</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="">'_variables'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$tmp2</span><span style="color: #339933;">===</span><span style="color: #000000; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">false</span>;
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000088;">$tmp</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$tmp</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$tmp2</span>;
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tmp</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Did you notice that <em>foreach</em> loop? Yes: that&#8217;s the key to everything, because we&#8217;re looping through the different <a href="http://www.php.net/manual/en/language.variables.superglobals.php">superglobals</a>. In this loop, we&#8217;re checking if we can create id&#8217;s based on cookie values. Off course, if the cookie value would change, a new id is generated. And that is actually what was happening on my system.</p>
<h3>What does Google have to do with it?</h3>
<p><img src="http://blog.feryn.eu/wp-content/uploads/2009/06/google-analytics-logo.png" alt="google-analytics-logo" title="google-analytics-logo" width="181" height="220" class="alignleft size-full wp-image-499" /> To summarize: the values of cookies can be used to create cache keys. If cookie values change, our caching key changes as well and we have a <em>cache miss</em>.</p>
<p>So I started looking at my cookies and noticed that there were some cookies which had a different value each time I reloaded the page. After some research, I finally figured out that these cookies were created by my <a href="http://www.google.com/analytics/">Google Analytics</a> implementation. The <a href="http://code.google.com/intl/nl/apis/analytics/docs/concepts/gaConceptsCookies.html">reference</a> page shows a definition of the cookies set by Google Analytics. Some of those cookies contain timestamps that change on every page hit.</p>
<h2>The solution</h2>
<p>The solution is actually simple: disable the <em>make_id_with_cookie_variables</em> key in the frontendOptions and you&#8217;re safe!</p>
<h2>The final summary</h2>
<ol>
<li>Caching is based on identifiers
</li>
<li>Rules can be defined to allow caching based on cookie values
</li>
<li>A new cookie value means new caching identifier
</li>
<li>A new caching identifier means a cache miss
</li>
<li>When cache misses occur, the &#8216;miss&#8217; is stored to result in a hit the next time
</li>
<li>Google Analytics creates cookies that have dynamic values
</li>
<li>By disabling <em>make_id_with_cookie_variables</em>, we can solve the problem
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/06/zend_cache_frontend_page-google-analytics-cookies/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Time to clean up the PHP source code in version 6</title>
		<link>http://blog.feryn.eu/2009/05/time-to-clean-up-the-php-source-code-in-version-6/</link>
		<comments>http://blog.feryn.eu/2009/05/time-to-clean-up-the-php-source-code-in-version-6/#comments</comments>
		<pubDate>Sun, 31 May 2009 18:02:15 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[chris]]></category>

		<category><![CDATA[code]]></category>

		<category><![CDATA[core]]></category>

		<category><![CDATA[derick]]></category>

		<category><![CDATA[developers]]></category>

		<category><![CDATA[inventis]]></category>

		<category><![CDATA[mcvicar]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[php 6]]></category>

		<category><![CDATA[php6]]></category>

		<category><![CDATA[ramakers]]></category>

		<category><![CDATA[rethans]]></category>

		<category><![CDATA[scott]]></category>

		<category><![CDATA[skyrocket]]></category>

		<category><![CDATA[source]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=478</guid>
		<description><![CDATA[
I attended PHP Vikinger in Leuven yesterday which was actually a really cool unconference organised by Derick Rethans. According to unconference standards, talks aren&#8217;t really planned in advance which sometimes results in somewhat suprising features.
The item that came up which surprised me the most is the fact that the PHP core developers will choose reverse [...]
]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.feryn.eu/wp-content/uploads/2009/05/php.gif" alt="PHP" title="PHP" width="120" height="67" class="alignleft size-full wp-image-483" />I attended <a href="http://phpvikinger.org/">PHP Vikinger</a> in Leuven yesterday which was actually a really cool <em>unconference</em> organised by <a href="http://derickrethans.nl">Derick Rethans</a>. According to unconference standards, talks aren&#8217;t really planned in advance which sometimes results in somewhat suprising features.<span id="more-478"></span></p>
<p>The item that came up which surprised me the most is the fact that the PHP core developers will choose reverse compatibility above a more than necessary source code cleanup. </p>
<p>This post is actually written in support of the one <a href="http://www.skyrocket.be">Chris Ramakers</a> from <a href="http://www.inventis.be">Inventis</a> wrote yesterday about this very same topic. I surely hope these kind of blog posts will re-open the discussion on this matter and I hope the PHP core developers will reconsider their strategy.</p>
<p>Please read <a href="http://www.skyrocket.be/2009/05/30/php-function-naming-and-argument-order/">Chris&#8217; blog post</a> and spread the word. Off course it&#8217;s the PHP developers who should share their opinion and if the majority feels reverse compatibility is a priority, well then the core guys should stick with it, otherwise a cleanup wouldn&#8217;t be a bad idea.</p>
<p>We&#8217;re talking about the release of a major version and I think this would be the ideal opportunity to fix some inconsistencies. The argument Derick and Scott used is that <em>they don&#8217;t want to piss off PHP developers</em>, but I&#8217;m pretty sure some of them will already be pissed off with the fact that <em>register_globals</em>, <em>safe_mode</em> &#038; <em>magic_quotes_gpc</em> will disappear as well.</p>
<p>Think about it &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/05/time-to-clean-up-the-php-source-code-in-version-6/feed/</wfw:commentRss>
		</item>
		<item>
		<title>&#8220;CLI, the other SAPI&#8221; slides online</title>
		<link>http://blog.feryn.eu/2009/05/cli-the-other-sapi-slides-online/</link>
		<comments>http://blog.feryn.eu/2009/05/cli-the-other-sapi-slides-online/#comments</comments>
		<pubDate>Wed, 27 May 2009 22:04:03 +0000</pubDate>
		<dc:creator>Thijs</dc:creator>
		
		<category><![CDATA[CLI]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[batch]]></category>

		<category><![CDATA[binary]]></category>

		<category><![CDATA[child]]></category>

		<category><![CDATA[combell]]></category>

		<category><![CDATA[command line]]></category>

		<category><![CDATA[cron]]></category>

		<category><![CDATA[daemon]]></category>

		<category><![CDATA[fork]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[multithreading]]></category>

		<category><![CDATA[parent]]></category>

		<category><![CDATA[pcntl]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[phpbelgium]]></category>

		<category><![CDATA[signals]]></category>

		<category><![CDATA[slideshare]]></category>

		<guid isPermaLink="false">http://blog.feryn.eu/?p=456</guid>
		<description><![CDATA[
Better late the never: I finally put the slides of my presentation called &#8220;CLI, the other SAPI&#8221;. I did this talk some time ago at the PHPBelgium user group meeting which took place in the COMBELL offices in Gent.
As some of you might have noticed: my blog series &#8220;CLI, the other SAPI&#8221; is actually based [...]
]]></description>
			<content:encoded><![CDATA[<p>Better late the never: I finally put the slides of my presentation called &#8220;CLI, the other SAPI&#8221;. I did this talk some time ago at the PHPBelgium user group meeting which took place in the COMBELL offices in Gent.</p>
<p>As some of you might have noticed: my blog series &#8220;CLI, the other SAPI&#8221; is actually based on this talk. There are still some episodes in the making, but you can have sneak preview of what&#8217;s yet to come by checking the slides.</p>
<p>A large portion of the presentation contains information on process control. Some people advised me to make a separate presentation on that topic. I might consider that, but in the mean time this is the result: </p>
<object style="margin:0px" width="425" height="348.360655738"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=clitheothersapi-090520114233-phpapp02"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=clitheothersapi-090520114233-phpapp02" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="348.360655738"></embed></object>
]]></content:encoded>
			<wfw:commentRss>http://blog.feryn.eu/2009/05/cli-the-other-sapi-slides-online/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
