<?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>Geekality &#187; PHP</title>
	<atom:link href="http://www.geekality.net/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.geekality.net</link>
	<description>With a hint of Social Ineptitude</description>
	<lastBuildDate>Sun, 05 Feb 2012 17:53:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>PHP: One way of differing between DEV and PROD environments with Kohana</title>
		<link>http://www.geekality.net/2012/01/12/php-one-way-of-differing-between-dev-and-prod-environments-with-kohana/</link>
		<comments>http://www.geekality.net/2012/01/12/php-one-way-of-differing-between-dev-and-prod-environments-with-kohana/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 22:22:49 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Environment]]></category>
		<category><![CDATA[Kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Setup]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1904</guid>
		<description><![CDATA[Usually when I develop websites, they will be deployed to a domain, for example www.geekality.net. But when I develop this site locally, I usually want it to be in some sub-folder of localhost, since I usually have more than one &#8230; <a href="http://www.geekality.net/2012/01/12/php-one-way-of-differing-between-dev-and-prod-environments-with-kohana/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Usually when I develop websites, they will be deployed to a domain, for example www.geekality.net. But when I develop this site locally, I usually want it to be in some sub-folder of localhost, since I usually have more than one website going on, and I don&#8217;t want the trouble with virtual-hosts. So, to solve this for my Kohana websites I do the following simple thing. This technique would work for other websites programmed in PHP as well, but the PHP part would probably be a bit different.</p>
<p><span id="more-1904"></span></p>
<h2>Apache httpd.conf</h2>
<p>First of all, I add this to the end of my httpd.conf.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># Custom htaccess file<br />
AccessFileName .htaccess.local .htaccess</div></div>
<p>Make sure to check if there is already a line with AccessFileName though, and if it is, just edit that instead of adding another one <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<h2>Environment variables</h2>
<p>With that done, you can have one regular .htaccess which would be used in production and a local one for your machine.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#.htaccess<br />
SetEnv KOHANA_ENV production<br />
SetEnv KOHANA_BASE /<br />
RewriteBase /</div></div>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#.htaccess.local<br />
SetEnv KOHANA_ENV development<br />
SetEnv KOHANA_BASE /geekality/<br />
RewriteBase /geekality/</div></div>
<p>These two files can now live side by side, checked in to source control, and not cause any trouble. Alternatively you could set the local one to be ignored so that other developers could create their own setup.</p>
<h2>Kohana bootstrap</h2>
<p>Now comes the Kohana specific part. In my application/bootstrap.php I have the following (among other stuff of course).</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'KOHANA_ENV'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; Kohana<span style="color: #339933;">::</span><span style="color: #000088;">$environment</span> <span style="color: #339933;">=</span> <span style="color: #990000;">constant</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Kohana::'</span><span style="color: #339933;">.</span><span style="color: #990000;">strtoupper</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'KOHANA_ENV'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
Kohana<span style="color: #339933;">::</span><span style="color: #004000;">init</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; <span style="color: #0000ff;">'base_url'</span> &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'KOHANA_BASE'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'index_file'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'profile'</span> <span style="color: #339933;">=&gt;</span> Kohana<span style="color: #339933;">::</span><span style="color: #000088;">$environment</span> <span style="color: #339933;">!==</span> Kohana<span style="color: #339933;">::</span><span style="color: #004000;">PRODUCTION</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'caching'</span> <span style="color: #339933;">=&gt;</span> Kohana<span style="color: #339933;">::</span><span style="color: #000088;">$environment</span> <span style="color: #339933;">!==</span> Kohana<span style="color: #339933;">::</span><span style="color: #004000;">DEVELOPMENT</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'errors'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>And that&#8217;s pretty much all there is to it. This way I don&#8217;t have to worry about not overwriting the .htaccess on my production server or stuff like that. The .htaccess is untouched and just for the production environment <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1904&amp;md5=0e58ab261f2f2ee24146da7ab4c4b525" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2012/01/12/php-one-way-of-differing-between-dev-and-prod-environments-with-kohana/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Measure upload time and speed with PHP and Javascript</title>
		<link>http://www.geekality.net/2011/11/20/measure-upload-time-and-speed-with-php-and-javascript/</link>
		<comments>http://www.geekality.net/2011/11/20/measure-upload-time-and-speed-with-php-and-javascript/#comments</comments>
		<pubDate>Sun, 20 Nov 2011 07:34:42 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Timer]]></category>
		<category><![CDATA[Upload]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1876</guid>
		<description><![CDATA[Stumbled upon a question on StackOverflow the other day which got me curious. The question was about how to measure how long it takes to upload a file to a PHP script. This is what had been tried out: $upload_time &#8230; <a href="http://www.geekality.net/2011/11/20/measure-upload-time-and-speed-with-php-and-javascript/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Stumbled upon <a href="http://stackoverflow.com/q/8181291/39321">a question on StackOverflow</a> the other day which got me curious. The question was about how to measure how long it takes to upload a file to a PHP script. This is what had been tried out:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$upload_time</span> <span style="color: #339933;">=</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_TIME'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></div></div>
<p>This pretty much always returns zero, even though the uploading actually took many seconds, because the request start time is <em>after</em> the server has received the post data. That we actually just get how long the script took to run, which of course is pretty close to zero seconds. So, what can we do?</p>
<ol>
<li>Right before data is posted, nudge the server with an AJAX call which stores the current timestamp in a session variable
<li>Post the data
<li>Compare current timestamp with the one stored in step 1
</ol>
<p>Wasn&#8217;t sure how it would work, but seems to work pretty well. There will of course be a very tiny difference since the AJAX request will be a bit part of the time, but compared to the upload time it shouldn&#8217;t matter much. Anyways, here&#8217;s how you could do it <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1876"></span></p>
<p>In your HTML you need your form, obviously.</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><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.php&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><br />
&nbsp; <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;file&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; <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><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></div>
<p>And then we need the Javascript which does the AJAX request (using <a href="http://api.jquery.com/jQuery.ajax/">jQuery</a>). Notice that this makes sure we have gotten a response from the timer script before we actually submit the form.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span><br />
&nbsp; $<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><br />
&nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'form'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">submit</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><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'start-timer.php'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'POST'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</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: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">submit</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: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></div></div>
<p>The start timer simply stores a timestamp in a session variable.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'time'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Then in the upload script we simply need to compare that time with the current timestamp to figure out how long this took.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$upload_time</span> <span style="color: #339933;">=</span> <span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$_SESSION</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'time'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #666666; font-style: italic;">// You should of course probably also check if the upload was OK and all that ;)</span></div></div>
<p>And that&#8217;s pretty much all there is to it! Working sample at <a href="http://samples.geekality.net/upload-timer">samples.geekality.net/upload-timer</a>. </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1876&amp;md5=f6f20c5127f2d1d601c665e890832113" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/11/20/measure-upload-time-and-speed-with-php-and-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: Simple compression of JSON data</title>
		<link>http://www.geekality.net/2011/10/31/php-simple-compression-of-json-data/</link>
		<comments>http://www.geekality.net/2011/10/31/php-simple-compression-of-json-data/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 00:57:35 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Compression]]></category>
		<category><![CDATA[GZ]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1847</guid>
		<description><![CDATA[Just discovered how super simple it was to add some gz compression when for example providing JSON data from PHP. All you need is regular output buffering with the ob_gzhandler as output callback. // Fetch some data $data = get_data&#40;&#41;; &#8230; <a href="http://www.geekality.net/2011/10/31/php-simple-compression-of-json-data/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Just discovered how super simple it was to add some gz compression when for example <a href="/?p=1021" title="How to easily provide JSON and JSONP">providing JSON data</a> from PHP.</p>
<p><span id="more-1847"></span></p>
<p>All you need is regular output buffering with the <a href="http://php.net/manual/en/function.ob-gzhandler.php">ob_gzhandler</a> as output callback.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Fetch some data</span><br />
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> get_data<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Turn on output buffering with the gzhandler</span><br />
<span style="color: #990000;">ob_start</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ob_gzhandler'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Output as normal</span><br />
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>The cool thing is that it actually looks at what the browser accepts before doing anything.</p>
<blockquote><p>Before ob_gzhandler() actually sends compressed data, it determines what type of content encoding the browser will accept (&#8220;gzip&#8221;, &#8220;deflate&#8221; or none at all) and will return its output accordingly. All browsers are supported since it&#8217;s up to the browser to send the correct header saying that it accepts compressed web pages.</p></blockquote>
<p>Tried adding it for a text field with timezone auto-completing for example, and without this handler:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Content-Length &nbsp; &nbsp;5517<br />
Content-Type &nbsp; &nbsp; &nbsp;application/json</div></div>
<p>With this handler:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Content-Encoding &nbsp;gzip<br />
Vary &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Accept-Encoding<br />
Content-Length &nbsp; &nbsp;1775<br />
Content-Type &nbsp; &nbsp; &nbsp;application/json</div></div>
<p>Do like! <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':lol:' class='wp-smiley smiley-9' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1847&amp;md5=c890086131603997dc9fbb335df67a82" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/10/31/php-simple-compression-of-json-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick installation of LAMP for Kohana on Ubuntu</title>
		<link>http://www.geekality.net/2011/09/18/quick-installation-of-lamp-on-ubuntu/</link>
		<comments>http://www.geekality.net/2011/09/18/quick-installation-of-lamp-on-ubuntu/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 16:06:49 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1836</guid>
		<description><![CDATA[Needed to get a LAMP environment up and running for some Kohana development. Starting with a more or less fresh install of Ubuntu, here&#8217;s what I did. Install LAMP $ sudo apt-get update $ sudo apt-get install lamp-server^ Install PHP &#8230; <a href="http://www.geekality.net/2011/09/18/quick-installation-of-lamp-on-ubuntu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Needed to get a <a href="http://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a> environment up and running for some <a href="http://kohanaframework.org/">Kohana</a> development. Starting with a more or less fresh install of Ubuntu, here&#8217;s what I did.</p>
<p><span id="more-1836"></span></p>
<h3>Install LAMP</h3>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get update</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> lamp-server^</div></div>
<h3>Install PHP modules used by Kohana</h3>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> php5-curl php5-gd php5-mcrypt</div></div>
<h3>Enable rewrite module</h3>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</span> a2enmod rewrite</div></div>
<h3>Allow for .htaccess overrides</h3>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">vim</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>apache2<span style="color: #000000; font-weight: bold;">/</span>sites-available<span style="color: #000000; font-weight: bold;">/</span>default</div></div>
<p>Find the part about the /var/www directory and set AllowOverride from None to All. Then save the file.</p>
<h3>Remove annoying Apache warning</h3>
<p>If you restart Apache now, you&#8217;ll get a warning like this:</p>
<blockquote><p>apache2: Could not reliably determine the server&#8217;s fully qualified domain name, using 127.0.1.1 for ServerName</p></blockquote>
<p>To prevent that, add a line with &#8220;ServerName localhost&#8221; to the httpd.conf file.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">vim</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>apache2<span style="color: #000000; font-weight: bold;">/</span>httpd.conf</div></div>
<h3>Restart Apache</h3>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</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>apache2 restart</div></div>
<p></code></p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1836&amp;md5=93d18a7d2d8bd2ce0e7570d487f0fa0d" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/09/18/quick-installation-of-lamp-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: What&#8217;s a valid JavaScript identifier (or function name)?</title>
		<link>http://www.geekality.net/2011/08/03/valid-javascript-identifier/</link>
		<comments>http://www.geekality.net/2011/08/03/valid-javascript-identifier/#comments</comments>
		<pubDate>Wed, 03 Aug 2011 15:09:49 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Language Spec]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Regular Expression]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1739</guid>
		<description><![CDATA[After another reply to a question I&#8217;ve had on StackOverflow for a while, I decided that I perhaps should add another level of security to my method of providing JSONP from PHP. The way I did it before, I didn&#8217;t &#8230; <a href="http://www.geekality.net/2011/08/03/valid-javascript-identifier/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After another reply to <a href="http://stackoverflow.com/a/6892827/39321" title="PHP: Is this safe for providing JSONP?" class="broken_link">a question</a> I&#8217;ve had on StackOverflow for a while, I decided that I perhaps should add another level of security to my method of <a href="/?p=1021" title="How to easily provide JSON and JSONP">providing JSONP</a> from PHP. The way I did it before, I didn&#8217;t do any checking on the provided callback. This means that someone could technically put whatever they wanted in there, including malicious code. So, therefore it might be a good idea to check if the callback, which should be a function name, actually <em>is</em> a valid function name. But,</p>
<p><span id="more-1739"></span></p>
<h2>What is valid?</h2>
<p>To figure that out, we need a look in the <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf" title="ECMA-262, 5.1 Edition / June 2011">ECMAScript Language Specification</a>. In chapter 13 on functions, we find that a function name is a so-called identifier, which is described in chapter 7.6. There we can find the following facts:</p>
<table style="font-size: 80%">
<tr>
<th>Identifier</th>
<td>&lt;IdentifierName&gt; <strong>but not</strong> &lt;ReservedWord&gt;</td>
</tr>
<tr>
<th>IdentifierName</th>
<td>&lt;IdentifierStart&gt;<br />
&lt;IdentifierName&gt; &lt;IdentifierPart&gt;
</td>
</tr>
<tr>
<th>IdentifierStart</th>
<td>&lt;UnicodeLetter&gt;<br />
$<br />
_<br />
\ &lt;UnicodeEscapeSequence&gt;</td>
</tr>
<tr>
<th>IdentifierPart</th>
<td>&lt;IdentifierStart&gt;<br />
&lt;UnicodeCombiningMark&gt;<br />
&lt;UnicodeDigit&gt;<br />
&lt;UnicodeConnectorPunctuation&gt;<br />
&lt;ZWNJ&gt;<br />
&lt;ZWJ&gt;</td>
</tr>
<tr>
<th>UnicodeLetter</th>
<td>Uppercase letter (Lu)<br />
Lowercase letter (Ll)<br />
Titlecase letter (Lt)<br />
Modifier letter (Lm)<br />
Other letter (Lo)<br />
Letter number (Nl)</td>
</tr>
<tr>
<th>UnicodeCombiningMark</th>
<td>Non-spacing mark (Mn)<br />
Combining spacing mark (Mc)</td>
</tr>
<tr>
<th>UnicodeDigit</th>
<td>Decimal number (Nd)</td>
</tr>
<tr>
<th>UnicodeConnectorPunctuation</th>
<td>Connector punctuation (Pc)</td>
</tr>
<tr>
<th>UnicodeEscapeSequence</th>
<td>The definitions of the nonterminal UnicodeEscapeSequence is given in 7.8.4</td>
</tr>
<tr>
<th>ZWNJ</th>
<td>U+200C (<a href="http://en.wikipedia.org/wiki/ZWNJ">Zero-width non-joiner</a> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=')' class='wp-smiley smiley-20' /> </td>
</tr>
<tr>
<th>ZWJ</th>
<td>U+200D (<a href="http://en.wikipedia.org/wiki/ZWJ">Zero-width joiner</a> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=')' class='wp-smiley smiley-20' /> </td>
</tr>
<tr>
<th>ReservedWord</th>
<td>&lt;Keyword&gt;<br />
&lt;FutureReservedWord&gt;<br />
&lt;NullLiteral&gt;<br />
&lt;BooleanLiteral&gt;</td>
</tr>
<tr>
<th>Keyword</th>
<td>break, do, instanceof, typeof, case, else, new, var, catch, finally, return, void, continue, for, switch, while, debugger, function, this, with, default, if, throw, delete, in, try</td>
</tr>
<tr>
<th>FutureReservedWord</th>
<td>class, enum, extends, super, const, export, import<br />
    implements, let, private, public, yield, interface, package, protected, static</td>
</tr>
<tr>
<th>NullLiteral</th>
<td>null</td>
</tr>
<tr>
<th>BooleanLiteral</th>
<td>true, false</td>
</tr>
</table>
<p>Looks long, but not too complicated.</p>
<h2>Checking if a string is valid</h2>
<p>To check if a string is a valid identifier is now pretty easy. We just need to make sure the string matches the allowed syntax, and that it&#8217;s not a reserved word. The first we can solve with a regular expression and the second with a simple white list array. For example, something along the following lines.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> is_valid_identifier<span style="color: #009900;">&#40;</span><span style="color: #000088;">$subject</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$identifier_syntax</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u'</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$reserved_words</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'break'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'do'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'instanceof'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'typeof'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'case'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'else'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'new'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'var'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'catch'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'finally'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'return'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'void'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'continue'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'for'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'switch'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'while'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'debugger'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'function'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'this'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'with'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'default'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'if'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'throw'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'delete'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'in'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'try'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'class'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'enum'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'extends'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'super'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'const'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'export'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'import'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'implements'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'let'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'private'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'public'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'yield'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'interface'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'package'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'protected'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'static'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'null'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'true'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'false'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$identifier_syntax</span><span style="color: #339933;">,</span> <span style="color: #000088;">$subject</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mb_strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$subject</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'UTF-8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$reserved_words</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Not too complex, although the regular expression might look a bit nuts at first because of all the Unicode character groups. You might find regular expressions other places to do this that uses a-z for the letters, but as you saw from the specification that won&#8217;t cover much of what&#8217;s actually valid. </p>
<p>I built the expression using the very helpful <a href="http://www.regexbuddy.com/">RegexBuddy</a> and exported an HTML explanation of it. Also threw together a tiny identifier validator thing where you can test it out with. You find it all at <a href="http://samples.geekality.net/js-identifiers">samples.geekality.net/js-identifiers</a>.</p>
<p>And that&#8217;s that. Hope that might be helpful for someone and please let me know if you find any issues with it!</p>
<blockquote><p><strong>Note:</strong> I have ignored the issue with the Unicode escape sequences for now as I&#8217;m not quite sure how to best handle those. From the specification:</p>
<blockquote><p>A UnicodeEscapeSequence cannot be used to put a character into an IdentifierName that would otherwise be illegal. In other words, if a \UnicodeEscapeSequence sequence were replaced by its UnicodeEscapeSequence&#8217;s <abbr title="Character Value">CV</abbr>, the result must still be a valid IdentifierName that has the exact same sequence of characters as the original IdentifierName. All interpretations of identifiers within this specification are based upon their actual characters regardless of whether or not an escape sequence was used to contribute any particular characters.</p></blockquote>
<p>So, I&#8217;m not sure if there is a way to just convert those sequences into actual characters or if this is done automatically by PHP as they come in as GET parameters or what. Either way, my code above there is ignoring them. This means, identifiers with escape sequences will not be considered valid. If you have some good ideas on how to handle it, please leave a comment <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p></blockquote>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1739&amp;md5=d6a9a0cd633273d4fde200b37d4ebbea" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/08/03/valid-javascript-identifier/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP: Proper age calculation</title>
		<link>http://www.geekality.net/2011/05/29/php-proper-age-calculation/</link>
		<comments>http://www.geekality.net/2011/05/29/php-proper-age-calculation/#comments</comments>
		<pubDate>Sat, 28 May 2011 23:52:12 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Age]]></category>
		<category><![CDATA[Date]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippet]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1397</guid>
		<description><![CDATA[Always struggle with calculating age in PHP for some reason. And there seems to be quite varying ideas on how this should be done. So decided to once and for all sit down and figure out how I could do &#8230; <a href="http://www.geekality.net/2011/05/29/php-proper-age-calculation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_1689" class="wp-caption alignright" style="width: 234px"><a href="http://www.rgbstock.com/photo/mhgnDJm/Birthday+cake"><img src="http://www.geekality.net/wp-content/uploads/2011/05/Birthday-cake-224x300.jpg" alt="" title="Birthday cake" width="224" height="300" class="size-medium wp-image-1689" /></a><p class="wp-caption-text">rgbstock.com</p></div>Always struggle with calculating age in PHP for some reason. And there seems to be quite varying ideas on how this should be done. So decided to once and for all sit down and figure out how I could do this.</p>
<p><span id="more-1397"></span></p>
<p>Found <a href="http://00f.net/2007/06/04/an-age-is-not-a-duration/">an article</a> which explained pretty well why I was a bit confused. It also had a code example in Perl(?).</p>
<p>So, thought I could stick a PHP version here in case that page dies or I forget. Actually there are two. The first calculates the age kind of manually, and can be used in PHP 4 and PHP 5. The second is a lot shorter and simpler, but requires PHP 5.3.</p>
<p>Enjoy <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Manual way. Takes unix time stamps.</span><br />
<span style="color: #000000; font-weight: bold;">function</span> getAge<span style="color: #009900;">&#40;</span><span style="color: #000088;">$birth</span><span style="color: #339933;">,</span> <span style="color: #000088;">$now</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$now</span> <span style="color: #339933;">=</span> <span style="color: #990000;">getdate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$now</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">NULL</span> ? <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$now</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$birth</span> <span style="color: #339933;">=</span> <span style="color: #990000;">getdate</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$birth</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$age</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$now</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'year'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$birth</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'year'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$now</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mon'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$birth</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mon'</span><span style="color: #009900;">&#93;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$now</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mon'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$birth</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mon'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$birth</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mday'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> <span style="color: #000088;">$now</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mday'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$age</span> <span style="color: #339933;">-=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$age</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>This next function uses the <a href="http://www.php.net/manual/en/datetime.diff.php">DateTime::diff</a> method available in PHP 5.3.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Takes dates like 'yyyy-mm-dd'</span><br />
<span style="color: #000000; font-weight: bold;">function</span> getAge<span style="color: #009900;">&#40;</span><span style="color: #000088;">$birth</span><span style="color: #339933;">,</span> <span style="color: #000088;">$now</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">NULL</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$now</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DateTime<span style="color: #009900;">&#40;</span><span style="color: #000088;">$now</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$birth</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DateTime<span style="color: #009900;">&#40;</span><span style="color: #000088;">$birth</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$birth</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">diff</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$now</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">format</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'%r%y'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>You can test them out at <a href="http://samples.geekality.net/age">samples.geekality.net/age</a> <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1397&amp;md5=143909b94d07cf9ac0ace0d1411e9767" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/05/29/php-proper-age-calculation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Tutorial: PayPal Instant Payment Notification (IPN)</title>
		<link>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/</link>
		<comments>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/#comments</comments>
		<pubDate>Sat, 28 May 2011 21:01:47 +0000</pubDate>
		<dc:creator>Torleif</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[IPN]]></category>
		<category><![CDATA[PayPal]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.geekality.net/?p=1420</guid>
		<description><![CDATA[In a previous post I tried to give an introduction on how to get started with PayPal Payment Data Transfers (PDT). PDT is very handy in several cases, but you can&#8217;t always rely on it since it requires the user &#8230; <a href="http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.rgbstock.com/photo/mswM744/got+a+letter"><img src="http://www.geekality.net/wp-content/uploads/2011/05/Got-a-letter-300x225.jpg" alt="Got a letter" title="rgbstock.com" width="300" height="225" class="alignright size-medium wp-image-1674" /></a>In <a href="/?p=1210">a previous post</a> I tried to give an introduction on how to get started with PayPal Payment Data Transfers (PDT). PDT is very handy in several cases, but you can&#8217;t always rely on it since it requires the user to return to your page after doing the payment. That will <em>often</em> happen, but it&#8217;s not guaranteed to happen. If you for example want to mark an order in your system as paid or something like that, you most likely want to use PayPal Instant Payment Notifications (IPN) in addition to PDT.</p>
<blockquote><p>Instant Payment Notification (IPN) is a message service that notifies you of events related to PayPal transactions. You can use it to automate back-office and administrative functions, such as fulfilling orders, tracking customers, and providing status and other information related to a transaction. &#8212; <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&#038;content_ID=developer/e_howto_admin_IPNIntro">PayPal</a></p></blockquote>
<p>Once again the documentation, tutorials and code samples I found on this was a bit all over the place. Sort of messy and outdated. So, once again I decided to do my own thing and just follow the steps required and implement them myself. And since the tutorial on PDT turned out to be a bit of a success, I decided to share this too. Hopefully it can make the lives of fellow developers easier <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p><span id="more-1420"></span></p>
<h2>How it works</h2>
<p>The concept is pretty simple. You first give PayPal an address to a listener, for example <code class="codecolorer text default"><span class="text">http://business.example.com/ipn/listener.php</span></code>. Then, whenever something happens, PayPal will post information about the event to that address. So for example if someone completes a payment, your listener will be notified shortly after with the transaction details and all you need to know.</p>
<p>This tutorial will focus on the listener part, as the setting up part on PayPal is very simple (Leave a comment if you disagree). Just go to the PayPal account settings, find the IPN settings and give the URL to your IPN listener. For testing we don&#8217;t even need to do that. All we need to do is to set up a PayPal Developer Account. We can then use their very handy <a href="https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session">Instant Payment Notification (IPN) simulator</a> that you find among their <a href="https://developer.paypal.com/cgi-bin/devscr?cmd=_tools-session">Test Tools</a>. So let&#8217;s get started!</p>
<h2>Step 0: Sign up for a Developer Account</h2>
<p>If you haven&#8217;t, go <a href="/?p=1176">sign up for a PayPal Developer account</a>. We don&#8217;t need to set up any accounts this time, as we will simply use the mentioned simulator.</p>
<p>Using the simulator is ultra simple. You just enter the address of your listener and choose a transaction type. You can then fill out all the data that should be in this fake transaction and then just hit &#8220;Send IPN&#8221; at the bottom. Luckily PayPal actually fills out all the fields with random test data, so unless you are trying to test something specific, you can just ignore the data and hit the button right away <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>Now, to the actual listener file&#8230;</p>
<h2>Step 1: Catch the IPN</h2>
<p>First thing we need to do in our listener is of course to catch the data we get from PayPal. The data is sent as a POST request, so PHP has actually done that for us. We just need to grab it <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$ipn_post_data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #339933;">;</span></div></div>
<h2>Step 2: Verification</h2>
<p>Since what we got could just be plain bogus from some stranger, we need to verify it with PayPal. This is done by taking all the POST data in its unaltered state, add one field to the beginning, and then send it back. In return we should then get one word, <code class="codecolorer text default"><span class="text">VERIFIED</span></code> or <code class="codecolorer text default"><span class="text">INVALID</span></code>. To do that, we can use our old buddy cURL.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Choose url</span><br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'test_ipn'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">===</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'test_ipn'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'https://www.sandbox.paypal.com/cgi-bin/webscr'</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">else</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'https://www.paypal.com/cgi-bin/webscr'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Set up request to PayPal</span><br />
<span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">curl_setopt_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><br />
<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; CURLOPT_URL <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$url</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_POST <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_POSTFIELDS <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">http_build_query</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmd'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'_notify-validate'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$ipn_post_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_RETURNTRANSFER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_HEADER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_SSL_VERIFYPEER <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; CURLOPT_CAINFO <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'cacert.pem'</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Execute request and get response and status code</span><br />
<span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #990000;">curl_exec</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$status</span> &nbsp; <span style="color: #339933;">=</span> <span style="color: #990000;">curl_getinfo</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span> CURLINFO_HTTP_CODE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// Close connection</span><br />
<span style="color: #990000;">curl_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$status</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">200</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$response</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'VERIFIED'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// All good! Proceed...</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #b1b100;">else</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Not good. Ignore, or log for investigation...</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Note that in the very beginning actually check for a field called <code class="codecolorer text default"><span class="text">test_ipn</span></code>. If that exists with a value of 1, it means it&#8217;s a request from the sandbox. In other words, we can choose the correct PayPal interface by just looking for that.</p>
<p>You can also see I set two cURL options called <code class="codecolorer text default"><span class="text">SSL_VERIFYPEER</span></code> and <code class="codecolorer text default"><span class="text">CAINFO</span></code>. The reason for that you will find in my post on <a href="http://www.geekality.net/?p=1413">cURL SSL verification</a>.</p>
<h2>Step 3: Fix character set</h2>
<p>Now that we know the data is valid, we can start to deal with it. What you get could be in a different character set than what you want though, so we should fix that first. The data should contain a key called <code class="codecolorer text default"><span class="text">charset</span></code> which specifies what character set the data is using. We just need to check for that and if needed convert from that to what we want, for example UTF-8.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'charset'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$charset</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Ignore if same as our default</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$charset</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Otherwise convert all the values</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$ipn_data</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mb_convert_encoding</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$charset</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// And store the charset values for future reference</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'utf-8'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$ipn_data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'charset_original'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$charset</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h2>Step 4: Use the data!</h2>
<p>Yup, believe it or not, that was everything that was needed to catch an IPN message from PayPal. Where you go from here completely depends on what exactly you need to do. </p>
<p>What you at least should do is the following:</p>
<ol>
<li>Confirm that the payment status is Completed.<br />
PayPal sends IPN messages for pending and denied payments as well, so don&#8217;t ship stuff or anything until the payment has cleared.</li>
<li>Use the transaction ID to verify that the transaction has not already been processed.<br />
This prevents you from processing the same transaction twice. You can for example store the transaction id in a database and check against those before you do anything with incoming IPNs. If you&#8217;re smart you could also store the time the IPN came in and the raw IPN data. This way you have a log of all incoming messages you can use if you need to reprocess something or for debugging if something weird is going on.</li>
<li>Make sure the receiver&#8217;s email address is the one you expected.</li>
<li>Make sure the price, item description, et cetera, match what it should be.</li>
</ol>
<p>And then finally you should of course make sure your customer gets what they should <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>You can read more about PayPal Instant Payment Notifications in their <a href="https://cms.paypal.com/cms_content/US/en_US/files/developer/IPNGuide.pdf">IPN Guide</a>.</p>
<h2>Working sample</h2>
<p>I have put together a working sample you can check out over at <a href="http://samples.geekality.net/ipn/">samples.geekality.net/ipn</a>. Hopefully this tutorial and that sample can help you get started with all of this <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p>I also put together an IPN handler class you can use pretty much out of the box. The sample uses it, and it&#8217;s very simple. Just extend the class, override the <code class="codecolorer text default"><span class="text">process</span></code> method and do what you need. Below is a simple example.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #666666; font-style: italic;">// example listener.php</span><br />
<br />
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'ipn_handler.class.php'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> My_Ipn_Handler <span style="color: #000000; font-weight: bold;">extends</span> IPN_Handler<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> process<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$post_data</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Let the IPN_Handler do it's processing,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// which includes validating and fixing the encoding</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$post_data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Check if validation failed</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.0 400 Bad Request'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">400</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">exit</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Seems it all was good, so in lack of better things to do,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// let's JSON encode it and dump it to a file</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #990000;">file_put_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ipn.txt'</span><span style="color: #339933;">,</span> <span style="color: #990000;">json_encode</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>PHP_EOL<span style="color: #339933;">,</span> FILE_APPEND<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000088;">$handler</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> My_Ipn_Handler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$handler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">process</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>That&#8217;s all! I&#8217;m sorry it took so long to get this tutorial written, but hopefully someone can find it useful. I have learned a lot writing it at least! Please leave a comment if it was helpful, if it wasn&#8217;t helpful, if there are mistakes, typos, or if you just want to say thank you <img src='http://www.geekality.net/wp-includes/images/blank.gif' alt=':)' class='wp-smiley smiley-1' /> </p>
<p class="wp-flattr-button"></p> <p><a href="http://www.geekality.net/?flattrss_redirect&amp;id=1420&amp;md5=c6fc8bcc514c281c5c7d8f2173c0042b" title="Flattr" target="_blank"><img src="http://www.geekality.net/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn/feed/</wfw:commentRss>
		<slash:comments>87</slash:comments>
		</item>
	</channel>
</rss>

