<?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>MichaelAHeap.com &#187; Work</title>
	<atom:link href="http://michaelaheap.com/category/work/feed/" rel="self" type="application/rss+xml" />
	<link>http://michaelaheap.com</link>
	<description>Reinventing The Wheel, One Step At A Time</description>
	<lastBuildDate>Fri, 27 Aug 2010 18:19:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>PHP 5.3: Anonymous (Lambda) Functions</title>
		<link>http://michaelaheap.com/2010/08/12/php-5-3-anonymous-lambda-functions/</link>
		<comments>http://michaelaheap.com/2010/08/12/php-5-3-anonymous-lambda-functions/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 17:41:02 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[lambda]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php 5.3]]></category>
		<category><![CDATA[sublive]]></category>

		<guid isPermaLink="false">http://michaelaheap.com/?p=913</guid>
		<description><![CDATA[A month or so ago I started work at a company called LiveLenz, who are a realtime sales provider for various POS systems. The project I've been working on is called Sublive, which is a piece if reporting software for Subway franchises. As a part of that system, I needed to provide detailed stats for&#8230


Related posts:<ol><li><a href='http://michaelaheap.com/2010/04/15/howto-codeigniter-partial-library/' rel='bookmark' title='Permanent Link: HowTo: Codeigniter Partial Library'>HowTo: Codeigniter Partial Library</a> <small>This assumes you have moved both the application and system...</small></li>
<li><a href='http://michaelaheap.com/2010/05/12/javascript-control-structures/' rel='bookmark' title='Permanent Link: Javascript Control Structures'>Javascript Control Structures</a> <small>I stumbled across http://eloquentjavascript.net/ and decided to have a flick...</small></li>
<li><a href='http://michaelaheap.com/2010/08/27/working-with-domdocument/' rel='bookmark' title='Permanent Link: Working with DOMDocument'>Working with DOMDocument</a> <small>Nowadays, most of the services we need to access programatically...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>A month or so ago I started work at a company called <a href="http://livelenz.com/">LiveLenz</a>, who are a realtime sales provider for various POS systems. The project I've been working on is called <a href="http://www.sublive.com">Sublive</a>, which is a piece if reporting software for Subway franchises.</p>
<p>As a part of that system, I needed to provide detailed stats for certain situations, such as a list of all transactions that had a discount code used. At first, I had one method per drilldown, all of which shared 90% of the same code. I tried and I tried, but I couldn't work out a way to abstract out the changes.</p>
<p>The only changes in the code were that the number of items counted differed depending on the section. E.g. On the sandwich breakdown all units with a specific PLU counted, but on the discount one, only items that had a discount applied are counted.</p>
<p>As the criteria used changed with every drill down, and wasn't just a case of comparing a field to a value. Passing in the field to check and the expected outcome as strings wasn't going to cut it.</p>
<h3>How To Solve It</h3>
<p>My first option was a giant if/else statement, or a switch. Pass in a parameter or two to the function and run whatever filter was needed. While this could have worked, it couples the two functions far too tightly for my liking, and I'm putting logic that belongs in multiple functions into one.</p>
<p>Another option was to conditionally define a function <code>filter</code> which took multiple optional parameters and automatically run it in the drilldown. Again, while this would have worked it's not a very clean way to do it.</p>
<p>Enter <a href="http://php.net/manual/en/functions.anonymous.php">lambda functions</a>. By passing a function as a parameter, we can filter the data as selectively as we like. By default, <code>$__filter</code> will be null, so we can check if there is a filter to run at all. If there is a filter, run it and handle the response however you want.</p>
<h3>Short Example</h3>
<p>Imagine we're selling things online. We have a model that returns all of the transactions made by a specific customer. We want to use all of this data to generate statistics - some for all the transactions returned, and some only for items that match our filter.</p>
<p>You can be as generic or as specific with your filters as you like. For example, this one will only return data for items that have a price of over £5.</p>
<pre class="brush: php;">
function over_five($__transaction_ids) {
        $filter = function($__item){
            return $__item-&gt;sale_price &gt; 5;
        };
        $r = $this-&gt;_filter_data(
                model::get_transactions($__transaction__ids),
                $filter
        );
    }
</pre>
<p>While that's a nice simple example, we can also make things more complicated by passing in variables to be used in the function with <code>use</code>. You simply tell the lambda function that you want to use a variable that's in the current scope, and pass it into your new function.</p>
<pre class="brush: php;">
function discounted($__transaction_ids, $__code) {
        $filter = function($__item) use ($__code){
            return $__item-&gt;discount_code == $__code;
        };
        $r = $this-&gt;_filter_data(
                model::get_transactions($__transaction__ids),
                $filter
        );
    }
</pre>
<p>Of course, the two filter functions are useless without the function that actually applies them to the data and gives us something back. This is a very contrived example, but hopefully it'll show how lambda functions can be used to filter out data we don't want.</p>
<pre class="brush: php;">
function _filter_data($__transactions, $__filter){
        // Some stats that we're gonna collect about the data
        $r = array();
        $r['total_items'] = 0;
        $r['matching_items'] = 0;
        $r['transaction_count'] = 0;
        $r['items_to_output'] = array();

        foreach ($__transactions as $k =&gt; $transaction){
            foreach($transaction as $item){
                    // Anything that's done every iteration goes before
                    // we try and filter the data
                    $r['total_items']++;

                    // If we have a filter provided
                    if (!is_null($__filter)){

                        // We pass in our item, and if it doesn't pass
                        // the filter skip the rest of this iteration
                        if (!$__filter($item)){
                            continue;
                        }

                    }

                    // Everything that we need to do if it matches
                    // the filter gets done down here
                    $r['matching_items']++;
                    array_push($r['items_to_output'], $item);
            }

            $r['transaction_count']++;
        }
       return $r;
    }
</pre>
<h3>Notes</h3>
<p>It's important to note that this only works in PHP 5.3 onwards. In previous versions, you would either have to use if/else or conditionally defined functions.</p>
<p>Additionally, you could also do all of your filtering within mySQL itself. Unfortunately this wasn't possible in this situation, as the database contains massive amounts of data. Running 6 big queries on the same page when I could have run one generic one and filtered it wasn't an option <img src='http://michaelaheap.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>


<p>Related posts:<ol><li><a href='http://michaelaheap.com/2010/04/15/howto-codeigniter-partial-library/' rel='bookmark' title='Permanent Link: HowTo: Codeigniter Partial Library'>HowTo: Codeigniter Partial Library</a> <small>This assumes you have moved both the application and system...</small></li>
<li><a href='http://michaelaheap.com/2010/05/12/javascript-control-structures/' rel='bookmark' title='Permanent Link: Javascript Control Structures'>Javascript Control Structures</a> <small>I stumbled across http://eloquentjavascript.net/ and decided to have a flick...</small></li>
<li><a href='http://michaelaheap.com/2010/08/27/working-with-domdocument/' rel='bookmark' title='Permanent Link: Working with DOMDocument'>Working with DOMDocument</a> <small>Nowadays, most of the services we need to access programatically...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://michaelaheap.com/2010/08/12/php-5-3-anonymous-lambda-functions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Party Like It&#8217;s r1999</title>
		<link>http://michaelaheap.com/2009/08/26/party-like-its-r1999/</link>
		<comments>http://michaelaheap.com/2009/08/26/party-like-its-r1999/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 13:03:22 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[revision]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[versatilia]]></category>

		<guid isPermaLink="false">http://michaelaheap.com/?p=559</guid>
		<description><![CDATA[Last night, I was trying to commit my final version of a site before it went live. For some reason, our pre-commit hook kept failing which I thought was strange as we've not changed it in quite a while. Fortunately, my boss was in and told me that he'd reserved commit 1999, and that he'd&#8230


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Last night, I was trying to commit my final version of a site before it went live. For some reason, our pre-commit hook kept failing which I thought was strange as we've not changed it in quite a while. Fortunately, my boss was in and told me that he'd reserved commit 1999, and that he'd fix it. I wondered why he'd reserved it, but his solution to the problem made me laugh, so I want to share it <img src='http://michaelaheap.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<blockquote><p>Author: john<br />
Date: 2009-08-25 17:42:12 +0100 (Tue, 25 Aug 2009)<br />
New Revision: 1999</p>
<p>Log:<br />
Party Like Its r1999!</p>
<p>Added:<br />
   versatilia/prince/<br />
   versatilia/prince/Party-Like-Its-Revision-1999.mp3</p></blockquote>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://michaelaheap.com/2009/08/26/party-like-its-r1999/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
