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

<channel>
	<title>Joe Freeman&#039;s Weblog</title>
	<atom:link href="http://joefreeman.co.uk/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://joefreeman.co.uk/blog</link>
	<description>Musings on Software Development, etc</description>
	<lastBuildDate>Mon, 21 Dec 2009 19:06:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Handling Multipart Uploads with MochiWeb</title>
		<link>http://joefreeman.co.uk/blog/2009/12/handling-multipart-uploads-with-mochiweb/</link>
		<comments>http://joefreeman.co.uk/blog/2009/12/handling-multipart-uploads-with-mochiweb/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 00:02:40 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[MochiWeb]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=262</guid>
		<description><![CDATA[An explanation of how to handle file uploads with the MochiWeb Erlang library. The article includes a brief introduction to setting up MochiWeb and an explanation of how to handle file uploads and save them to the /tmp directory. I've also put together a very simple photo gallery system to show how to make use of this feature.]]></description>
			<content:encoded><![CDATA[<p>I was getting along fairly well with my own custom-built, lightweight Erlang web server, until I needed to handle file uploading. At this point, I decided it was time to stop trying to re-invent the wheel (or take the lazy approach—whichever way you choose to look at it), and take another look at MochiWeb, which implements this feature.</p>
<p>However, MochiWeb&#8217;s documentation is non-existent (unless I&#8217;m missing something—<em>please</em> let me know if I am). I came across <a href="http://jimmyg.org/blog/2007/multipart-post-with-erlang-and-mochiweb.html">James Gardner&#8217;s post</a> on handling file uploads, which helped me out. But after digging through the MochiWeb source-code I discovered a slightly easier way of handling file uploads. It may be that this method has been added since James&#8217; post in 2007, or maybe it&#8217;s just less appropriate to James&#8217; requirements.</p>
<p>I&#8217;m going to quickly run over how to setup MochiWeb. I know this has been covered quite a lot by other people, but it&#8217;s something a found a little daunting when I started out, so I want to emphasise that it&#8217;s a lot easier to setup than maybe first appears. Then I&#8217;ll post and explain a short chunk of code for handling uploads, and saving them to <code>/tmp</code>. Finally, I&#8217;ll provide an example of using this technique to provide a <em>very</em> simple photo gallery system.</p>
<h2>Setting up MochiWeb</h2>
<p>There&#8217;s a pretty good tutorial <a href="http://beebole.com/en/blog/erlang/how-to-quickly-set-up-ubuntu-804-loaded-with-erlang-mochiweb-and-nginx/">on the BeeBole blog</a>, but I&#8217;ll cover the basics here.</p>
<p>First step is to check out the code from the Google Code repository. Make sure you have subversion installed, and then:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">svn</span> checkout http:<span style="color: #000000; font-weight: bold;">//</span>mochiweb.googlecode.com<span style="color: #000000; font-weight: bold;">/</span>svn<span style="color: #000000; font-weight: bold;">/</span>trunk<span style="color: #000000; font-weight: bold;">/</span> mochiweb</pre></div></div>

<p>Now, make sure that you have Erlang installed, and:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> mochiweb
<span style="color: #c20cb9; font-weight: bold;">make</span>
<span style="color: #c20cb9; font-weight: bold;">chmod</span> +x scripts<span style="color: #000000; font-weight: bold;">/</span>new_mochiweb.erl
.<span style="color: #000000; font-weight: bold;">/</span>scripts<span style="color: #000000; font-weight: bold;">/</span>new_mochiweb.erl mochiweb_uploads ..<span style="color: #000000; font-weight: bold;">/</span>.</pre></div></div>

<p>This will build the MochiWeb system and then create a new MochiWeb project. You can repeat this process whenever you&#8217;re starting a new project. Note that <code>mochiweb_uploads</code> is the project&#8217;s name. MochiWeb is a bit picky about project names: they must be valid module names, so (it seems) you can&#8217;t use hyphens.</p>
<p>Next, we should make sure that the project builds and runs before we start coding:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> ..<span style="color: #000000; font-weight: bold;">/</span>mochiweb_uploads
<span style="color: #c20cb9; font-weight: bold;">make</span>
.<span style="color: #000000; font-weight: bold;">/</span>start-dev.sh</pre></div></div>

<p>By default, your MochiWeb project is setup as a lightweight web server that serves files from the <code>priv/www</code> directory on port 8000. All being well, you should now be able to point your browser at <code>http://localhost:8000/</code> and see the &#8216;MochiWeb is running.&#8217; message.</p>
<p>If you have any problems, you&#8217;ll need to wade through the progress reports on the console to try and figure out where things are going wrong. The clues will be in any &#8216;crash reports&#8217;.</p>
<p>You can stop the server with Ctrl+C, then entering &#8216;a&#8217;, and hitting return. Or you can just hit Ctrl+C twice.</p>
<h2>Handling File Uploads</h2>
<p>First of all, we need to put together a page that we can test our uploading with. We&#8217;ll just replace the <code>index.html</code> file in <code>priv/www</code> with something straight-forward:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>MochiWeb Upload Test<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;upload_photo&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">enctype</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;multipart/form-data&quot;</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;file&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;photo&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Upload&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></pre></div></div>

<h3>Routing the Request</h3>
<p>The code for starting the web server is in <code>src/mochiweb_uploads_web.erl</code>. Open up this file and take a look at the <code>loop/2</code> function. The function is split up into two parts by the outer <code>case</code> construct: the first part is for HTTP GET (and HEAD) requests, the second is for POST requests. We&#8217;re going to be handling the file uploads in the POST clause. Like so:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="">'POST'</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #186895;">case</span> <span style="color: #45b3e6;">Path</span> <span style="color: #186895;">of</span>
        <span style="color: #ff7800;">&quot;upload_photo&quot;</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #ff3c00;">upload_photo</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
        <span style="color: #45b3e6;">_</span> <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">not_found</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span></pre></div></div>

<p>All we are doing here, is delegating responsibility for handling the &#8216;upload_photo&#8217; request to a function called &#8216;upload_photo&#8217;, which we can add to the bottom of <code>mochiweb_uploads_web.erl</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">upload_photo</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;text/html&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;&lt;p&gt;Hello, world!&lt;/p&gt;&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>That&#8217;s going to just return a &#8216;Hello, world!&#8217; message so we can check the request is getting routed correctly. If we try out the system (<code>make</code>, <code>./start-dev.sh</code>, go to <code>localhost:8000</code>), we should initially see the form, then after submitting the form our message should appear.</p>
<h3>Handling the POSTed multipart data</h3>
<p>Now onto actually handling the POSTed multipart data. We&#8217;ll replace our <code>upload_photo/1</code> function with this:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">upload_photo</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">FileHandler</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">handle_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #45b3e6;">Files</span> <span style="color: #014ea4;">=</span> mochiweb_multipart:<span style="color: #ff3c00;">parse_form</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">FileHandler</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #45b3e6;">Photo</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">proplists</span>:<span style="color: #ff3c00;">get_value</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;photo&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Files</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #666666; font-style: italic;">% TODO: handle the photo here</span>
    <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">ok</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;text/html&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;&lt;p&gt;Thank you. &lt;a href=<span style="color: #000099; font-weight: bold;">\&quot;</span>index.html<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;Upload another?&lt;/a&gt;&lt;/p&gt;&quot;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Let&#8217;s examine this line-by-line.</p>
<p>First of all, we&#8217;re specifying a function that we pass to the <code>mochiweb_multipart:parse_form/2</code> function. The function that we&#8217;re passing will get called <strong>once for every file that is present in the POST data</strong> (i.e., that is in the form)—don&#8217;t forget that multiple files may be being uploaded.</p>
<p>The file will be split into &#8216;chunks&#8217;. So it&#8217;s the job of this &#8216;FileHandler&#8217; function to return <em>another</em> function that will be used to consume each chunk of the file (and then, finally, the &#8216;eof&#8217; atom). We&#8217;ll come back to this in a moment.</p>
<p>The <code>parse_form/2</code> function will then return a list (in fact, a <a href="http://www.erlang.org/doc/man/proplists.html">property list</a>) of all the files. There will be a mapping from the name of the input to the value finally returned from our file handler.</p>
<p>Let&#8217;s take a look at the <code>handle_file/2</code> function:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">handle_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">TempFilename</span> <span style="color: #014ea4;">=</span> <span style="color: #ff7800;">&quot;/tmp/&quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff3c00;">atom_to_list</span><span style="color: #109ab8;">&#40;</span>?<span style="color: #6941fd;">MODULE</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff3c00;">integer_to_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">erlang</span>:<span style="color: #ff3c00;">phash2</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">make_ref</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">File</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">open</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">TempFilename</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span>raw<span style="color: #6bb810;">,</span> write<span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff3c00;">chunk_handler</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">TempFilename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">File</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>We use <a href="http://www.erlang.org/doc/man/erlang.html#erlang:phash2-2"><code>erlang:phash2/2</code></a> and <a href="http://www.erlang.org/doc/man/erlang.html#make_ref-0"><code>make_ref/0</code></a> together with a (hopefully) application-specific prefix to construct a random filename which will reside in &#8216;/tmp&#8217;. A couple of points to make here: collisions aren&#8217;t impossible and this is platform-dependent. We could get the <a href="http://en.wikipedia.org/wiki/Temporary_folder">temporary directory</a> from the operating system, and we could generate <a href="http://stackoverflow.com/questions/1222084/how-do-i-create-a-temp-filename-in-erlang">better filenames</a>.</p>
<p>We open a file for writing to and pass it to our &#8216;chunk handler&#8217; ready for consuming the first chunk. Note that <code>chunk_handler/4</code> is <strong>a function that returns a function</strong>. We return this generated function back to the MochiWeb code, which will use it to handle the first chunk.</p>
<p>Before I go on to explain the &#8216;chunk_handler&#8217;, I should point out that in theory we could use this opportunity to filter the input. If (for some reason) we wanted to handle different types of file in different ways, we could do this based on the <code>ContentType</code>. Annoyingly, there&#8217;s no way to inspect the name of the field (i.e., the name of the HTML input) that we&#8217;re handling at this stage.</p>
<p>As I mentioned, the <code>chunk_handler/4</code> function simply returns another function (which will accept one parameter) that MochiWeb will call once it has fetched a chunk. I&#8217;m using the term &#8216;chunk&#8217; casually: it can be <em>either</em> a raw chunk of data from the socket, <em>or</em> the <code>eof</code> atom. <strong>If the chunk being passed is not the <code>eof</code> atom, the function must return another function which will be used to handle the next chunk.</strong> However, if the function is passed the <code>eof</code> atom, we will return a value that we want to associate with this part of the multipart data. The value returned here will be the value that is stored in the property list we mentioned earlier (in <code>upload_photo/1</code>).</p>
<p>Here&#8217;s our <code>chunk_handler/4</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">chunk_handler</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">TempFilename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">File</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Next</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
        <span style="color: #186895;">case</span> <span style="color: #45b3e6;">Next</span> <span style="color: #186895;">of</span>
            eof <span style="color: #6bb810;">-&gt;</span>
                <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">close</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">File</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">TempFilename</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span>
            <span style="color: #45b3e6;">Data</span> <span style="color: #6bb810;">-&gt;</span>
                <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">write</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">File</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Data</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                <span style="color: #ff3c00;">chunk_handler</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">TempFilename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">File</span><span style="color: #109ab8;">&#41;</span>
        <span style="color: #186895;">end</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>So, don&#8217;t forget we&#8217;re returning a function here, which will get executed later on. There are two cases, as we&#8217;ve discussed:</p>
<ul>
<li>The <code>eof</code> case involves closing the file, and returning a tuple containing the original filename, the content-type and the temporary filename. We could return this in record form, or we may choose just to return the temporary filename if we didn&#8217;t care about the other parameters.</li>
<li>The non-<code>eof</code> case involves writing the chunk of data to the file, and then returning a function to handle the next chunk of data.</li>
</ul>
<p>This concludes the data-handling code. At this point you may wish to refer back to the <code>upload_photo/1</code>—this is where you would then be able to reference each of the uploaded files in the property list by it&#8217;s HTML input&#8217;s name. The value in the property list would be the <code>{Filename, ContentType, TempFilename}</code> tuple being returned by <code>chunk_handler/4</code>.</p>
<h2>A Semi-practical Example</h2>
<p>To turn this into something &#8216;useful&#8217;, I&#8217;ve put together a rudimentary photo gallery system.</p>
<p>We will adapt our <code>upload_photo/1</code> function to take another two parameters (the directory for the photos and a list of valid file extensions; the function will hence become <code>upload_photo/3</code>).</p>
<p>The total of our security features will be to check that the extension of the file corresponds to a recognised image type. Anyone will be able to upload files.</p>
<p>Here&#8217;s our function:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">upload_photo</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">PhotoDir</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidExtensions</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">FileHandler</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">handle_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Filename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ContentType</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span>
    <span style="color: #45b3e6;">Files</span> <span style="color: #014ea4;">=</span> mochiweb_multipart:<span style="color: #ff3c00;">parse_form</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">FileHandler</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">OriginalFilename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">TempFilename</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">proplists</span>:<span style="color: #ff3c00;">get_value</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;photo&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Files</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #186895;">case</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">member</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">filename</span>:<span style="color: #ff3c00;">extension</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">OriginalFilename</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ValidExtensions</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
        true <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #45b3e6;">Destination</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">PhotoDir</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">OriginalFilename</span><span style="color: #6bb810;">,</span>
            <span style="color: #186895;">case</span> <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">rename</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">TempFilename</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Destination</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span>
                ok <span style="color: #6bb810;">-&gt;</span>
                    <span style="color: #45b3e6;">Url</span> <span style="color: #014ea4;">=</span> <span style="color: #ff7800;">&quot;/&quot;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #45b3e6;">Req</span>:<span style="color: #ff3c00;">respond</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff9600;">302</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;Location&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Url</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Redirecting to &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Url</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
                <span style="color: #109ab8;">&#123;</span>error<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
                    <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">delete</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">TempFilename</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
                    <span style="color: #ff3c00;">html_response</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;An error occured whilst trying to move your file: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff3c00;">atom_to_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Reason</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff7800;">&quot;. Does the destination directory exist?&quot;</span><span style="color: #109ab8;">&#41;</span>
            <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span>
        false <span style="color: #6bb810;">-&gt;</span>
            <span style="color: #ff4e18;">file</span>:<span style="color: #ff3c00;">delete</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">TempFilename</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
            <span style="color: #ff3c00;">html_response</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Req</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;Invalid file type. File extension must be one of: &quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff4e18;">string</span>:<span style="color: #ff3c00;">join</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">ValidExtensions</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;, &quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">++</span> <span style="color: #ff7800;">&quot;. &lt;a href=<span style="color: #000099; font-weight: bold;">\&quot;</span>/<span style="color: #000099; font-weight: bold;">\&quot;</span>&gt;Try again?&lt;/a&gt;&quot;</span><span style="color: #109ab8;">&#41;</span>
    <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>You can <a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/12/mochiweb_uploads.zip">download</a> the rest of the code. It&#8217;s not very elegant, but I was keen to put together something for you to take home.</p>
<p>Obviously this isn&#8217;t the sort of thing you should consider making available to the world wide web, but hopefully it&#8217;ll be useful in explaining how to handle file uploads.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/12/handling-multipart-uploads-with-mochiweb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Book Review: Ext JS 3.0 Cookbook</title>
		<link>http://joefreeman.co.uk/blog/2009/11/book-review-ext-js-3-0-cookbook/</link>
		<comments>http://joefreeman.co.uk/blog/2009/11/book-review-ext-js-3-0-cookbook/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 20:08:05 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Ext JS]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=238</guid>
		<description><![CDATA[Packt Publishing sent me a copy of one of their new books for review: Ext JS 3.0 Cookbook, by Jorge Ramon. I have a few criticisms, but am generally very impressed with the book considering it has to be compared with some excellent documentation from the Ext JS team.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.packtpub.com/ext-js-3-0-cookbook?utm_source=joefreeman.co.uk&#038;utm_medium=bookrev&#038;utm_content=blog&#038;utm_campaign=mdb_001631">Packt Publishing</a> contacted me recently (it would seem, among many others) to ask if I&#8217;d like to review one of their new books: <em>Ext JS 3.0 Cookbook</em>, by Jorge Ramon. I was more than happy to oblige, since the book looked like it would contain some interesting material.</p>
<p><a href="http://www.packtpub.com/ext-js-3-0-cookbook?utm_source=joefreeman.co.uk&#038;utm_medium=bookrev&#038;utm_content=blog&#038;utm_campaign=mdb_001631"><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/ext-js-3.0-cookbook.png" alt="Ext JS 3.0 Cookbook" title="Ext JS 3.0 Cookbook" width="260" height="321" class="aligncenter size-full wp-image-240" /></a></p>
<h2>The Book&#8217;s Structure</h2>
<p>The book comprises &#8220;109 great recipes for building impressive rich internet applications using the Ext JS JavaScript library&#8221; (according to the front-cover—although I notice that the slogan on the picture above is different to my copy).</p>
<p>Each recipe starts with an introduction to the problem, and then a &#8216;How to do it&#8230;&#8217; section. This is usually followed by a &#8216;How it works&#8230;&#8217; section—where Jorge goes a little bit deeper into the inner workings of the Ext JS library. This is, I think, where the book shines. At lot of the examples in the book don&#8217;t seem to be any more special than the samples provided by ExtJS, but this added depth and explanation gives the examples more value than the ExtJS samples.</p>
<p>The book is split into ten chapters:</p>
<ol>
<li>DOM and Data Types, the Ext JS Way</li>
<li>Laying Out a Rich User Interface</li>
<li>Load, Validate, and Submit Forms</li>
<li>Fun with Combo Boxes and Date Fields</li>
<li>Using Grid Panels to Display and Edit Tabular Data</li>
<li>More Applications of Grid and List Views</li>
<li>Keeping Tabs on Your Trees</li>
<li>Making Progress with Menus and Toolbars</li>
<li>Well-charted Territory</li>
<li>Patterns in Ext JS</li>
</ol>
<p>The structure of the book is a little strange. It works fine as a reference book, but when reading from cover to cover, the concepts in the recipes rarely seem to flow from one to the next. For this reason, I think the book may not be ideal for beginners. It also means that some explanations get repeated in different recipes. However, the reference style of the book is benefitted by the &#8216;See also&#8230;&#8217; section at the end of each recipe, which directs you to related recipes.</p>
<p>The book would have gained, I think, from an initial chapter introducing Ext JS, rather than jumping straight into methods for detecting the user&#8217;s browser—which isn&#8217;t a particularly interesting topic to start on anyway.</p>
<h2>Code Samples</h2>
<p>The book is largely made up of code samples, as you would expect. However, I have a few small criticisms to make of the code:</p>
<ul>
<li>I feel that some of the samples are longer than they need to be (often a few pages long—the portlets recipe consists of nine pages of code interspersed with a few comments).</li>
<li>The choice of variable names is sometimes poor (although this may be following from the Ext JS convention).</li>
<li>Occasionally the formatting of the code is unhelpful—I noticed a comment had been wrapped, and on some examples the indentation was inconsistent.</li>
<li>Some of the code lines are highlighted in bold to make them stand out, but I found that quite often this was over-used, or highlighted the wrong areas—so turned out to be not so helpful.</li>
</ul>
<p>This is nit-picking really though—the code is generally quite appropriate to the topics in question, and if you&#8217;re familiar with Ext JS, you shouldn&#8217;t have problems understanding the code—but I&#8217;d have expected more attention to these areas by a publishing company that has probably never published a book <em>without</em> source code.</p>
<h2>Screenshots</h2>
<p>Some of the screenshots are not very clear and the annotations are sometimes a little confusing. In one case, the same half-page screenshot seemed to get duplicated four times, with very minor changes between them.</p>
<p>A little colour and better annotations would have really benefitted the book, especially since it is largely focussed on user interface design (and RRPs at £30.99/$49.99!)</p>
<h2>Further Observations</h2>
<p>I was surprised to see the occasional use of PHP, which didn&#8217;t actually seem to be required to explain the topic. Giving a snippet of raw JSON may have been more appropriate.</p>
<p>I&#8217;m not sure how other books from Packt are structured, but I think the book would have benefitted from &#8217;side boxes&#8217; in the margin giving little extra hints, or explaining certain parts of the code in more detail. In my experience, this is a common and useful feature of computing books.</p>
<h2>Conclusion</h2>
<p>It was very nice to see a chapter on the use of design patterns in Ext JS. This is a topic that I found difficult when I started working with the library, and I didn&#8217;t manage to find much helpful material online at the time. The recipe on creating customised &#8216;vtypes&#8217; was also interesting.</p>
<p>I feel like I&#8217;ve come up with plenty of criticisms, but in general I think the book is worth reading, even if just for the ~50% original material (which isn&#8217;t already available on the Ext JS samples page), and for the brief-but-valuable explanations of how things are working &#8216;under the hood&#8217;.</p>
<p>As a reference book, it feels very complete. I haven&#8217;t been able to think of any topics that it misses out. Mixing the recipes together should result in a substantial meal, and some very satisfied clients.</p>
<p>Thank you <a href="http://www.packtpub.com/ext-js-3-0-cookbook?utm_source=joefreeman.co.uk&#038;utm_medium=bookrev&#038;utm_content=blog&#038;utm_campaign=mdb_001631">Packt</a> for sending me the book, and thanks <a href="http://www.miamicoder.com/">Jorge</a> for putting so many useful examples together in one resource.</p>
<p><strong>Update:</strong> I requested a link to some sample content: here&#8217;s the whole of Chapter 3, <a href="http://www.packtpub.com/files/8709-ext-js-cookbook-sample-chapter-3-load-validate-and-submit-forms.pdf"><em>Load, Validate, and Submit Forms</em></a>, for you to download.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/11/book-review-ext-js-3-0-cookbook/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Java Swing Application for Testing PHP Snippets</title>
		<link>http://joefreeman.co.uk/blog/2009/11/a-java-swing-application-for-testing-php-snippets/</link>
		<comments>http://joefreeman.co.uk/blog/2009/11/a-java-swing-application-for-testing-php-snippets/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 16:34:44 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Swing]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=210</guid>
		<description><![CDATA[I've put together an application that lets you test PHP snippets without having to save them to a file. This should be useful to testing out built-in functions and regular expressions amongst other things. There's also a built-in web server so you can see the results in your browser. The article talks through how I've put it together. There are links to download the application and it's source code.]]></description>
			<content:encoded><![CDATA[<p>I occasionally find myself needing to try out short chunks of PHP code. For example, to try out a regular expression, or to see how a built-in function behaves if it&#8217;s not documented very well. Creating a file, moving it to my web server&#8217;s document root, loading it up in the browser often seems too much trouble. So I&#8217;ve put together a simple application using Swing to make this easier.</p>
<h2>Overview of the Application</h2>
<p>Let me summarise the functionality of the application, incase you just want to try it out. The app allows you to enter PHP code and then execute it without having to save it to file. You see the results instantly in the bottom half of the window.</p>
<p>There is also a built-in, simple (single-threaded) web server. This means you can view the results of execution in your browser—again, without having to save the file.</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/php-snippet-tester.png" alt="php-snippet-tester" title="php-snippet-tester" width="500" height="497" class="aligncenter size-full wp-image-222" /></p>
<p>I&#8217;m going to explain some of the technical aspects of putting the app together. If you&#8217;re just interested in using the app, scroll down to the bottom of the post for the download link.</p>
<h2>Working with the Command Line from Java</h2>
<p>PHP can be run from the command line. Details about this are on the <a href="http://php.net/manual/en/features.commandline.php">PHP website</a>, but in short, if you run <code>php</code> with no arguments, then it will take in source code from the <a href="http://en.wikipedia.org/wiki/Standard_streams">standard input</a>, execute it, and print out the result.</p>
<p>This can be achieve programatically from within the Java environment:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Get the runtime object</span>
<span style="color: #003399;">Runtime</span> rt <span style="color: #339933;">=</span> <span style="color: #003399;">Runtime</span>.<span style="color: #006633;">getRuntime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Run the command</span>
<span style="color: #003399;">Process</span> process <span style="color: #339933;">=</span> rt.<span style="color: #006633;">exec</span><span style="color: #009900;">&#40;</span>PHP_COMMAND<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Setup buffered input and output streams</span>
<span style="color: #003399;">BufferedReader</span> input <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedReader</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InputStreamReader</span><span style="color: #009900;">&#40;</span>process.<span style="color: #006633;">getInputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003399;">BufferedWriter</span> output <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BufferedWriter</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">OutputStreamWriter</span><span style="color: #009900;">&#40;</span>process.<span style="color: #006633;">getOutputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Send the source code and close the stream (to make EOF)</span>
output.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>code<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
output.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Read in the result, line by line and print it to the console</span>
<span style="color: #003399;">String</span> line<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>line<span style="color: #339933;">=</span>input.<span style="color: #006633;">readLine</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>line<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Wait for the process to terminate (not really necessary, because the process will terminate once it has closed the input stream anyway)</span>
<span style="color: #000066; font-weight: bold;">int</span> result <span style="color: #339933;">=</span> process.<span style="color: #006633;">waitFor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Note that <code>rt.exec(...)</code> and <code>process.waitFor()</code> can both potentially throw exceptions—<code>IOException</code> and <code>InterruptedException</code> respectively—which must be dealt with.</p>
<p>We could get the standard error stream aswell—using the same approach as with the output stream—but PHP doesn&#8217;t send anything to the error stream, so we don&#8217;t need to worry about it. If we wanted to do this, we&#8217;d need to read both streams in separate threads.</p>
<h2>Building the Swing User Interface</h2>
<p>Let&#8217;s look at how to setup the user interface. I&#8217;ll talk through a simplified version of the final application. We&#8217;ll look at a few of the Swing components individually.</p>
<h3><code>JFrame</code></h3>
<p>We&#8217;re going to make use of the <code>JFrame</code> class as our base. A common practice is to extend this class with your own, however, generally a more practical approach is to encapsulate the <code>JFrame</code> object by keeping track of the <code>JFrame</code> as a property within your class, and exposing methods as necessary.</p>
<p>We create a <code>JFrame</code>, set a layout (refer to the next section), a preferred size, the behaviour to associate with the window&#8217;s &#8216;close&#8217; button, pack it (to make sure the components get arranged properly) and then finally make the frame visible to the user:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">frame <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">JFrame</span><span style="color: #009900;">&#40;</span>FRAME_TITLE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
frame.<span style="color: #006633;">setLayout</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">BorderLayout</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
frame.<span style="color: #006633;">setPreferredSize</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Dimension</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">500</span>, <span style="color: #cc66cc;">500</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
frame.<span style="color: #006633;">setDefaultCloseOperation</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">JFrame</span>.<span style="color: #006633;">EXIT_ON_CLOSE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add components to the frame here</span>
&nbsp;
frame.<span style="color: #006633;">pack</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
frame.<span style="color: #006633;">setVisible</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3><code>BorderLayout</code></h3>
<p>Once the <code>JFrame</code> has been setup, we&#8217;ll use a <code>BorderLayout</code> to arrange our components on the window. Border layouts are a fairly common concept in user interface design. One component can be attached to each of five regions. Each region defines the position that the component appears at, and how its size changes as the parent component is resized. Border layouts can be nested within each other. The regions are:</p>
<ul>
<li><strong>PAGE_START</strong> &#8211; generally at the top of the page, resizes to fill the width of the parent component.</li>
<li><strong>PAGE_END</strong> &#8211; opposite side to PAGE_START.</li>
<li><strong>LINE_START</strong> &#8211; generally on the left of the page (but actually dependent on the user&#8217;s language), resizes to fill the height of the parent minus the height of any components at PAGE_START and PAGE_END.</li>
<li><strong>LINE_END</strong> &#8211; opposite side to LINE_END.</li>
<li><strong>CENTER</strong> &#8211; the remaining space in the middle of the layout, resizes to fill the available space.</li>
</ul>
<p>See the example below, which shows the positioning of the components:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/border-layout.png" alt="border-layout" title="border-layout" width="500" height="314" class="aligncenter size-full wp-image-213" /></p>
<h3><code>JSplitPane</code></h3>
<p>For our user interface we will divide the window into two: the top half for editing the PHP code, and the bottom half for viewing the results of the execution. We will allow the user to move the separator between the two components using a <code>JSplitPane</code>.</p>
<p>Using a <code>JSplitPane</code> is fairly straight forward. Pass each of the two components you&#8217;re splitting into the constructor, along with a specified orientation (either <code>VERTICAL_SPLIT</code> or <code>HORIZONTAL_SPLIT</code>). The location of the divider can also be given.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">JSplitPane</span> splitPane <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">JSplitPane</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">JSplitPane</span>.<span style="color: #006633;">VERTICAL_SPLIT</span>, inputPanel, outputPanel<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
splitPane.<span style="color: #006633;">setDividerLocation</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3><code>JTextArea</code> and <code>JScrollPane</code></h3>
<p>Both the editor and the area for displaying execution results will be based on <code>JTextArea</code>s. On their own, these components don&#8217;t support scrolling (e.g., for when there are more lines of text than will fit in the component). To support scrolling, we need to wrap them with <code>JScrollPane</code>s.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">JScrollPane</span> inputScrollPane <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">JScrollPane</span><span style="color: #009900;">&#40;</span>inputBox<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3><code>JButton</code> and <code>Action</code>s</h3>
<p>When the user wants to execute their code, they will click on an &#8216;Execute&#8217; button (which will be a <code>JButton</code>). There are a few ways to handle button clicks in Swing. One such method is to define an <code>Action</code> that will be associated with the button. This is a nice way to separate logic from the design of the user interface.</p>
<p>A button can be created like this:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #003399;">JButton</span> executeButton <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">JButton</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> ExecuteAction<span style="color: #009900;">&#40;</span>inputBox, outputBox<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The easiest way to create the action is to extend from <code>AbstractAction</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ExecuteAction <span style="color: #000000; font-weight: bold;">extends</span> <span style="color: #003399;">AbstractAction</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">JTextArea</span> inputBox<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">JTextArea</span> outputBox<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ExecuteAction<span style="color: #009900;">&#40;</span><span style="color: #003399;">JTextArea</span> inputBox, <span style="color: #003399;">JTextArea</span> outputBox<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Save these components for later</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">inputBox</span> <span style="color: #339933;">=</span> inputBox<span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">outputBox</span> <span style="color: #339933;">=</span> outputBox<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Set the name of the button</span>
        putValue<span style="color: #009900;">&#40;</span><span style="color: #003399;">AbstractAction</span>.<span style="color: #006633;">NAME</span>, <span style="color: #0000ff;">&quot;Execute&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> actionPerformed<span style="color: #009900;">&#40;</span><span style="color: #003399;">ActionEvent</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Event will be handled here</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Any objects that the action needs to access get passed to the constructor, and stored as properties of the action for use later. In this case, we&#8217;ll want to be able to get the source code from the input box and then put the result into the output box.</p>
<h2>Putting Together the <code>PhpRunner</code> Class</h2>
<p>We will put our earlier PHP-running code into it&#8217;s own class and package (<code>runner.PhpRunner</code>). The class will be constructed with two parameters:</p>
<ul>
<li>The PHP code to be run</li>
<li>An event listener (an object implementing the <code>OutputConsumer</code> interface)</li>
</ul>
<p>The <code>execute()</code> method can then be called. This will start the execution, and notify the event listener every time we get a new line of output back. This approach means that if a PHP script takes a long time to complete, we&#8217;ll be able to see the output as it happens, rather than having to wait for the whole script to finish executing.</p>
<p>The code is similar to the code at the top of the post, so I won&#8217;t paste it again. I have added calls to the event listener though. Refer to the source code if you&#8217;re interested.</p>
<h2>Threads and Thread Safety</h2>
<p>Introducing threads into a Swing application can be dangerous, since <strong>Swing&#8217;s components are not thread safe</strong>. Only one thread should be allowed to access the Swing components at any one time—this is known as the <em>event-dispatching thread</em> (EDT).</p>
<p>However, we don&#8217;t want the user interface to freeze whilst the PHP code is being executed, so it&#8217;s important that we don&#8217;t wait for output from within the EDT. The swing library provides a <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html"><code>SwingWorker</code></a> class, which makes working with threads a bit easier and safer. Fortunately, our <code>PhpRunner</code> fits nicely into this pattern. A cut-down version of the code looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">new</span> SwingWorker<span style="color: #339933;">&lt;</span>String, String<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #003399;">String</span> doInBackground<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Setup the PHP runner, and listen for any lines of output</span>
        PhpRunner runner <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PhpRunner<span style="color: #009900;">&#40;</span>code, <span style="color: #000000; font-weight: bold;">new</span> OutputConsumer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            @Override
            <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> output<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> line<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// Let the SwingWorker know there are more lines</span>
                publish<span style="color: #009900;">&#40;</span>line<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">// Execute, and return the result</span>
        <span style="color: #000000; font-weight: bold;">return</span> runner.<span style="color: #006633;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> process<span style="color: #009900;">&#40;</span>List<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span> chunks<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Add any output to the output box</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> chunk <span style="color: #339933;">:</span> chunks<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            outputBox.<span style="color: #006633;">append</span><span style="color: #009900;">&#40;</span>chunk <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> done<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// The operation has completed</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>.<span style="color: #006633;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>Adding a Built-in Web Server</h2>
<p>Sometimes it&#8217;s useful to be able to test the PHP output in a web browser. So we will add a very basic web server to the application. The user will be able to request execution of the code by loading a URL in their web browser.</p>
<p>First of all, we need to add a button to the user interface to allow the user to manually start and stop the web server. When the associated action is performed, we will either create a new HTTP server object, or stop an existing one.</p>
<p>The HTTP server doesn&#8217;t need to be very complicated at all. We don&#8217;t have to handle POST requests (just GET and HEAD requests) or even URLs since all requests to the server will execute the same script. We also only need to handle one request at a time—so the server can happily run on a single thread.</p>
<p>I don&#8217;t want to go into details of the server implementation here, but it&#8217;s worth nothing that this use of a web server does bring up the slightly unconventional approach of trying to get the contents of a Swing component from outside the EDT:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> value <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">SwingUtilities</span>.<span style="color: #006633;">invokeAndWait</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Runnable</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            value<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> inputBox.<span style="color: #006633;">getText</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Do nothing</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">return</span> value<span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The <code>value</code> variable must be declared final, since it&#8217;s accessed from a different thread. However, we want to be able to update the value, so the use of a single-element array is a bit of a hack to bypass the compiler&#8217;s warnings. A more elegant solution to this might involve wrapping the method in it&#8217;s own class, and using a class property instead of a final variable.</p>
<h2>Saving User Settings with the Preferences API</h2>
<p>Java provides an API that makes it very straight-forward to store and retrieve user preferences. These are used in our application to save a number of different parameters:</p>
<ul>
<li>The position and location of the window on the screen.</li>
<li>The position of the resizable split pane.</li>
<li>The last-used PHP code.</li>
<li>The specified font size.</li>
<li>The directory of the last file that was loaded.</li>
</ul>
<p>We can wrap the <code>Preferences</code> class in our own <code>Settings</code> class, which provides methods to get the required properties. Attaching a <code>WindowListener</code> to our <code>JFrame</code> means that we can attempt to save the settings when the application is closed.</p>
<h2>Conclusions</h2>
<p>I ended up making a few more changes to the application to those mentioned above. The buttons that are referred to above have been move to the menu bar (which was easy to do, since I was using <code>Action</code>s), and have associated keyboard shortcuts which make the application much easier to use. It&#8217;s now also possible to load files from disk, change the font size of the input and output boxes. I&#8217;ve also added a status bar which shows status messages for a period of time, and a &#8216;preferences&#8217; dialog which allows you to change the PHP command path and the web server port.</p>
<p>If the implementation of any of these features interests you, I suggest you download the source code to have a look.</p>
<p>To get a grasp of the structure of the project, the layout below may help:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/project-layout.png" alt="project-layout" title="project-layout" width="269" height="572" class="aligncenter size-full wp-image-230" /></p>
<p>I&#8217;m very pleased with the final product. The application&#8217;s concept is simple, but I think it adheres well to the <a href="http://en.wikipedia.org/wiki/Unix_philosophy">&#8220;do one thing and do it well&#8221;</a> philosophy.</p>
<p>I&#8217;ve also made a few minor tweaks to the application that will affect Mac users: moving the menu bar to the top of the screen, and setting the application&#8217;s title.</p>
<h2>Download</h2>
<p>If you&#8217;d like to download the application to give it a try yourself, or if you&#8217;d like to download the source code in its entirety, use the links below:</p>
<ul>
<li><a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/PHPTester.jar">Download application (packaged as a .jar file)</a></li>
<li><a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/11/php-tester-src.zip">Download source code (.zip archive)</a></li>
</ul>
<p>If you do try out the application, please let me know what you think.</p>
<h3>Requirements</h3>
<p>The application requires that you have both Java (version 1.6—although 1.5 might work) and PHP installed. The PHP executable must be accessible on your &#8216;path&#8217;. I have tested this on OS X and on a vanilla install of Vista (after installing Java and PHP).</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/11/a-java-swing-application-for-testing-php-snippets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FULLTEXT Search with MySQL and CodeIgniter</title>
		<link>http://joefreeman.co.uk/blog/2009/10/fulltext-search-with-mysql-and-codeigniter/</link>
		<comments>http://joefreeman.co.uk/blog/2009/10/fulltext-search-with-mysql-and-codeigniter/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 10:17:27 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=187</guid>
		<description><![CDATA[This article demonstrates how to use MySQL's FULLTEXT search feature from within CodeIgniter with a sample search application. It highlights a few of CodeIgniter's features such as the MVC pattern, pagination, custom configuration, custom helpers and profiling.]]></description>
			<content:encoded><![CDATA[<p>I was required to use CodeIgniter for a project recently. I&#8217;m generally not a big fan of the framework, but I have grown to like aspects of it. A lot of people seem to praise the documentation, the mass of examples and the active community. Maybe my hopes were set too high, but I was disappointed with all of these.</p>
<p>The thing I like about using a framework is <em>being told</em> how to do things, but for many the big attraction to CodeIgniter seems to be that it&#8217;s lightweight and you can do things how you like. I think this is the reason for the inconsistencies and low quality of example code. So I thought that I&#8217;d put together an article and example project showing a few of the tricks I&#8217;ve learnt, and <em>my</em> preferred CodeIgniter style.</p>
<p>I&#8217;m going to put together a simple application which shows off the search capabilities of MySQL, whilst exploring some of CodeIgniter&#8217;s features.</p>
<h2>Getting CodeIgniter Ready</h2>
<p>This is pretty basic stuff. <a href="http://codeigniter.com/downloads/">Download</a>, unzip, and dump the files somewhere into your web server&#8217;s directory. Setup a MySQL database and associated user and fill in the connection details in <code>application/config/database.php</code>.</p>
<p>Open up <code>application/config/config.php</code> and edit the <code>base_url</code> setting. This needs to be the web-visible URL to the directory that you put the CodeIgniter files into. If you did put them into your local web server&#8217;s root directory, this may be as simple as &#8216;http://localhost/&#8217;.</p>
<h2>Setting Up the Database</h2>
<p>You should already have a database setup, but we need a table to store the data. I&#8217;ve created a simple &#8216;pages&#8217; table. To make use of MySQL&#8217;s FULLTEXT search capabilities, you must setup an index on any fields that you want to be searchable. See the the SQL below:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> pages <span style="color: #66cc66;">&#40;</span>
  id int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  url text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  title text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  content text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  updated datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  FULLTEXT <span style="color: #993333; font-weight: bold;">KEY</span> content <span style="color: #66cc66;">&#40;</span>content<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM</pre></div></div>

<p>I&#8217;ve setup an index on the &#8216;content&#8217; field so that it will be searchable. Note also that FULLTEXT search is only available when using the MyISAM engine.</p>
<h2>Some Test Data</h2>
<p>In order to perform a decent evaluation of the searching mechanism, I realised that I would need some substantial data. I decided Wikipedia would make a good source of this data. Rather than export all three million articles, I limited myself to about two thousand of the <a href="http://en.wikipedia.org/wiki/Wikipedia:Featured_articles">featured articles</a>. I setup a script to scrape the list of featured articles and then used the Wikipedia <a href="http://en.wikipedia.org/wiki/Special:Export">export</a> feature to automatically copy across all the data into my database.</p>
<p>After over-coming an issue with the character encoding it soon because obvious that the Wikipedia markup wasn&#8217;t quite the format that I wanted. Hacking together a few regular expressions meant I could strip most of this out, leaving plain and readable content.</p>
<h2>Searching the Data</h2>
<p>At this point, the magic SQL to use takes the form: <code>MATCH (columns) AGAINST ('terms')</code>. Note that when <code>MATCH ... AGAINST</code> is used in the <code>WHERE</code> clause, the results are automatically sorted, so there&#8217;s no need to add an <code>ORDER BY</code> clause. An example:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> pages
<span style="color: #993333; font-weight: bold;">WHERE</span> MATCH <span style="color: #66cc66;">&#40;</span>content<span style="color: #66cc66;">&#41;</span> AGAINST <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'test'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span></pre></div></div>

<p>There are a few FULLTEXT gotchas you should be aware of:</p>
<ul>
<li>Something that I was stung by: if you have fewer than three rows of data, you won&#8217;t get any search results back.</li>
<li>Search strings have a minimum length. This is generally three or four characters, but depends on configuration. See below.</li>
<li>There is a collection of &#8216;<a href="http://dev.mysql.com/doc/refman/5.1/en/fulltext-stopwords.html">stopwords</a>&#8216; that MySQL will ignore (words like &#8216;the&#8217;, &#8216;however&#8217;, &#8216;hello&#8217;). If you try a search for any of these, you won&#8217;t get any results back.</li>
</ul>
<p>You can find out some of the configuration details by executing <code>SHOW VARIABLES LIKE  'ft%'</code>. You should get something like this:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/10/mysql-variables.png" alt="mysql-variables" title="mysql-variables" width="210" height="96" class="aligncenter size-full wp-image-203" /></p>
<p>A few different &#8216;modes&#8217; are available for searching. By default, a <a href="http://dev.mysql.com/doc/refman/5.1/en/fulltext-natural-language.html">natural language</a> search is performed. A boolean search is also possible, and allows a number of powerful operators to be used &#8211; refer to the <a href="http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html">documentation</a> for details.</p>
<p>It is also possible to use <a href="http://dev.mysql.com/doc/refman/5.1/en/fulltext-query-expansion.html">query expansion</a>. This roughly means that the search may return items where the search terms aren&#8217;t actually in the content, but instead there are words that are deemed similar. This is achieved by performing two searches. Where the second search uses content from high-ranking rows in the first search to perform the second search. This only tends to work well for short queries, otherwise less-relevant results will be returned.</p>
<p>More details on the full-text functionality can be found in the <a href="http://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html">MySQL documentation</a>.</p>
<h2>CodeIgniter and the MVC Pattern</h2>
<p>Let us return our attention to CodeIgniter&#8230;</p>
<p>The framework takes advantage of the ever-popular model-view-controller (MVC) pattern. Everyone knows you&#8217;re supposed to separate your domain-logic from presentation code, but the nice thing about the MVC pattern is that it&#8217;s constantly there to remind you.</p>
<p>I stick to a few basic rules:</p>
<ul>
<li>you can only touch the database from within the model</li>
<li>nothing should be echo-ed from the controller (or the model)</li>
<li>only one statement can appear inside each set of &lt;?php-tags and it should generally be either en echo or a control structure (use the <a href="http://php.net/manual/en/control-structures.alternative-syntax.php">alternative syntax</a>)</li>
</ul>
<p>If you find yourself breaking any of these rules, it&#8217;s probably a sign that it&#8217;s time to step back and re-think what you&#8217;re trying to achieve.</p>
<p>Let&#8217;s start off with the model. I only have one method here, which performs the searching. You may note that I&#8217;m using raw SQL here rather than using CodeIgniter&#8217;s Active Record implementation. This is just a personal preference &#8211; I think the CodeIgniter implementation is a bit messy compared to something <a href="http://www.phpactiverecord.org/">more RoR-like</a>.</p>
<p>The following code needs to go into <code>application/models/page_model.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Page_model <span style="color: #000000; font-weight: bold;">extends</span> Model
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">function</span> Page_model<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">Model</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Make the database available to all the methods</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">database</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> search<span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Execute our SQL statement and return the result</span>
        <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT url, title
                    FROM pages
                    WHERE MATCH (content) AGAINST (?) &gt; 0&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #339933;">,</span> <span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Next up is the view. Note that I&#8217;m religiously using the form helpers. This needs to go into <code>application/views/search_results.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_open<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">uri</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">uri_string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_label<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Search:'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'search-box'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_input<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'q'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'search-box'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_submit<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Search'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_close<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;ul&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            &lt;li&gt;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/a&gt;&lt;/li&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;/ul&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;p&gt;&lt;em&gt;There are no results for your query.&lt;/em&gt;&lt;/p&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Finally, pulling both the model and view together with the controller. The following code should go into <code>application/controllers/pages.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Pages <span style="color: #000000; font-weight: bold;">extends</span> Controller <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> search<span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// If the form has been submitted, rewrite the URL so that the search</span>
        <span style="color: #666666; font-style: italic;">// terms can be passed as a parameter to the action. Note that there</span>
        <span style="color: #666666; font-style: italic;">// are some issues with certain characters here.</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><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'q'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            redirect<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/pages/search/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'q'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Load the model and perform the search</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">model</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page_model'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">page_model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Render the view, passing it the necessary data</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_results'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'search_terms'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$search_terms</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'results'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">@</span><span style="color: #000088;">$results</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>At the beginning of the method, there is a reference to a <code>redirect</code> function. This is a helper function, and it&#8217;s part of the &#8216;url&#8217; group of helper functions. To use it, we could load the helper manually using: <code>$this->load->helper('url');</code>. However, because this group of helper functions is quite commonly used, we can load them automatically. To do this, we need to edit the <code>application/config/autoload.php</code> file:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$autoload</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'helper'</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: #0000ff;">'url'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>We should now have a working prototype. Make sure you have some data in your database (remember, at least three rows). Then steer your browser to the relevant URL, which should be something like: &#8216;http://localhost/index.php/pages/search&#8217;, enter some text to search (something that you know is in the database) and hit the &#8216;Search&#8217; button.</p>
<p>You should get something like this:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/10/screenshot-1.png" alt="screenshot-1" title="screenshot-1" width="500" height="505" class="aligncenter size-full wp-image-191" /></p>
<h2>Adding More Features</h2>
<p>To show off a bit more of CodeIgniter, I&#8217;ll add a few more features, including pagination, custom configuration files and custom helpers.</p>
<p>The CodeIgniter user guide boasts that the pagination class is &#8220;100% customizable&#8221;. I wouldn&#8217;t go that far, but you can certainly change a few things.</p>
<p>First of all, we need to modify our model so that it only returns a portion of the results, and also so that we can find out how many results in total our query would return.</p>
<p>The first problem is easily solved by adding an argument to the method, and a <code>LIMIT</code> to our SQL query. For the second problem, there are a few solutions, none of which seem very elegant:</p>
<ul>
<li>We can add a separate method to the model, which will return the total number of results. This means that generally we will always have to call both routines. Certainly not a disaster, but it just doesn&#8217;t seem very refined.</li>
<li>Alternatively, we can calculate this count from within our &#8217;search&#8217; method, and return both a collection of results and the total count together in some form of array structure. This is a bit abusive of the only-return-one thing methodology.</li>
<li>Or, we can pass a reference parameter to the method, set the value inside the method, and then access this variable from the controller. I think this works quite nicely because it&#8217;s discrete, but possibly a bit too subtle to be obvious to other developers.</li>
</ul>
<p>To keep things simple, I&#8217;m going to go with the first option. Let&#8217;s refactor the model:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Page_model <span style="color: #000000; font-weight: bold;">extends</span> Model <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Constructor as before</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> search<span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results_per_page</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Determine whether we need to limit the results</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results_per_page</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;LIMIT <span style="color: #006699; font-weight: bold;">$start</span>, <span style="color: #006699; font-weight: bold;">$results_per_page</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$limit</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Execute our SQL statement and return the result</span>
        <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT url, title, content
                    FROM pages
                    WHERE MATCH (content) AGAINST (?) &gt; 0
                    <span style="color: #006699; font-weight: bold;">$limit</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #339933;">,</span> <span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> count_search_results<span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Run SQL to count the total number of search results</span>
        <span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT COUNT(*) AS count
                    FROM pages
                    WHERE MATCH (content) AGAINST (?)&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">row</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Note that I&#8217;m also returning the &#8216;content&#8217; field in the SQL &#8211; this will be useful later. The next thing to do is to modify our controller. We need to load and initialise the pagination library. Here&#8217;s the modified &#8217;search&#8217; method:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Pages <span style="color: #000000; font-weight: bold;">extends</span> Controller <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> search<span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// If the form has been submitted, rewrite the URL so that the search</span>
        <span style="color: #666666; font-style: italic;">// terms can be passed as a parameter to the action. Note that there</span>
        <span style="color: #666666; font-style: italic;">// are some issues with certain characters here.</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><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'q'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            redirect<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/pages/search/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'q'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// Determine the number of results to display per page</span>
            <span style="color: #000088;">$results_per_page</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">config</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">item</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'results_per_page'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Load the model, perform the search and establish the total</span>
            <span style="color: #666666; font-style: italic;">// number of results</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">model</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page_model'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">page_model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results_per_page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$total_results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">page_model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count_search_results</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Call a method to setup pagination</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_setup_pagination<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/pages/search/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$search_terms</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$total_results</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results_per_page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Work out which results are being displayed</span>
            <span style="color: #000088;">$first_result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$start</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$last_result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">min</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$start</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$results_per_page</span><span style="color: #339933;">,</span> <span style="color: #000088;">$total_results</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Render the view, passing it the necessary data</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_results'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'search_terms'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$search_terms</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'first_result'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">@</span><span style="color: #000088;">$first_result</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'last_result'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">@</span><span style="color: #000088;">$last_result</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'total_results'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">@</span><span style="color: #000088;">$total_results</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'results'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">@</span><span style="color: #000088;">$results</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> _setup_pagination<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$total_results</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results_per_page</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Ensure the pagination library is loaded</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">library</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'pagination'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// This is messy. I'm not sure why the pagination class can't work</span>
        <span style="color: #666666; font-style: italic;">// this out itself...</span>
        <span style="color: #000088;">$uri_segment</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Initialise the pagination class, passing in some minimum parameters</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pagination</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'base_url'</span> <span style="color: #339933;">=&gt;</span> site_url<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'uri_segment'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$uri_segment</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'total_rows'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$total_results</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'per_page'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$results_per_page</span>
        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Let&#8217;s look at the changes we&#8217;ve made&#8230;</p>
<p>We have added an extra argument to the method. This means the URL will have another (optional) segment to it. It will be a number representing the record that we are starting on, and will get set automatically by the pagination code.</p>
<p>In order to determine the number of results to show on a page at a time, I have used the <a href="http://codeigniter.com/user_guide/libraries/config.html">config library</a>. In order to setup custom configuration for your application, it&#8217;s best to add a new file to the <code>application/config</code> directory, then set it to be autoloaded. Edit the <code>application/config/autoload.php</code> file again, and add &#8216;application&#8217; to the <code>$autoload['config']</code> array. Then create the <code>application/config/application.php</code> file, and put the following line in it:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$config</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'results_per_page'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span></pre></div></div>

<p>The next change we have made is to setup the pagination. I have put this code into a separate method. Note that the method name is prefixed with an underscore. This prevents the private method being called as an action on the controller. The code here is fairly self-explanatory.</p>
<p>We also pass some extra information over to our view. Which leads us to our next task of updating the view. But first, we will write our own custom helper functions for use within the view. These go into <code>application/helpers/search_helper.php</code>. The first function &#8211; <code>search_highlight($text, $search_terms)</code> &#8211; provides a way to highlight search terms in a string (there is a similar CodeIgniter helper, but it doesn&#8217;t quite do what we want). The second function &#8211; <code>search_extract($content, $search_terms, $number_of_snippets = 3, $snippet_length = 60)</code> &#8211; is a flaky attempt to generate an &#8216;excerpt&#8217; to accompany each result. An excerpt is made up of a number of &#8217;snippets&#8217; which should each contain at least one of the search terms. I won&#8217;t paste the code here since it&#8217;s far from elegant, but it&#8217;s available in the download.</p>
<p>Finally, the updated view. Note that we have to manually load the helper before using the helper functions. The pagination links are created using the <code>create_links</code> method.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'search'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_open<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">uri</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">uri_string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_label<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Search:'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'search-box'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_input<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'q'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'id'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'search-box'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'value'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_submit<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Search'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_close<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
        &lt;p&gt;Showing search results for '<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$search_terms</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>' (<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$first_result</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&amp;ndash;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$last_result</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> of <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$total_results</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>):&lt;/p&gt;
&nbsp;
        &lt;ul&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            &lt;li&gt;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> search_highlight<span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span><span style="color: #339933;">,</span> <span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/a&gt;&lt;br /&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> search_extract<span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">content</span><span style="color: #339933;">,</span> <span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/li&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;/ul&gt;
&nbsp;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">pagination</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">create_links</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;p&gt;&lt;em&gt;There are no results for your query.&lt;/em&gt;&lt;/p&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Here&#8217;s the result of trying it out in the browser again:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/10/screenshot-2.png" alt="screenshot-2" title="screenshot-2" width="500" height="605" class="aligncenter size-full wp-image-193" /></p>
<h2>Evaluation</h2>
<p>CodeIgniter comes with <a href="http://codeigniter.com/user_guide/libraries/benchmark.html">benchmarking</a> and <a href="http://codeigniter.com/user_guide/general/profiling.html">profiling</a> features. We can mark points in the execution, enable profiling, and have them have them output to the browser. For example, I might add marks around the calls to the model:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Mark the start of search</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">benchmark</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mark</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_start'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Load the model, perform the search and establish the total</span>
<span style="color: #666666; font-style: italic;">// number of results</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">model</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'page_model'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">page_model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">search</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$results_per_page</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$total_results</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">page_model</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">count_search_results</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$search_terms</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Mark the end of search</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">benchmark</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">mark</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'search_end'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The output at the bottom of the page would look something like this:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/10/profiling.png" alt="profiling" title="profiling" width="500" height="480" class="aligncenter size-full wp-image-196" /></p>
<p>We can see that the search on 1800 rows took 0.0138 seconds. This is 49% of the total execution time.</p>
<p>It is also possible to measure the time it takes to render the view by putting marks in the controller on either side of the <code>$this->load->view(...)</code> call. The view takes about 0.007 seconds to load. Without the generation of a page extract, it takes significantly less time: 0.002 seconds.</p>
<h2>Download</h2>
<p>I have packaged up the code for this example. Feel free to <a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/10/fulltext-search-with-mysql-and-codeigniter.zip">download</a> it.</p>
<h2>Other Search Solutions</h2>
<p>There are, of course, other search solutions available. Two such popular projects are <a href="http://www.sphinxsearch.com/">Sphinx</a> and <a href="http://lucene.apache.org/java/docs/">Lucene</a>. However, getting them compiled, installed and running doesn&#8217;t appear to be any simple task.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/10/fulltext-search-with-mysql-and-codeigniter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Lineographic Interpretations of Images, with an Etch-a-sketch</title>
		<link>http://joefreeman.co.uk/blog/2009/09/lineographic-interpretations-of-images-with-an-etch-a-sketch/</link>
		<comments>http://joefreeman.co.uk/blog/2009/09/lineographic-interpretations-of-images-with-an-etch-a-sketch/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 07:52:22 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Image Processing]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=155</guid>
		<description><![CDATA[A very condensed summary of the final year project of my degree: interpreting images and drawing them onto an etch-a-sketch. The project focusses on extracting features from the input images, deciding on a path to represent them lineographically and then displaying the results on an etch-a-sketch simulator. The project also involves drawing the images onto a 'real-life' etch-a-sketch.]]></description>
			<content:encoded><![CDATA[<p>A significant part of my computing degree was the individual project. I&#8217;d like to take this opportunity to talk about what I did, and hence provide a home for the project online. I&#8217;m not going to provide too many concrete details of the implementation—just outline the concept, talk about some of the challenges, and comment on the results.</p>
<h2>Selecting the Project</h2>
<p>I decided to propose my own project, rather than adopt one of the staff proposals. The idea being that I could choose something &#8216;fun&#8217; that I would retain interest in. The initial problem is coming up with an idea which covers the criteria of a good project:</p>
<ul>
<li>it should require a notable amount of research, rather than just being a relatively straight-forward implementation problem</li>
<li>it should be challenging enough so that it provides enough scope to demonstrate your abilities, whilst not being too difficult</li>
</ul>
<p>I came up with a few ideas, some of which I still have intentions of pursuing. But the idea that I finally settled on seemed like it had the best scope in terms of the above criteria.</p>
<p>During the period that I was trying to come up with a project idea, I came across a video of an etch-a-sketch artist. I don&#8217;t recall the exact video, but there are <a href="http://www.youtube.com/results?search_query=etch+a+sketch">plenty</a> online. I was amazed at the skill and patience of the artist. The sketches take days to complete, and it made me wonder if it was the sort of thing a computer could be made to do.</p>
<p>Essentially this leads to the question: <b>is a computer better at re-creating images with an etch-a-sketch than a human?</b> Various interpretations of the word &#8216;better&#8217; can be taken, but I will be looking at both the aesthetic results and the time it takes to complete the sketch.</p>
<p>The process of drawing an image on an etch-a-sketch is essentially that of <a href="http://en.wikipedia.org/wiki/Lineography">lineography</a>—drawing the whole image without taking your pen off the paper.</p>
<h2>Overview</h2>
<p>The project takes an image as its input and uses several techniques to extract features in the image before attempting to find a single path that can be used to represent the image. The path is then serialised, and passed either to an etch-a-sketch simulator, or over Bluetooth to an external device connected to a real etch-a-sketch.</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/overview.png" alt="overview" title="overview" width="400" height="108" class="aligncenter size-full wp-image-184" /></p>
<h2>Feature Extraction</h2>
<p>A number of techniques were experimented with for feature extraction. The most promising was based on segmentation of the image—specifically, by a region-growing technique, based on the intensity of pixels.</p>
<p>In order to reduce &#8216;noise&#8217;, segments with a size below a given threshold will be absorbed by neighbouring segments.</p>
<p>The next stage is to come up with a path around the edge of segments. To achieve this, a technique very similar to the &#8216;<a href="http://en.wikipedia.org/wiki/Marching_squares">marching squares</a>&#8216; algorithm is used. The following image shows a trivial example with four segments, with paths around the segments shown as dashed lines:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/segments.png" alt="segments" title="segments" width="350" height="243" class="aligncenter size-full wp-image-177" /></p>
<p>Once paths have been found, the problem can be represented as a graph, and hence becomes a path-finding exercise. The graph is made up of nodes that represent the points were more than two segments meet (marked as circles on the image above) and edges between the nodes are annotated with the corresponding paths in the image. The following image shows how a graph can be constructed from our previous example:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/graph.png" alt="graph" title="graph" width="300" height="235" class="aligncenter size-full wp-image-176" /></p>
<h2>Path Finding</h2>
<p>The path finding problem is quite unique. Features of the problem are shared with the <a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem">travelling salesman problem</a> in that we are aiming to traverse all the edges (although the TSP actually aims to visit all the nodes). However we aren&#8217;t searching for an optimal solution—instead we are looking for an aesthetically pleasing solution.</p>
<p>The edges between neighbouring segments that have significantly different colours (based on their Euclidean distance) are given a higher weight, and hence are more likely to be drawn over repeatedly. This results in a darker line in the finished sketch (refer to the images below).</p>
<p>The general technique is to traverse the graph with priority given to edges that we want to appear darker, and then back-tracing when we get stuck, to a point that allows us to continue to unused edges.</p>
<p>Occasionally &#8216;hops&#8217; must be taken, where two points must be joined so as to connect unconnected sections of the graph. In these cases, various alternative paths will be investigated to attempt to minimise disruption to the sketch. This usually results in a pair of smaller hops to and from a neighbouring line.</p>
<h2>Drawing Techniques</h2>
<p>A few techniques for drawing were experimented with. These were inspired by work done by human etch-a-sketch artists. Eventually, a hybrid technique was settled on: first to draw the outline of features in the image, and then to shade in regions based on their intensity. Shading was achieved by hatching—drawing backwards and forth over the region.</p>
<p>The following two images show relatively successful results being displayed on the simulator:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/tiffany.png" alt="tiffany" title="tiffany" width="500" height="256" class="aligncenter size-full wp-image-167" /></p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/peppers.png" alt="peppers" title="peppers" width="500" height="255" class="aligncenter size-full wp-image-165" /></p>
<p>See the image below for a screenshot of the &#8216;Sketcher&#8217; application: part of the framework developed for testing the various algorithms—referred to as &#8216;engines&#8217;:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/sketcher.png" alt="sketcher" title="sketcher" width="500" height="503" class="aligncenter size-full wp-image-173" /></p>
<h2>Hystereis</h2>
<p>Extensive testing with a real-life etch-a-sketch device revealed that a significant error would occur when trying to control the device programatically.</p>
<p>When a knob is rotated first in one direction, and then in the other, it takes a certain amount of rotation in the second direction before the pen begins to move again on the screen. This is due to tension building up in the strings within the device. I have referred to the error that this effect introduces as the &#8216;hysteresis&#8217;.</p>
<p>The effect is taken into account in the etch-a-sketch simulator so that it can be correctly accounted for when a path is being finalised. I won&#8217;t go into details here, but will mention that trying to simulate this effect in two dimensions is significantly more complicated than I was anticipating.</p>
<h2>Nxt-A-Sketch</h2>
<p>An extension to the project was to connect an actual etch-a-sketch to the program and draw out the sketch using stepper motors. To achieve this, a <a href="http://mindstorms.lego.com/Products/Default.aspx">Lego NXT brick</a> was used. A small C program was written to listen for commands via a Bluetooth channel and control the stepper motors. The images below shows how this physical connection was made:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/nxt-a-sketch-1.png" alt="nxt-a-sketch-1" title="nxt-a-sketch-1" width="500" height="375" class="aligncenter size-full wp-image-162" /></p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/nxt-a-sketch-2.png" alt="nxt-a-sketch-2" title="nxt-a-sketch-2" width="500" height="375" class="aligncenter size-full wp-image-163" /></p>
<p>This extension was relatively successful, and certainly made the final presentation more engaging. The device was able to recreate the sketches at a recognisable level, but would take a while to draw (about an hour)—though still significantly less time than a human artist would take. However, mechanical problems were frequently encountered with the device (likely caused by the wires slipping within the etch-a-sketch), which can be observed in the following photograph:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/nxt-a-sketch-3.png" alt="nxt-a-sketch-3" title="nxt-a-sketch-3" width="500" height="375" class="aligncenter size-full wp-image-164" /></p>
<h2>Conclusion</h2>
<p>At this stage, it is important to consider whether or not the project was successful. It is difficult to achieve this objectively, but it was certainly able to create sketches far better than the average human can, and sketches can be produced much quicker than those done by artists.</p>
<p>However, to answer this question in a slightly more analytical way, we can compare the results of the program with sketches done by artists. Below are two such comparisons. The first shows what I would consider a successful sketch of Mario; the second, a less successful interpretation of Da Vinci&#8217;s Mona Lisa (original images from <a href="http://etchasketchist.blogspot.com/2007/11/mario.html">here</a> and <a href="http://www21.flickr.com/photos/etcha/2314531739/">here</a>):</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/mario.png" alt="mario" title="mario" width="500" height="319" class="aligncenter size-full wp-image-161" /></p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/09/lisa.png" alt="lisa" title="lisa" width="500" height="319" class="aligncenter size-full wp-image-160" /></p>
<p>Clearly the project has room for improvement. A more intelligent method of feature detection is required, and it would be nice if the program had some form of <a href="http://www.thepaintingfool.com/">artistic abilities</a>.</p>
<p>Having said this, I like to think that the level of sketches being produced are better than I would be able to do had I spent the time that I devoted to the project instead practicing with the device.</p>
<p>Tests revealed that my accounting for hysteresis was particularly successful. However, I won&#8217;t go into details here, as the tests are rather complicated to explain.</p>
<h2>Further Information</h2>
<p>I have essentially attempted to squash a large portion of my report into this post, so a lot of the details have been glossed over or simplified. If anyone is interested in a specific area of the project, feel free to contact me for more information.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/09/lineographic-interpretations-of-images-with-an-etch-a-sketch/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Deploying an Erlang Appliance with SUSE Studio</title>
		<link>http://joefreeman.co.uk/blog/2009/08/deploying-an-erlang-appliance-with-suse-studio/</link>
		<comments>http://joefreeman.co.uk/blog/2009/08/deploying-an-erlang-appliance-with-suse-studio/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 08:27:54 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=123</guid>
		<description><![CDATA[An introduction to the newly released SUSE Studio, and method for setting up an Erlang application to run on an appliance. The process involves using an Erlang script to automatically setup a release file and boot script with the appropriate application dependencies and version numbers.]]></description>
			<content:encoded><![CDATA[<p>Having read Nat Friedman&#8217;s <a href="http://nat.org/blog/2009/07/suse-studio-10/">blog post</a> about the release of <a href="http://susestudio.com/">SUSE Studio</a>, I thought I&#8217;d take a look at it. I was also interested to find out how easy it is to create an appliance for a simple Erlang application.</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/suse-studio.png" alt="suse-studio" title="suse-studio" width="500" height="388" class="aligncenter size-full wp-image-127" /></p>
<h2>An Introduction to SUSE Studio</h2>
<p>I&#8217;m very impressed with SUSE Studio. It allows you to completely customise a Linux distribution and actually <strong>try it out</strong> (in the browser!) before you download it. This is, in my opinion, a pretty novel concept. At least at this scale.</p>
<p>Being able to have this control before you download the distribution obviously saves you from downloading a load of components that you don&#8217;t want. But the benefits don&#8217;t stop there:</p>
<ul>
<li><strong>Performing the administrative tasks of setting up the system can be performed <em>before</em> installation.</strong> This means a system can be deployed many times with minimum effort. Products like <a href="http://www.xen.org/">Xen</a> and <a href="http://www.vmware.com/">VMware</a> provide cost-effective ways to host several different systems together and keep them isolated from each other. If one of your applications breaks, the others are (potentially) isolated from the problem.</li>
<li><strong>Applications can be deployed and run in a pre-specified environment.</strong> This means their behaviour will be more predictable, and it will be easier to provide support for them. If a client is reporting problems, it will be much easier to replicate them yourself in a test environment.</li>
</ul>
<h2>My Experiences with SUSE Studio</h2>
<p>The service is currently by invite only. But having filled out the form, I got an invite the next day:</p>
<blockquote><p>Thank you for your interest in SUSE Studio, a new service that makes it quick and easy to create and test software appliances from your web browser.  We are pleased to invite you to try SUSE Studio.</p></blockquote>
<p>Sign in is via OpenID, which is nice.</p>
<p>The interface is very smooth and pleasant to use. Helpful messages appear in the left-hand column, which let you know where you&#8217;ve gone wrong, or give you tips as you go, and there&#8217;s a helpful &#8216;undo&#8217; feature. The site is also scattered with a selection of pleasing cartoons.</p>
<p>The &#8216;test drive&#8217; feature is <strong>awesome</strong>. Once you&#8217;ve finished configuring the system you need to build it, which takes a little time. When this is completed, just click on &#8216;Testdrive&#8217;, and a flash applet lets you watch the machine and interact with it (via VNC). Nat has an <a href="http://nat.org/blog/2009/07/linux-in-the-browser/">article</a> about some of the implementation details.</p>
<p>By enabling networking in test drive, you can also connect to the machine via SSH, or with your web browser if there&#8217;s a web server running.</p>
<p>Whilst Test Drive is running, you can even see a list of the files that have been modified, view <code>diff</code>s and download the modified files.</p>
<p>A impressive number of configuration parameters are at your disposal. You can even personalise the system by changing the logo and background image.</p>
<p>I noted a minor problem with the interface so I sent some feedback to the developers to check they were aware of it. I was impressed that they replied to me about ten minutes later (to say they were aware of the problem, thanks).</p>
<h2>Setting up an Appliance with Erlang</h2>
<p>The steps involved in setting up a basic appliance are very simple. I&#8217;ll skim over these steps and instead focus on those involved in setting up Erlang, and adding your application to the appliance. The aim is to have an Erlang application boot automatically when the appliance is started.</p>
<p>I started off with the openSUSE 11.1 &#8216;just enough&#8217; base template, which, for reference, has the following packages installed:</p>
<blockquote><p>aaa_base, branding-openSUSE, dhcpcd, grub, hwinfo, insserv, kbd, kernel-default, licenses, mkinitrd, module-init-tools, netcfg, openssh, openSUSE-build-key, openSUSE-release, PolicyKit, polkit-default-privs, procps, pwdutils, rpcbind, rpm, sysconfig, syslog-ng, vim</p></blockquote>
<p>The next step is to add a repository that contains the Erlang package. Select &#8216;Add repositories&#8230;&#8217; from the Software page, search for &#8216;erlang&#8217; and then add the suggested &#8216;devel:languages:erlang 11.1&#8242; repository. At time of writing, this will install Erlang release R12B-5.</p>
<p>Then, from the software page, search for &#8216;erlang&#8217;, and select the &#8216;erlang&#8217; package to be added.</p>
<p>Then make a few more configuration changes as required—for example, selecting the keyboard layout and time zone, and adding users (with default passwords that should obviously be changed following installation).</p>
<p>The next step is to add the Erlang application. I won&#8217;t go into details of setting up OTP applications, but I will explain how to <em>automatically</em> generate a bootable release file.</p>
<p>The release file needs to be setup to work with the installed version of Erlang, and the boot script needs to be generated in the same system environment (so we know we&#8217;ve got the correct versions of applications). To achieve this, I have written an Erlang script to be run when the appliance is first booted, which will generate a release file and accompanying boot script.</p>
<p>The main function that generates the release file is:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">generate_release</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Name</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Version</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Apps</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
    <span style="color: #45b3e6;">ErtsVsn</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">erlang</span>:<span style="color: #ff3c00;">system_info</span><span style="color: #109ab8;">&#40;</span>version<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">foreach</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">App</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff4e18;">application</span>:<span style="color: #ff3c00;">load</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">App</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Apps</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #45b3e6;">AppsVsns</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">lists</span>:<span style="color: #ff3c00;">map</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">App</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">App</span><span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">get_app_vsn</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">App</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#125;</span> <span style="color: #186895;">end</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Apps</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
    <span style="color: #109ab8;">&#123;</span>release<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">Name</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Version</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span>erts<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">ErtsVsn</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">AppsVsns</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>Download the <a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/make_release.erl">complete script</a> to try it out.</p>
<p>The application I am deploying is a simple echo server, but I won&#8217;t go into details here.</p>
<p>You need to package up your application (possibly including the compiled <code>make_release.erl</code> script), then upload it under the &#8216;Overlay files&#8217; section, and specify a directory to extract the files to. I put the application into <code>/usr/local/</code>, and use the following directory structure:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/directory-structure.png" alt="directory-structure" title="directory-structure" width="228" height="264" class="aligncenter size-full wp-image-132" /></p>
<p>(Note that the <code>echo-1.0.*</code> files wouldn&#8217;t be there when uploaded as they get generated by the script.)</p>
<p>If you&#8217;d like the application to be started when the system boots, you may wish to add this to a boot script. Boot scripts can be configured under the &#8216;Configuration&#8217; section. The following boot script will generate the release file when the system is booted for the first time. Following this, and on subsequent boots, the the Erlang application will be started.</p>
<p>My boot script looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>suse_studio_firstboot <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #666666; font-style: italic;"># Generate release for Echo Server</span>
  <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Generating release for Echo Server...&quot;</span>
  erl <span style="color: #660033;">-noshell</span> <span style="color: #660033;">-s</span> make_release <span style="color: #660033;">-pa</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>Echo-<span style="color: #000000;">1.0</span><span style="color: #000000; font-weight: bold;">/</span>ebin<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Start the echo server</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Starting Echo Server...&quot;</span>
erl <span style="color: #660033;">-boot</span> echo-<span style="color: #000000;">1.0</span> <span style="color: #660033;">-pa</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>Echo-<span style="color: #000000;">1.0</span> <span style="color: #660033;">-detached</span></pre></div></div>

<p>If you&#8217;re wondering, it looks like this script gets installed to: <code>/etc/init.d/suse_studio_custom</code></p>
<p>I installed the &#8216;open-vm-tools&#8217; package, as suggested (since I had specified that I wanted to generate a VMware virtual machine), and then set the machine to be built.</p>
<p>The appliance took a few minutes to build.</p>
<p>(Having requested a few more builds, it turns out that there&#8217;s a queueing system, so you may get lucky, or you may be in for a wait&#8230;)</p>
<p>Once the build was complete I was able to try it out in the browser:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/test-drive.png" alt="test-drive" title="test-drive" width="500" height="371" class="aligncenter size-full wp-image-128" /></p>
<p>After downloading it, double-clicking the .vmx file booted the machine in VMware:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/vmware.png" alt="vmware" title="vmware" width="500" height="411" class="aligncenter size-full wp-image-149" /></p>
<p>I was then able to test out the Erlang application by connecting with telnet:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/08/echo.png" alt="echo" title="echo" width="500" height="262" class="aligncenter size-full wp-image-148" /></p>
<h2>Alternative Approaches</h2>
<p>An alternative to actually installing your application is to just setup an appliance that has Erlang installed. This would still ease the setup process of the system and would just require you to add your Erlang application in after installation.</p>
<p>If you wanted the latest version of the Erlang system, it might be possible to upload the latest Erlang release as an &#8216;overlay file&#8217;, as opposed to fetching it from the repository. The benefit of using the repository is that it could be set to update automatically.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/08/deploying-an-erlang-appliance-with-suse-studio/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP Script to Compare MySQL Database Schemas</title>
		<link>http://joefreeman.co.uk/blog/2009/07/php-script-to-compare-mysql-database-schemas/</link>
		<comments>http://joefreeman.co.uk/blog/2009/07/php-script-to-compare-mysql-database-schemas/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 19:40:46 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=110</guid>
		<description><![CDATA[A brief description of the process involved in determining the schema of a MySQL database, and an accompanying tool, which will compare schemas of databases. The tool is able to compare databases that reside on separate hosts. This may be a useful tool for checking that databases have the same schema when deploying an application to separate hosts.]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>I&#8217;ve been working on a project recently that has a rather messy deployment strategy. This resulted in a minor glitch occurring during a recent deployment to a fairly high-profile site when a database table wasn&#8217;t updated.</p>
<p>Clearly the best solution to this problem would be to come up with a better deployment strategy, which is something we have been looking into. However, the problem has inspired me to write a small tool which collects information on the schema of a database so that it can be compared with other databases.</p>
<p>A slight twist to the problem comes from the requirement that the databases are more than likely to be hosted on different servers. Since the database servers are setup to only allow connections locally, we aren&#8217;t able to access both databases at the same time. Additionally, some of these servers are running PHP 4, so are lacking some newer PHP features.</p>
<h2>Fetching Schema Information from MySQL</h2>
<p>The MySQL queries to get information about tables are fairly straight-forward.</p>
<p>To get a list of the tables in a database, we can do:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">SHOW</span> <span style="color: #990099; font-weight: bold;">TABLES</span></pre></div></div>

<p>To get information about the fields in a specific table, we can do:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">SHOW</span> <span style="color: #990099; font-weight: bold;">COLUMNS</span> <span style="color: #990099; font-weight: bold;">FROM</span> table_name</pre></div></div>

<p>This returns a collection of information on each field:</p>
<ul>
<li>the names of fields,</li>
<li>the data type,</li>
<li>whether null values can be stored,</li>
<li>whether the column is indexed,</li>
<li>the default value of the field, and</li>
<li>whether the field uses <code>auto_increment</code></li>
</ul>
<p>Full details can be found on the <a href="http://dev.mysql.com/doc/refman/5.0/en/show-columns.html">manual page</a>.</p>
<h2>The PHP Script</h2>
<p>The tool consists of:</p>
<ul>
<li>a simple class for extracting the schema and performing the comparison between extracted schemas</li>
<li>a user interface to the class</li>
</ul>
<p>Since we need to be able to access databases on different hosts, the solution I am using is to serialise the schema information and give it back to the user. The user is then required to copy and paste this data from separate instances back into a form so that the comparison can be performed.</p>
<p>The user interface provides the user with a list of pre-configured databases to choose from, and also allows the user to enter connection details in the form. Arguably, the first option is more convenient and more secure.</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/options.png" alt="options" title="options" width="500" height="332" class="aligncenter size-full wp-image-117" /></p>
<p>The actual comparison of schemas works on three levels:</p>
<ol>
<li>We check both databases have the same tables</li>
<li>For each table, we check that the same fields are present</li>
<li>For each field, we check that the field&#8217;s parameters are the same</li>
</ol>
<p>Any discrepancies are then displayed to the user on a per-table basis.</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/comparison.png" alt="comparison" title="comparison" width="500" height="245" class="aligncenter size-full wp-image-116" /></p>
<h2>Download this Tool</h2>
<p>If you have a use for this tool, or are just interested to see how it works, feel free to <a href="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/php-script-to-compare-mysql-database-schemas.zip">download the code</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/07/php-script-to-compare-mysql-database-schemas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Estimating Pi with Monte Carlo Methods</title>
		<link>http://joefreeman.co.uk/blog/2009/07/estimating-pi-with-monte-carlo-methods/</link>
		<comments>http://joefreeman.co.uk/blog/2009/07/estimating-pi-with-monte-carlo-methods/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 12:58:16 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Erlang]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=77</guid>
		<description><![CDATA[This article demonstrates how to use a Monte Carlo simulation to calculate a value for Pi. An example program is given, written in Erlang, which can be run in a parallel environment. As well as the theory behind the method, we will look at how random numbers can be generated in Erlang and how to time Erlang programs. We will also perform an informal analysis of the results.]]></description>
			<content:encoded><![CDATA[<p>This article demonstrates how to use a Monte Carlo simulation to calculate a value for Pi. An example program is given, written in Erlang, which can be run in a parallel environment. As well as the theory behind the method, we will look at how random numbers can be generated in Erlang and how to time Erlang programs. We will also perform an informal analysis of the results.</p>
<h2>Monte Carlo Simulations</h2>
<p>A Monte Carlo method is the general name of an algorithm that uses a stochastic process to perform repeated random sampling on a problem. A statistical approach is used such that the numerical result to the problem can then be given by considering the number of &#8216;hits&#8217; that are achieved with the sampling.</p>
<p>The accuracy of the result, and the confidence in it, will increase as the number of samples we take increases.</p>
<p>More details about Monte Carlo methods can be found on the <a href="http://en.wikipedia.org/wiki/Monte_Carlo_method">Wikipedia article</a> and in the article <a href="http://library.lanl.gov/cgi-bin/getfile?00326866.pdf"><i>The Beginning of the Monte Carlo Method</i></a>.</p>
<h2>Estimating Pi</h2>
<p>A nice example of the use of Monte Carlo methods involves estimating a value for Pi. Let us consider a circle (with a radius of one) which is within a square (with edges of length two). Refer to the following diagram:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/diagram.gif" alt="Diagram" title="Diagram" width="350" height="301" class="aligncenter size-full wp-image-88" /></p>
<p>Now, by choosing random points within the square, we are able to calculate whether or not each point is within the circle or not. We can consider the analogy of throwing darts &#8216;randomly&#8217; at a dart board.</p>
<p>Since we know the area of a circle with radius <em>r</em> is given by:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/pirsquared.gif" alt="Area of a circle" title="Area of a circle" width="57" height="20" class="aligncenter size-full wp-image-80" /></p>
<p>And the area of a square with sides of length <em>x</em> is given by:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/xsquared.gif" alt="Area of a square" title="Area of a square" width="45" height="20" class="aligncenter size-full wp-image-83" /></p>
<p>And in our example, <em>r</em>=1 and <em>x</em>=2 and we know that the ratio, <em>R</em>, of the area of the circle to the total area of the square is:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/ratio.gif" alt="Ratio of areas" title="Ratio of areas" width="96" height="40" class="aligncenter size-full wp-image-82" /></p>
<p>Therefore, if we can come up with this ratio by experimentation, we can use it to derive a value for Pi:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/r4.gif" alt="Estimation of Pi" title="Estimation of Pi" width="51" height="20" class="aligncenter size-full wp-image-81" /></p>
<h2>Generating Random Numbers in Erlang</h2>
<p>Our method requires that we generate pairs of random numbers to identify the x- and y-co-ordinates of random points within the square. We need to make sure that these numbers have a uniform distribution—so that there is an equal chance of hitting any point on the dart board.</p>
<p>Fortunately, Erlang has just such a function: <code>random:uniform/0</code>. It is essentially as simple as calling <code>random:uniform()</code> to generate a random float between 0.0 and 1.0. Details can be found in the <a href="http://erlang.org/doc/man/random.html">manual page</a>.</p>
<h2>Seeding</h2>
<p>A note at the bottom of the manual page states:</p>
<blockquote><p>If a process calls <code>uniform/0</code> or <code>uniform/1</code> without setting a seed first, <code>seed/0</code> is called automatically.</p></blockquote>
<p>Interestingly, if a number of processes are spawned together, they will all produce the same list of &#8216;random&#8217; numbers. This is because each process is seeding the random number generator with the same default values.</p>
<p>To avoid this, we can seed the random number generator ourselves. The manual recommends using the built-in-function <code>now/0</code>. We can achieve this by calling the following line from the newly spawned process:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff3c00;">apply</span><span style="color: #109ab8;">&#40;</span>random<span style="color: #6bb810;">,</span> seed<span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">tuple_to_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span></pre></div></div>

<p>The function <code>now/0</code> will always return a unique value, so we can be confident that each process has a uniquely seeded random number generator. Incidentally, I am led to believe that <code>now/0</code> will actually move ahead of the system time if called frequently enough.</p>
<h2>Code Listing</h2>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>pi<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>start<span style="color: #014ea4;">/</span><span style="color: #ff9600;">2</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #666666; font-style: italic;">%% Start processing on the specified number of processes for the specified</span>
<span style="color: #666666; font-style: italic;">%% number of points. The number of points will be split equally amongst the</span>
<span style="color: #666666; font-style: italic;">%% number of processes.</span>
&nbsp;
<span style="color: #ff3c00;">start</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">PointsPerProcess</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Points</span> <span style="color: #014ea4;">div</span> <span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff3c00;">start_processes</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">PointsPerProcess</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">%% Spawn the required number of processes. Each process is passed the Pid of</span>
<span style="color: #666666; font-style: italic;">%% the current process so that it can send the result back.</span>
&nbsp;
<span style="color: #ff3c00;">start_processes</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff9600;">0</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_PointsPerProcess</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;Started all processes.~n&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #ff3c00;">start_processes</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">PointsPerProcess</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">self</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff3c00;">spawn</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">fun</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #ff3c00;">process_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">PointsPerProcess</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">end</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff3c00;">start_processes</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">PointsPerProcess</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">%% Wait for the results to come back from each of the processeses. The result</span>
<span style="color: #666666; font-style: italic;">%% from each process comes back containing the count of 'hits'. A total sum</span>
<span style="color: #666666; font-style: italic;">%% of hits is calculated, and then when all the results have come back, we</span>
<span style="color: #666666; font-style: italic;">%% give a calculated value for Pi.</span>
<span style="color: #666666; font-style: italic;">%% </span>
<span style="color: #666666; font-style: italic;">%% Note: this is heavily reliant on the spawned processes not crashing, and</span>
<span style="color: #666666; font-style: italic;">%% returning their respective counts. (Otherwise we will be waiting forever).</span>
&nbsp;
<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
&nbsp;
<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff9600;">0</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Sum</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">Pi</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Sum</span> <span style="color: #014ea4;">/</span> <span style="color: #45b3e6;">Points</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">*</span> <span style="color: #ff9600;">4</span><span style="color: #6bb810;">,</span>
	<span style="color: #ff4e18;">io</span>:<span style="color: #ff3c00;">format</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;Pi: ~w~n&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #45b3e6;">Pi</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Sum</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #186895;">receive</span>
		<span style="color: #109ab8;">&#123;</span>result<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span>
			<span style="color: #ff3c00;">wait_for_results</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Processes</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Sum</span> <span style="color: #014ea4;">+</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#41;</span>
	<span style="color: #186895;">end</span><span style="color: #6bb810;">.</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">%% Setup processing of the points. We seed the random number generator, count</span>
<span style="color: #666666; font-style: italic;">%% the number of 'hits' in the simulation, and then send the result back to</span>
<span style="color: #666666; font-style: italic;">%% the parent process.</span>
&nbsp;
<span style="color: #ff3c00;">process_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pid</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #ff3c00;">apply</span><span style="color: #109ab8;">&#40;</span>random<span style="color: #6bb810;">,</span> seed<span style="color: #6bb810;">,</span> <span style="color: #ff3c00;">tuple_to_list</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff3c00;">now</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #45b3e6;">Count</span> <span style="color: #014ea4;">=</span> <span style="color: #ff3c00;">test_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">0</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span>
	<span style="color: #45b3e6;">Pid</span> <span style="color: #014ea4;">!</span> <span style="color: #109ab8;">&#123;</span>result<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">.</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">%% Each point is chosen randomly and then tested to see whether it is within</span>
<span style="color: #666666; font-style: italic;">%% the circle. If it is, it is added to the count. Finally, the count is</span>
<span style="color: #666666; font-style: italic;">%% returned.</span>
&nbsp;
<span style="color: #ff3c00;">test_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff9600;">0</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span> <span style="color: #45b3e6;">Count</span><span style="color: #6bb810;">;</span>
&nbsp;
<span style="color: #ff3c00;">test_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Points</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span>
	<span style="color: #45b3e6;">X</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">random</span>:<span style="color: #ff3c00;">uniform</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">*</span> <span style="color: #ff9600;">2</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span>
	<span style="color: #45b3e6;">Y</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#40;</span><span style="color: #ff4e18;">random</span>:<span style="color: #ff3c00;">uniform</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">*</span> <span style="color: #ff9600;">2</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span>
	<span style="color: #45b3e6;">I</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">X</span><span style="color: #014ea4;">*</span><span style="color: #45b3e6;">X</span> <span style="color: #014ea4;">+</span> <span style="color: #45b3e6;">Y</span><span style="color: #014ea4;">*</span><span style="color: #45b3e6;">Y</span><span style="color: #6bb810;">,</span>
	<span style="color: #186895;">if</span>
		<span style="color: #45b3e6;">I</span> <span style="color: #014ea4;">&lt;</span> <span style="color: #ff9600;">1</span> <span style="color: #6bb810;">-&gt;</span>
			<span style="color: #ff3c00;">test_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Points</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span> <span style="color: #014ea4;">+</span> <span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">;</span>
		true <span style="color: #6bb810;">-&gt;</span>
			<span style="color: #ff3c00;">test_points</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Points</span> <span style="color: #014ea4;">-</span> <span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Count</span><span style="color: #109ab8;">&#41;</span>
	<span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></pre></div></div>

<p><b>Note</b>: I&#8217;ve only just started learning Erlang. Any feedback on my (simple) code will be welcomed.</p>
<h2>Timing an Erlang Program</h2>
<p>In order to experiment with running the program on multiple processors, it would be useful to be able to time the execution of the program. There is a module in Erlang for just this purpose. The function to use is: <code>timer:tc/3</code>. The three parameters that it takes are the module, the function and a list of arguments (these three parameters are commonly referred to as the MFA—module, function, arguments).</p>
<p>The following two lines allow us to time the program for ten thousand points running on one process and two processes, respectively:</p>

<div class="wp_syntax"><div class="code"><pre class="erlang" style="font-family:monospace;"><span style="color: #ff4e18;">timer</span>:<span style="color: #ff3c00;">tc</span><span style="color: #109ab8;">&#40;</span>pi<span style="color: #6bb810;">,</span> start<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #ff9600;">1</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">10000</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span>
<span style="color: #ff4e18;">timer</span>:<span style="color: #ff3c00;">tc</span><span style="color: #109ab8;">&#40;</span>pi<span style="color: #6bb810;">,</span> start<span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#91;</span><span style="color: #ff9600;">2</span><span style="color: #6bb810;">,</span> <span style="color: #ff9600;">10000</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></pre></div></div>

<p>The <code>timer:tc/3</code> function returns the tuple <code>{Time, Value}</code>, where <code>Time</code> is the time that the function took to execute, in <i>microseconds</i>, and <code>Value</code> is the return value from the function we are timing.</p>
<h2>Analysis of Results</h2>
<p>I&#8217;m currently running this code on my MacBook, so as a result of having two CPU cores, running with any more than two processes doesn&#8217;t give any speed benefits. It is nice to see, however, that running with two processes does give a significant speed increase over just a single process:</p>
<table>
<tr>
<th></th>
<th>One Processor</th>
<th>Two Processors</th>
<th>Speed-up</th>
</tr>
<tr>
<th>1 000 000 points</th>
<td>1.371</td>
<td>0.6980</td>
<td>1.964</td>
</tr>
<tr>
<th>10 000 000 points</th>
<td>13.44</td>
<td>6.854</td>
<td>1.961</td>
</tr>
</table>
<p>Times above (and below) are averaged from three runs of each scenario and given in seconds.</p>
<p>Let&#8217;s now look at the estimations given for Pi:</p>
<table>
<tr>
<th>Number of Points</th>
<th>Time taken (seconds)</th>
<th>Estimation for Pi</th>
</tr>
<tr>
<td>1 000 000</td>
<td>0.69800</td>
<td>3.14225733</td>
</tr>
<tr>
<td>10 000 000</td>
<td>6.8543</td>
<td>3.1418392</td>
</tr>
<tr>
<td>100 000 000</td>
<td>68.452</td>
<td>3.14162744</td>
</tr>
<tr>
<td>1 000 000 000</td>
<td>843.74</td>
<td>3.14161595</td>
</tr>
</table>
<p>We can observe the convergence to the true value of Pi on a graph:</p>
<p><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/convergence.gif" alt="Convergence to Pi" title="Convergence to Pi" width="500" height="339" class="aligncenter size-full wp-image-103" /></p>
<p>The blue line shows our estimation of Pi, and the red line shows the true value of Pi. Note that the x-axis has a logarithmic scale.</p>
<h2>Extensions</h2>
<p>A nice extension to my program would be to be able to leave it running, and be able to call a function to see what the current progress is. For example, the number of points tested, and the current estimation of Pi would be given.</p>
<p>It would also be interesting to see how the program behaved on more than two processors. Specifically, when the processors are distributed over a network. I don&#8217;t currently have any other machines set up to try this out on.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/07/estimating-pi-with-monte-carlo-methods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stock Quotes with Ext JS Charts</title>
		<link>http://joefreeman.co.uk/blog/2009/07/stocks-with-ext-js-charts/</link>
		<comments>http://joefreeman.co.uk/blog/2009/07/stocks-with-ext-js-charts/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 23:02:01 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Ext JS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://joefreeman.co.uk/blog/?p=4</guid>
		<description><![CDATA[An example to display stock indexes in an Ext JS chart. Including an introduction to Ext JS, a simple introductory Ext JS example and an introduction to the new charts feature. Concludes with a more comprehensive demo, showing some more of Ext's features.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll keep the introduction to <a href="http://extjs.com">Ext JS</a> brief, and then give a short primer to using Ext. Skip to the charts section if you&#8217;re already familiar with Ext. Or skip straight to the end if you just want to see the final demo.</p>
<p>Ext JS is yet another JavaScript library. However the emphasis is on UI widgets that allow you to build user interfaces in the browser. The concept is far from new, but the way Ext JS stands out from the contenders must be embarrassing. The library&#8217;s widgets are visually stunning, feature-rich, and yet still maintains high performance.</p>
<p>I will admit that I hadn&#8217;t heard of Ext JS before working on a project last year that used it. I&#8217;ve been doing freelance web development for about five years and I tend to keep quite up-to-date with web technologies, so I&#8217;m surprised that it had slipped under my radar.</p>
<p>Fairly recently, the team <a href="http://extjs.com/blog/2009/06/03/ext-js-30-rc2-release-stable-robust-and-enhanced/">announced</a> the latest release candidate of Ext 3.0. I wanted to experiment with some of the lesser-hyped new features, and so I&#8217;ve been working on a small experiment to display stock indexes using the new charts feature.</p>
<h2>Hello, world!</h2>
<p>Let&#8217;s start by walking through a really simple Ext example before we look at the charts.</p>
<p><a href="http://extjs.com/products/extjs/download.php">Download</a> the latest Ext release. Setup a simple HTML page and add a few includes:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="html" style="font-family:monospace;">&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;ext-3.0-rc3/resources/css/ext-all.css&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;ext-3.0-rc3/adapter/ext/ext-base.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;ext-3.0-rc3/ext-all-debug.js&quot;&gt;&lt;/script&gt;</pre></td></tr></table></div>

<p>At this point, we should be able to load the blank page in the browser without any errors.</p>
<p>The next step is to write some code to do something with the Ext library. So as not to upset the gods, we&#8217;re going to make a pop-up &#8216;hello world&#8217; window. The following is JavaScript code, so put it in a &lt;script&gt; tag or an external .js file.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Ext.<span style="color: #660066;">onReady</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">Window</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    title<span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hello, world!'</span><span style="color: #339933;">,</span>
    width<span style="color: #339933;">:</span> <span style="color: #CC0000;">280</span><span style="color: #339933;">,</span>
    height<span style="color: #339933;">:</span> <span style="color: #CC0000;">120</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>We use <code>Ext.onReady(...)</code> to setup a callback for when the DOM is loaded. This callback will create a new <code>Ext.Window</code> object, and show it. The parameter to the <code>Ext.Window</code> constructor is a configuration object.</p>
<p>The concept of configuration objects is used extensively throughout Ext, and it can be rather fiddly and difficult to get used to. You <i>have</i> to keep the Ext documentation open (see below) to know what parameters to use. In our simple example, all we do is specify the title and dimensions of the window.</p>
<p>Load the page in your browser. The result should look something like this:</p>
<p><a href="http://joefreeman.co.uk/projects/extstock/part-1.html"><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/hello-world.png" alt="hello-world" title="hello-world" width="290" height="128" class="aligncenter size-full wp-image-11" /></a></p>
<p>Notice that you can drag the window around the screen and resize it to your hearts content.</p>
<p>See the <a href="http://joefreeman.co.uk/projects/extstock/part-1.html">demo</a> or <a href="http://joefreeman.co.uk/projects/extstock/stocks-with-ext-js-charts.zip">download</a> the code.</p>
<p>For a nice collection of more advanced examples, check out the <a href="http://extjs.com/deploy/dev/examples/samples.html">samples</a> on the Ext site (they are also contained in the Ext download). These samples are great. My only criticism is that they can be a bit inconsistent in the way they implement features.</p>
<p>Another indispensable resource is the Ext <a href="http://extjs.com/deploy/dev/docs/">documentation</a> (this is also included in the download).</p>
<h2>Ext JS Charts</h2>
<p>In a way, it&#8217;s a shame that Flash has been used to implement the charts feature, since the library has achieved so much without resorting to it in the past. Nevertheless, the actual Flash applet has been well contained and even resizes smoothly with it&#8217;s container.</p>
<p>We can build on our simple example from above to add a chart to the window.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">Ext.<span style="color: #660066;">onReady</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">var</span> store <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">data</span>.<span style="color: #660066;">JsonStore</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'data.php'</span><span style="color: #339933;">,</span>
    baseParams<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
      symbol<span style="color: #339933;">:</span> <span style="color: #3366CC;">'GOOG'</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    autoLoad<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    root<span style="color: #339933;">:</span> <span style="color: #3366CC;">'data'</span><span style="color: #339933;">,</span>
    fields<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'date'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'close'</span><span style="color: #009900;">&#93;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">Window</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    title<span style="color: #339933;">:</span> <span style="color: #3366CC;">'GOOG'</span><span style="color: #339933;">,</span>
    width<span style="color: #339933;">:</span> <span style="color: #CC0000;">400</span><span style="color: #339933;">,</span>
    height<span style="color: #339933;">:</span> <span style="color: #CC0000;">300</span><span style="color: #339933;">,</span>
    items<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
      <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">chart</span>.<span style="color: #660066;">LineChart</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
        store<span style="color: #339933;">:</span> store<span style="color: #339933;">,</span>
        xField<span style="color: #339933;">:</span> <span style="color: #3366CC;">'date'</span><span style="color: #339933;">,</span>
        yField<span style="color: #339933;">:</span> <span style="color: #3366CC;">'close'</span>
      <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#93;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>We are introducing two new concepts here. First of all, the use of a &#8217;store&#8217;. In this case, a <code>JsonStore</code>. To quote the documentation:</p>
<blockquote><p>The Store class encapsulates a client side cache of Record objects which provide input data for Components [...]</p></blockquote>
<p>So basically, the store takes care of fetching and storing our data. The <code>JsonStore</code> uses a <code>JsonReader</code> to fetch the data in <a href="http://www.json.org">JSON</a> format, keeping the data completely separate from the UI component. The data is then represented internally as a series of <code>Record</code>s.</p>
<p>Let&#8217;s look at the configuration parameters we have set. The first parameter, <code>url</code>, is the URL that we will be loading the data from and <code>baseParams</code> specifies the parameters to send to this URL. By default the store doesn&#8217;t attempt to load the data straight away, so we specify the <code>autoLoad</code> parameter so that we don&#8217;t have to call <code>store.load()</code> ourselves later on. The <code>root</code> parameter tells the store where to look in the returned object for the bulk of the records, and <code>fields</code> is a short-hand way to specify the structure of the individual records.</p>
<p>The second new concept we have introduced is the addition of a component to the window. We have done this by specifying an array of components in the &#8216;items&#8217; property. The single item that we are adding is a <code>LineChart</code> component. The configuration here just links the component to the store we have defined, and specifies the fields to bind to the axes of the chart.</p>
<p>Once the store has been loaded, we should end up with this:</p>
<p><a href="http://joefreeman.co.uk/projects/extstock/part-2.html"><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/goog.png" alt="goog" title="goog" width="410" height="311" class="aligncenter size-full wp-image-13" /></a></p>
<p>See the <a href="http://joefreeman.co.uk/projects/extstock/part-2.html">demo</a> or <a href="http://joefreeman.co.uk/projects/extstock/stocks-with-ext-js-charts.zip">download</a> the code.</p>
<p>The current Ext documentation for styling the charts is fairly minimal. Since the underlying Flash applet for the charts is based on the one from the Yahoo UI Library, further information on styling the charts can be obtained from <a href="http://developer.yahoo.com/yui/charts/">their documentation</a>.</p>
<h2>Fetching the Data</h2>
<p>Let&#8217;s take a look now at the server-end of the process.</p>
<p>The data is generated by a PHP script which in turn gets the stock data from Yahoo. Yahoo kindly provide a CSV-formatted data set of the daily stock prices (including open, close, high and low values) which go back about five years. We don&#8217;t want to be pumping this much data to the browser, so we will take a few steps:</p>
<ol>
<li>Fetch the data if not already cached</li>
<li>Extract the closing price for each day</li>
<li>Cache the data</li>
<li>Choose an appropriate range of dates to display</li>
<li>Sample the remaining data to leave us with a suitable number of points that can be plotted</li>
<li>Return the data encoded as JSON</li>
</ol>
<p>We now have a simple web service that allows us to specify a number of parameters:</p>
<ul>
<li><b>symbol</b> — The stock ticker symbol. Required. Note that because we are using the Yahoo stock data we are limited to stocks listed on the NASDAQ.</li>
<li><b>start</b> — The start date. Specified as a Unix timestamp. Defaults to roughly one year ago.</li>
<li><b>span</b> — The timespan to get data for. Also given as a Unix timestamp. Defaults to roughly one year.</li>
<li><b>points</b> — The number of points to sample. Defaults to 20.</li>
</ul>
<p>An example result from the service would look a little like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;symbol&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;MSFT&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;data&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
  <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;date&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-07-24&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;close&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">25</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;date&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2008-08-12&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;close&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">28</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  <span style="color: #006600; font-style: italic;">//...</span>
<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>I won&#8217;t paste the PHP script here. It can, however be <a href="http://joefreeman.co.uk/projects/extstock/stocks-with-ext-js-charts.zip">downloaded</a>.</p>
<p>Once the data has been successfully loaded, an event is raised, which the chart has been listening for. The chart can then re-draw itself using the new data.</p>
<h2>Taking Things Further</h2>
<p>In an attempt to mature our example a little, and to highlight a few of Ext&#8217;s other features, I&#8217;ve put together a more substantial example. See the screenshot below, and refer to the <a href="http://joefreeman.co.uk/projects/extstock/">live demo</a>.</p>
<p><a href="http://joefreeman.co.uk/projects/extstock/"><img src="http://joefreeman.co.uk/blog/wp-content/uploads/2009/07/extstock.png" alt="extstock" title="extstock" width="500" height="324" class="aligncenter size-full wp-image-56" /></a></p>
<p>I won&#8217;t go into much detail here, other than to list some of the features that I&#8217;ve used:</p>
<ul>
<li>A <code>Viewport</code> together with the <code>BorderLayout</code> to ensure that the interface takes over all the space offered by the browser window.</li>
<li>A modal pop-up window which contains an auto-complete <code>ComboBox</code>. A list of the NASDAQ-100 are presented for the user to choose from.</li>
<li>A <code>TabPanel</code> to organise the different stocks that have been loaded. Selecting a different tab will change the chart being displayed, and closing a tab will unload the data and chart.</li>
<li>A <code>ListView</code> component, which is the new lightweight version of the <code>GridPanel</code>.</li>
<li>Some more advanced features of the <code>Chart</code> object—including making use of the <code>TimeAxis</code>, linking mouse movements to the <code>ListView</code> component, and making some changes to the chart&#8217;s style.</li>
</ul>
<p>I have left the JavaScript <a href="http://joefreeman.co.uk/projects/extstock/js/extstock.js">un-minified</a> so feel free to take a look at it.</p>
]]></content:encoded>
			<wfw:commentRss>http://joefreeman.co.uk/blog/2009/07/stocks-with-ext-js-charts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
