<?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>Matt Geri &#187; Development</title>
	<atom:link href="http://mattgeri.com/blog/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://mattgeri.com</link>
	<description>Adventurous web and mobile developer</description>
	<lastBuildDate>Thu, 10 May 2012 19:43:46 +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>Get a query column value by index in Coldfusion</title>
		<link>http://mattgeri.com/blog/2012/05/get-a-query-column-value-by-index-in-coldfusion/</link>
		<comments>http://mattgeri.com/blog/2012/05/get-a-query-column-value-by-index-in-coldfusion/#comments</comments>
		<pubDate>Mon, 07 May 2012 19:38:56 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Coldfusion]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[Query]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=803</guid>
		<description><![CDATA[Just a neat little Coldfusion query tip that I found out today. If are are looking for a single column value in a Coldfusion query result set and you know what the number of the row (index) that the value resides in, then you can use the following code snippet it to fetch that column [...]]]></description>
			<content:encoded><![CDATA[<p>Just a neat little Coldfusion query tip that I found out today. If are are looking for a single column value in a Coldfusion query result set and you know what the number of the row (index) that the value resides in, then you can use the following code snippet it to fetch that column value.</p>
<pre><code class="coldfusion">&lt;cfset columnValue = "#queryName.columnName[2]#"&gt;</code></pre>
<p>Just change <code>columnValue</code> to the variable you want to set. <code>queryName</code> is name of your <code>cfquery</code> and <code>columnName</code> is obviously the name of the database column.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/05/get-a-query-column-value-by-index-in-coldfusion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Find the last element of a PHP array within a loop</title>
		<link>http://mattgeri.com/blog/2012/05/find-the-last-element-of-a-php-array-within-a-loop/</link>
		<comments>http://mattgeri.com/blog/2012/05/find-the-last-element-of-a-php-array-within-a-loop/#comments</comments>
		<pubDate>Sun, 06 May 2012 20:15:05 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Arrays]]></category>
		<category><![CDATA[Loops]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Refactor]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=795</guid>
		<description><![CDATA[I see a lot of developers using a count to find out if they are at the last element of an array. Let&#8217;s look at a quick example: &#60;?php $array = array( 'blue', 'green', 'red' ); $count = 0; foreach ( $array as $a ) { $count++; if ( count( $array ) == $count ) [...]]]></description>
			<content:encoded><![CDATA[<p>I see a lot of developers using a count to find out if they are at the last element of an array. Let&#8217;s look at a quick example:</p>
<pre><code class="php">&lt;?php
$array = array( 'blue', 'green', 'red' );
$count = 0;

foreach ( $array as $a ) {
	$count++;

	if ( count( $array ) == $count ) {
		echo "Last element";
	} else {
		echo "Just another element";
	}
}
?&gt;</code></pre>
<p>I used to use this method extensively but recently started looking at alternative ways to solve this problem which uses less code. So far I have come up with the following:</p>
<pre><code class="php">&lt;?php
$array = array( 'blue', 'green', 'red' );

foreach ( $array as $key => $a ) {
	if ( end( array_keys( $array ) ) == $key ) {
		echo "Last element";
	} else {
		echo "Just another element";
	}
}
?&gt;</code></pre>
<p>It&#8217;s much less code and functions beautifully. We can obviously assign the last array key outside the loop and store it in it&#8217;s own variable if we don&#8217;t want to do an <code>end()</code> lookup on the <code>array_keys</code> array on each loop through.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/05/find-the-last-element-of-a-php-array-within-a-loop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Location based content in PHP using IP addresses</title>
		<link>http://mattgeri.com/blog/2012/04/location-based-content-in-php-using-ip-addresses/</link>
		<comments>http://mattgeri.com/blog/2012/04/location-based-content-in-php-using-ip-addresses/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 18:40:48 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Device Atlas]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[Location]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=761</guid>
		<description><![CDATA[With the internet being a globally accessible resource, there may come a time when you want to display different content to your website visitors based on their location. For instance, if you are a consultant you may want to display a US dollar hourly rate to people viewing your site from the United States and [...]]]></description>
			<content:encoded><![CDATA[<p>With the internet being a globally accessible resource, there may come a time when you want to display different content to your website visitors based on their location. For instance, if you are a consultant you may want to display a US dollar hourly rate to people viewing your site from the United States and a euro hourly rate to those who are viewing your site from Europe. Doing this in PHP is rather easy, let&#8217;s look at how.</p>
<p>We&#8217;re going to base our script on IP addresses. It&#8217;ll involve looking up the visitors IP address and then matching it against a set of IP addresses specific to a country. Based on that we can easily show our visitor content that is locally relevant to them.</p>
<p>For the sake of simpleness, let&#8217;s build our application to detect if a visitor is from South Africa and then display a relevant message to them, otherwise we&#8217;ll display a generic message.</p>
<p>To start off, we need to build an array of IP ranges to match against. This method isn&#8217;t 100% fool-proof and in a real life application, if you are dealing with multiple countries or even provinces, I&#8217;d recommend that you use a location matching library like DeviceAtlas. But for a small application like ours, an array is perfect.</p>
<p>Here is the array with the IP address ranges for South Africa:</p>
<pre><code>&lt;?php
$ranges = array(
	array( '41.0.0.0', '41.31.255.255' ),
	array( '41.75.224.0', '41.75.239.255' ),
	array( '41.112.0.0', '41.127.255.255' ),
	array( '41.144.0.0', '41.151.255.255' ),
	array( '41.154.0.0', '41.154.255.255' ),
	array( '41.156.0.0', '41.157.255.255' ),
	array( '41.160.0.0', '41.175.255.255' ),
	array( '41.177.0.0', '41.177.255.255' ),
	array( '41.180.0.0', '41.180.255.255' ),
	array( '41.181.0.0', '41.181.255.255' ),
	array( '41.183.0.0', '41.183.255.255' ),
	array( '41.185.0.0', '41.185.255.255' ),
	array( '41.188.192.0', '41.188.255.255' ),
	array( '41.189.64.0', '41.189.95.255' ),
	array( '41.191.128.0', '41.191.191.255' ),
	array( '41.192.0.0', '41.192.255.255' ),
	array( '41.193.0.0', '41.193.255.255' ),
	array( '41.194.0.0', '41.194.255.255' ),
	array( '41.195.0.0', '41.195.255.255' ),
	array( '41.198.0.0', '41.198.255.255' ),
	array( '41.202.32.0', '41.202.63.255' ),
	array( '41.203.0.0', '41.203.31.255' ),
	array( '41.203.32.0', '41.203.63.255' ),
	array( '41.203.160.0', '41.203.175.255' ),
	array( '41.204.192.0', '41.204.223.255' ),
	array( '41.206.160.0', '41.206.191.255' ),
	array( '41.206.192.0', '41.206.223.255' ),
	array( '41.207.224.0', '41.207.255.255' ),
	array( '41.208.0.0', '41.208.63.255' ),
	array( '41.208.192.0', '41.208.255.255' ),
	array( '41.213.0.0', '41.213.127.255' ),
	array( '41.216.128.0', '41.216.143.255' ),
	array( '41.216.192.0', '41.216.207.255' ),
	array( '41.221.0.0', '41.221.15.255' ),
	array( '41.221.224.0', '41.221.239.255' ),
	array( '41.240.0.0', '41.247.255.255' ),
	array( '66.8.0.0', '66.8.127.255' ),
	array( '66.18.64.0', '66.18.95.255' ),
	array( '69.67.32.0', '69.67.47.255' ),
	array( '137.158.0.0', '137.158.255.255' ),
	array( '137.214.0.0', '137.214.255.255' ),
	array( '137.215.0.0', '137.215.255.255' ),
	array( '139.53.0.0', '139.53.255.255' ),
	array( '143.128.0.0', '143.128.255.255' ),
	array( '143.160.0.0', '143.160.255.255' ),
	array( '146.64.0.0', '146.64.255.255' ),
	array( '146.141.0.0', '146.141.255.255' ),
	array( '146.182.0.0', '146.182.255.255' ),
	array( '146.230.0.0', '146.230.255.255' ),
	array( '146.231.0.0', '146.231.255.255' ),
	array( '146.232.0.0', '146.232.255.255' ),
	array( '147.110.0.0', '147.110.255.255' ),
	array( '152.106.0.0', '152.106.255.255' ),
	array( '152.107.0.0', '152.107.255.255' ),
	array( '152.108.0.0', '152.108.255.255' ),
	array( '152.109.0.0', '152.109.255.255' ),
	array( '152.110.0.0', '152.110.255.255' ),
	array( '152.111.0.0', '152.111.255.255' ),
	array( '152.112.0.0', '152.112.255.255' ),
	array( '155.159.0.0', '155.159.255.255' ),
	array( '155.232.0.0', '155.232.255.255' ),
	array( '155.233.0.0', '155.233.255.255' ),
	array( '155.234.0.0', '155.234.255.255' ),
	array( '155.235.0.0', '155.235.255.255' ),
	array( '155.236.0.0', '155.236.255.255' ),
	array( '155.237.0.0', '155.237.255.255' ),
	array( '155.238.0.0', '155.238.255.255' ),
	array( '155.239.0.0', '155.239.255.255' ),
	array( '155.240.0.0', '155.240.255.255' ),
	array( '156.8.0.0', '156.8.255.255' ),
	array( '160.115.0.0', '160.115.255.255' ),
	array( '160.116.0.0', '160.116.255.255' ),
	array( '160.117.0.0', '160.117.255.255' ),
	array( '160.118.0.0', '160.118.255.255' ),
	array( '160.121.0.0', '160.121.255.255' ),
	array( '160.122.0.0', '160.122.255.255' ),
	array( '160.123.0.0', '160.123.255.255' ),
	array( '160.124.0.0', '160.124.255.255' ),
	array( '163.195.0.0', '163.195.255.255' ),
	array( '163.196.0.0', '163.196.255.255' ),
	array( '163.197.0.0', '163.197.255.255' ),
	array( '163.198.0.0', '163.198.255.255' ),
	array( '163.199.0.0', '163.199.255.255' ),
	array( '163.200.0.0', '163.200.255.255' ),
	array( '163.201.0.0', '163.201.255.255' ),
	array( '163.202.0.0', '163.202.255.255' ),
	array( '163.203.0.0', '163.203.255.255' ),
	array( '164.88.0.0', '164.88.255.255' ),
	array( '164.146.0.0', '164.151.255.255' ),
	array( '164.155.0.0', '164.155.255.255' ),
	array( '165.3.0.0', '165.5.255.255' ),
	array( '165.8.0.0', '165.11.255.255' ),
	array( '165.25.0.0', '165.25.255.255' ),
	array( '165.143.0.0', '165.149.255.255' ),
	array( '165.165.0.0', '165.165.255.255' ),
	array( '165.180.0.0', '165.180.255.255' ),
	array( '165.233.0.0', '165.233.255.255' ),
	array( '166.85.0.0', '166.85.255.255' ),
	array( '168.76.0.0', '168.76.255.255' ),
	array( '168.80.0.0', '168.81.255.255' ),
	array( '168.89.0.0', '168.89.255.255' ),
	array( '168.128.0.0', '168.128.255.255' ),
	array( '168.142.0.0', '168.142.255.255' ),
	array( '168.155.0.0', '168.155.255.255' ),
	array( '168.164.0.0', '168.164.255.255' ),
	array( '168.172.0.0', '168.172.255.255' ),
	array( '168.206.0.0', '168.206.255.255' ),
	array( '168.209.0.0', '168.210.255.255' ),
	array( '169.129.0.0', '169.129.255.255' ),
	array( '169.202.0.0', '169.202.255.255' ),
	array( '196.1.32.0', '196.1.51.255' ),
	array( '196.1.144.0', '196.1.159.255' ),
	array( '196.2.16.0', '196.2.31.255' ),
	array( '196.2.32.0', '196.2.63.255' ),
	array( '196.2.64.0', '196.2.79.255' ),
	array( '196.2.96.0', '196.2.127.255' ),
	array( '196.2.128.0', '196.2.159.255' ),
	array( '196.2.160.0', '196.2.191.255' ),
	array( '196.3.164.0', '196.3.179.255' ),
	array( '196.3.224.0', '196.3.255.255' ),
	array( '196.4.0.0', '196.4.19.255' ),
	array( '196.4.100.0', '196.4.149.255' ),
	array( '196.4.173.0', '196.4.188.255' ),
	array( '196.4.212.0', '196.4.231.255' ),
	array( '196.5.0.0', '196.5.255.255' ),
	array( '196.6.1.0', '196.6.100.255' ),
	array( '196.6.133.0', '196.6.172.255' ),
	array( '196.7.0.0', '196.7.255.255' ),
	array( '196.8.0.0', '196.8.255.255' ),
	array( '196.9.0.0', '196.9.255.255' ),
	array( '196.10.1.0', '196.10.50.255' ),
	array( '196.10.61.0', '196.10.95.255' ),
	array( '196.10.150.0', '196.10.199.255' ),
	array( '196.11.0.0', '196.11.30.255' ),
	array( '196.12.16.0', '196.12.31.255' ),
	array( '196.13.1.0', '196.13.30.255' ),
	array( '196.13.31.0', '196.13.80.255' ),
	array( '196.13.81.0', '196.13.100.255' ),
	array( '196.14.0.0', '196.14.255.255' ),
	array( '196.15.64.0', '196.15.127.255' ),
	array( '196.15.128.0', '196.15.255.255' ),
	array( '196.16.0.0', '196.19.255.255' ),
	array( '196.21.0.0', '196.21.255.255' ),
	array( '196.22.16.0', '196.22.31.255' ),
	array( '196.22.32.0', '196.22.47.255' ),
	array( '196.22.64.0', '196.22.127.255' ),
	array( '196.22.160.0', '196.22.191.255' ),
	array( '196.22.192.0', '196.22.239.255' ),
	array( '196.22.240.0', '196.22.255.255' ),
	array( '196.23.0.0', '196.23.255.255' ),
	array( '196.24.0.0', '196.24.255.255' ),
	array( '196.25.0.0', '196.25.255.255' ),
	array( '196.26.0.0', '196.26.255.255' ),
	array( '196.28.16.0', '196.28.47.255' ),
	array( '196.28.64.0', '196.28.127.255' ),
	array( '196.28.128.0', '196.28.223.255' ),
	array( '196.29.0.0', '196.29.31.255' ),
	array( '196.29.128.0', '196.29.159.255' ),
	array( '196.29.240.0', '196.29.255.255' ),
	array( '196.30.0.0', '196.30.255.255' ),
	array( '196.31.0.0', '196.31.255.255' ),
	array( '196.32.160.0', '196.32.191.255' ),
	array( '196.33.0.0', '196.33.255.255' ),
	array( '196.34.0.0', '196.35.255.255' ),
	array( '196.36.0.0', '196.39.255.255' ),
	array( '196.40.96.0', '196.40.111.255' ),
	array( '196.41.0.0', '196.41.31.255' ),
	array( '196.41.96.0', '196.41.127.255' ),
	array( '196.41.128.0', '196.41.159.255' ),
	array( '196.41.160.0', '196.41.191.255' ),
	array( '196.41.192.0', '196.41.223.255' ),
	array( '196.43.0.0', '196.43.63.255' ),
	array( '196.44.0.0', '196.44.31.255' ),
	array( '196.44.32.0', '196.44.47.255' ),
	array( '196.44.64.0', '196.44.95.255' ),
	array( '196.44.192.0', '196.44.207.255' ),
	array( '196.44.208.0', '196.44.223.255' ),
	array( '196.44.224.0', '196.44.239.255' ),
	array( '196.45.16.0', '196.45.31.255' ),
	array( '196.45.64.0', '196.45.95.255' ),
	array( '196.45.96.0', '196.45.111.255' ),
	array( '196.46.160.0', '196.46.175.255' ),
	array( '196.47.0.0', '196.47.63.255' ),
	array( '196.47.64.0', '196.47.95.255' ),
	array( '196.207.32.0', '196.207.47.255' ),
	array( '196.208.0.0', '196.211.255.255' ),
	array( '196.212.0.0', '196.215.255.255' ),
	array( '196.220.32.0', '196.220.63.255' ),
	array( '198.54.22.0', '198.54.37.255' ),
	array( '204.12.128.0', '204.12.143.255' ),
	array( '209.203.0.0', '209.203.63.255' ),
	array( '209.212.96.0', '209.212.127.255' ),
	array( '213.193.32.0', '213.193.63.255' ),
	array( '216.236.176.0', '216.236.191.255' )
);
?php&gt;</code></pre>
<p>Before we go any further, we need to write a function to check if the IP address we have got from the visitors user agent is valid.</p>
<pre><code>&lt;?php
function checkValidIp( $ip ) {
	$invalid = array(
		array( '10.0.0.0', '10.255.255.255' ),
		array( '127.0.0.0', '127.255.255.255' ),
		array( '169.254.0.0', '169.254.255.255' ),
		array( '172.16.0.0', '172.31.255.255' ),
		array( '192.0.2.0', '192.0.2.255' ),
		array( '192.168.0.0', '192.168.255.255' ),
		array( '255.255.255.0', '255.255.255.255' )
	);

	$ip = ip2long( $ip );

	foreach( $invalid as $ips ) {
		if ( ip2long( $ips[0] ) <= $ip &#038;&#038; $ip <= ip2long( $ips[1] ) )
			return false;
	}

	return true;
}
?php&gt;</code></pre>
<p>As you can see, we accept an IP address in our <code>checkValidIP</code> function. We then setup an array of invalid IP address (which are mostly local IP address ranges), run through them and if we find a match we return false i.e. it is not a valid IP address.</p>
<p>You will have noticed one important PHP function that was used in the code snippet. That is the <code>ip2long</code> function. It takes an IP address and converts it to the type of a long integer. We can then easily check if the IP address falls within the invalid range. We're going to use this function again below.</p>
<p>The next step is to fetch the IP address of the visitor and match it against our ranges array. Here is a small function that does exactly that.</p>
<pre><code>&lt;?php
function isSouthAfrican() {
	// Range array goes here
	$ranges = array()

	if ( checkValidIp( $_SERVER['HTTP_CLIENT_IP'] ) ) {
		$ip = $_SERVER['HTTP_CLIENT_IP'];
	}

	if ( ! isset( $ip ) ) {
		if ( $ips = count( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) > 0 ) {
			foreach ( $ips as $i ) {
				if ( checkValidIp( trim( $i ) ) ) {
					$ip = $i;
					break;
				}
			}
		}
	}

	if ( ! isset( $ip ) ) {
		if ( checkValidIp( $_SERVER['HTTP_X_FORWARDED'] ) ) {
			$ip = $_SERVER['HTTP_X_FORWARDED'];
		} else if ( checkValidIp( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
			$ip = $_SERVER['HTTP_FORWARDED_FOR'];
		} else if ( checkValidIp( $_SERVER['HTTP_FORWARDED'] ) ) {
			$ip = $_SERVER['HTTP_FORWARDED'];
		} else if ( checkValidIp( $_SERVER['HTTP_X_FORWARDED'] ) ) {
			$ip = $_SERVER['HTTP_X_FORWARDED'];
		} else {
			$ip = $_SERVER['REMOTE_ADDR'];
		}
	}

	$ip = ip2long( $ip );

	foreach ( $ranges as $range ) {
		if ( ip2long( $range[0] ) <= $ip &#038;&#038; $ip <= ip2long( $range[1] ) )
			return true;
	}

	return false;
}
?php&gt;</code></pre>
<p>In this snippet we check numerous user agent variables for the IP address to try and bypass proxies and weird browser behavior. Finally we run through our IP ranges and see if we get a match. If so, we naturally return true. Include this code in your project and then simply call the <code>isSouthAfrican</code> function and voila!</p>
<pre><code>&lt;?php
if ( isSouthAfrican() ) {
	echo "We're in South Africa baby!";
} else {
	echo "Hello world";
}
?php&gt;</code></pre>
<p>To test this code out, you'll need to use a proxy. Just do a Google search and you'll find thousands of international proxies that you can use. Change the IP ranges based on the country you want to check against.</p>
<p>You can download a full working version of the code <a href="http://mattgeri.com/wp-content/uploads/2012/04/locationMatch.php_.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/04/location-based-content-in-php-using-ip-addresses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blog design tip: add a link back to your websites homepage</title>
		<link>http://mattgeri.com/blog/2012/02/blog-design-tip-add-a-link-back-to-your-websites-homepage/</link>
		<comments>http://mattgeri.com/blog/2012/02/blog-design-tip-add-a-link-back-to-your-websites-homepage/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 18:55:49 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Blogging]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=737</guid>
		<description><![CDATA[This is more of a short rant with a tip at the end of it There is nothing more annoying than visiting a blog, be it via Google, a twitter link or however you end up on the blog and browsing the blog and then deciding to view the company/product home page, only to find [...]]]></description>
			<content:encoded><![CDATA[<p>This is more of a short rant with a tip at the end of it <img src='http://mattgeri.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>There is nothing more annoying than visiting a blog, be it via Google, a twitter link or however you end up on the blog and browsing the blog and then deciding to view the company/product home page, only to find that you have to physically retype the URL bar and/or remove the &#8216;blog.&#8217; or &#8216;/blog/&#8217; piece to get to the home page.</p>
<p>I&#8217;ve noticed quite a number of popular blogs that don&#8217;t have a clear link back to the homepage. Some will have a small disguised link (usually on the sidebar of the blog) that is very difficult to find. Why make it so difficult for a visitor and/or potential customer to go to your home page.</p>
<p>This practice usually occurs a lot on 3rd party hosted blogs like WordPress.com, Blogger, Posterous, etc. I understand that it can sometimes be tricky to edit the blog theme and add that link, but it is vitally important. Pay someone to do it for you.</p>
<p>I&#8217;ve actually started to close the browser tab on a blog who does not link back to the homepage, even if I am interested in the product or service!</p>
<p>So take 5 minutes to quickly add a link back to your homepage.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/02/blog-design-tip-add-a-link-back-to-your-websites-homepage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to add the TinyMCE editor to a WordPress meta box or plugin form</title>
		<link>http://mattgeri.com/blog/2012/02/how-to-add-the-tinymce-editor-to-a-wordpress-meta-box-or-plugin-form/</link>
		<comments>http://mattgeri.com/blog/2012/02/how-to-add-the-tinymce-editor-to-a-wordpress-meta-box-or-plugin-form/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 17:14:34 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[TinyMCE]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress meta box]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=717</guid>
		<description><![CDATA[I&#8217;ve worked on a number of WordPress sites and custom plugins recently where I have needed to add the TinyMCE editor to a meta box that was added to a post type and/or a custom textarea fields in a plugin. Pre-WordPress 3.0 this was quite difficult and required a bit of hacking, but luckily since [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve worked on a number of WordPress sites and custom plugins recently where I have needed to add the TinyMCE editor to a meta box that was added to a post type and/or a custom textarea fields in a plugin. Pre-WordPress 3.0 this was quite difficult and required a bit of hacking, but luckily since WordPress version 3.0 they have made it extremely easy.</p>
<p>In WordPress 3.0 a new function was introduced called &#8216;<a href="http://codex.wordpress.org/Function_Reference/wp_editor">wp_editor()</a>&#8216;. This function allows us to easily add a the TinyMCE editor to our meta box or plugin.</p>
<p>The wp_editor() function gives us quite a bit of flexibility through its parameters. Let&#8217;s take a quick look at an example of adding an editor to a meta box. I&#8217;m going to skip out the part where we define the meta box and skip directly to the function which outputs our meta box content.</p>
<pre><code class="php">&lt;?php
function display_meta_box_content( $post ) {
	echo '&lt;label for="content"&gt;Content&lt;/label&gt;';
	wp_editor( '', 'content-id', array( 'textarea_name' => 'content', 'media_buttons' => false ) );
}
?&gt;</code></pre>
<p>Simple as that. You can also use this in your plugin. Just insert the wp_editor() function where you want a textarea to display on your admin page.</p>
<p>Check out the <a href="http://codex.wordpress.org/Function_Reference/wp_editor">wp_editor()</a> page in the WordPress codex for extra parameters you can pass the function. You can also set TinyMCE settings using the &#8216;tinymce&#8217; parameter. For instance, let&#8217;s look at a quick example where we define what formatting options we want displayed and add a spellchecker to the TinyMCE editor.</p>
<pre><code class="php">&lt;?php
	wp_editor( '', 'content-id', array( 'textarea_name' => 'content', 'media_buttons' => false, 'tinymce' => array( 'theme_advanced_buttons1' => 'formatselect,forecolor,|,bold,italic,underline,|,bullist,numlist,blockquote,|,justifyleft,justifycenter,justifyright,justifyfull,|,link,unlink,|,spellchecker,wp_fullscreen,wp_adv' ) ) );
?&gt;</code></pre>
<h3>Just one small thing!</h3>
<p>Unfortunately, the editor cannot be moved around the DOM which means the editor will not work if you move the meta box. There is discussion around this on <a href="http://core.trac.wordpress.org/ticket/19173">trac</a> where a few proposed solutions are put forward, such as static meta boxes that cannot be dragged, but as it currently stands, there is no work around for this.</p>
<p>This only effects meta boxes though and not plugins.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/02/how-to-add-the-tinymce-editor-to-a-wordpress-meta-box-or-plugin-form/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick tip for WordPress developers: Use the WP_DEBUG constant</title>
		<link>http://mattgeri.com/blog/2012/02/quick-tip-for-wordpress-developers-use-the-wp_debug-constant/</link>
		<comments>http://mattgeri.com/blog/2012/02/quick-tip-for-wordpress-developers-use-the-wp_debug-constant/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 12:24:06 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=698</guid>
		<description><![CDATA[Over the past few years I have worked with many different WordPress plugins and themes, both on my own websites and on my clients websites. During this time, I have noticed something that a lot of developers are doing that they shouldn&#8217;t be doing. I&#8217;m talking about developers not using the WP_DEBUG constant when building [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past few years I have worked with many different WordPress plugins and themes, both on my own websites and on my clients websites. During this time, I have noticed something that a lot of developers are doing that they shouldn&#8217;t be doing. I&#8217;m talking about developers not using the WP_DEBUG constant when building their plugins and themes.</p>
<p>I was guilty of this before as well. I never used it mostly due to ignorance and not knowing what it does. I discovered it when I was working on a client website who had it set to true in their live environment (not a good idea) and their website was throwing tons of PHP errors.</p>
<h3>What does the WP_DEBUG constant do?</h3>
<p>WP_DEBUG is a simple flag that tells WordPress you want to debug your code and that PHP errors should be displayed. If it is set to false, WordPress will suppress many of those PHP errors (such as undefined index&#8217;s) and you will never know that they exist &#8211; That is until you look at your web server logs and see all the errors showing up.</p>
<p>The WP_DEBUG constant can also be very useful. Let&#8217;s use analytics as an example. In your development environment you do not want to track analytics. Debug should always be set to true in development environments so lets assume that it is. To stop the analytics script from collecting data (running the analytics script), you can use this code:</p>
<pre><code class="php">&lt;?php if ( ! WP_DEBUG ): ?&gt;
// Display analytics code in your theme
&lt;?php endif; ?&gt;</code></pre>
<p>If you constantly turn the WP_DEBUG flag on and off in your development environment, then I recommend creating a new constant called WP_DEV in your wp-config.php file to get the above code to work.</p>
<p>You&#8217;d be very surprised to see how many of the popular plugins actually have basic PHP errors in them such as undefined indexes. Install a couple plugins, turn the WP_DEBUG flag on and see for yourself.</p>
<p>As mentioned above, you should set WP_DEBUG to false in any live environment.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/02/quick-tip-for-wordpress-developers-use-the-wp_debug-constant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symbolic links on a Mac (OS X)</title>
		<link>http://mattgeri.com/blog/2012/01/symbolic-links-on-a-mac-os-x/</link>
		<comments>http://mattgeri.com/blog/2012/01/symbolic-links-on-a-mac-os-x/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 15:11:31 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=691</guid>
		<description><![CDATA[If you are a developer and have not come across symbolic links before, then you need to read this blog post. Symbolic links are extremely useful if you hate copying and pasting duplicate files and folders in different places/projects. So what exactly are they? Simply speaking, they are a virtual link or shortcut between a [...]]]></description>
			<content:encoded><![CDATA[<p>If you are a developer and have not come across symbolic links before, then you need to read this blog post. Symbolic links are extremely useful if you hate copying and pasting duplicate files and folders in different places/projects.</p>
<p>So what exactly are they? Simply speaking, they are a virtual link or shortcut between a file or folder from a different file/folder location.</p>
<p>So for instance, I have a project that I am working on in a directory called &#8216;Example-Project&#8217; that lives in a &#8216;Projects&#8217; directory. Let&#8217;s say that this is a WordPress site. Now, I also have a plugin that I have written called &#8216;Display-Latest-Posts&#8217; and this plugin also sits in the main &#8216;Projects&#8217; directory. Now, I want to use this plugin on the Example-Project site.</p>
<p>There are two ways in which we can do this</p>
<ol>
<li>Copy/Paste the plugin files from &#8216;Display-Latest-Posts&#8217; into &#8216;Projects/Example-Project/wp-content/plugins/&#8217;</li>
<li>Create a symbolic link</li>
</ol>
<p>The problem with method number 1 above, is that if I change some code in the &#8216;Display-Latest-Posts&#8217; plugin, I have to go and copy/paste the files I changed back into the &#8216;Example-Project&#8217; folder. Now imagine that you have the plugin running on a number of sites in your development environment. That could take a while.</p>
<h3>Introducing symbolic links</h3>
<p>Symbolic links solve the problem that I just mentioned. When you create a symbolic link in a folder, any changes to the files in the original folder will be reflected in the linked folder, since the linked folder is actually just a reference/shortcut of the original folder. It is not two separate folders.</p>
<p>To create a symbolic link, open terminal and type the following:</p>
<pre><code>ln -s /Path/to/original/folder New-folder-name</code></pre>
<p>So in our example above, we would have created the following symbolic link:</p>
<pre><code>ln -s /Projects/Display-Latest-Posts /Projects/Example-Project/wp-content/plugins/Display-Latest-Posts</code></pre>
<p>The symbolic link is now created between those two folders and our plugin will now be working in our Example-Project site.</p>
<p>Symbolic links are really easy to use and can save you tons of time. Give them a try.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/01/symbolic-links-on-a-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to ignore WordPress pagination and display all posts on a page</title>
		<link>http://mattgeri.com/blog/2012/01/how-to-ignore-wordpress-pagination-and-display-all-posts-on-a-page/</link>
		<comments>http://mattgeri.com/blog/2012/01/how-to-ignore-wordpress-pagination-and-display-all-posts-on-a-page/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 14:20:53 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=489</guid>
		<description><![CDATA[There are times when you want to display a list of WordPress posts (or even custom post types) on a page and not have them paginated into multiple different WordPress pages. For example, you may be creating an archive page and instead of showing just the latest 10 posts in your category, you want to [...]]]></description>
			<content:encoded><![CDATA[<p>There are times when you want to display a list of WordPress posts (or even custom post types) on a page and not have them paginated into multiple different WordPress pages. For example, you may be creating an archive page and instead of showing just the latest 10 posts in your category, you want to show the whole list of posts in that category.</p>
<p>I recently come across this challenge when building the theme for this site and it is actually very easily overcome. You just need to add a little bit of PHP code to your theme file.</p>
<p>Let&#8217;s assume we are working on an archive page (archive.php in WordPress). In that file you have your standard WordPress loop which will display the latest 10 posts (or however many you have set to display per page in your WordPress settings). So we have something like this&#8230;</p>
<pre>
<code class="php">
&lt;php
if ( have_posts() ) : while ( have_posts() ) : the_post();
	// Your code here
endwhile; endif;
php&gt;
</code>
</pre>
<p>Now, to avoid showing just the latest 10 posts, we need to do this</p>
<pre>
<code class="php">
&lt;php
global $query_string;
query_posts( $query_string . '&#038;posts_per_page=-1' );
if ( have_posts() ) : while ( have_posts() ) : the_post();
	// Your code here
endwhile; endif;
wp_reset_query();
php&gt;
</code>
</pre>
<p>Simple enough. All we added was 3 extra lines of code.</p>
<p>Firstly, we reference the $query_string global so that we can use it in the code. Then we use the existing query string that was set to fetch the posts and add an extra parameter to the end of the query string called &#8220;posts_per_page&#8221; to display a custom number of posts, in this case we use -1 to display all posts. And lastly, we reset the query after we are done.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/01/how-to-ignore-wordpress-pagination-and-display-all-posts-on-a-page/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Escaping input to the PHP mail() function</title>
		<link>http://mattgeri.com/blog/2012/01/escaping-input-to-the-php-mail-function/</link>
		<comments>http://mattgeri.com/blog/2012/01/escaping-input-to-the-php-mail-function/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 20:31:50 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=443</guid>
		<description><![CDATA[I recently built my email contact form on this website and thought I would share with you the method which I used to escape input to the PHP mail() function in order to avoid security vulnerabilities on your own contact form. You may think that the mail() function is a relatively safe function and data [...]]]></description>
			<content:encoded><![CDATA[<p>I recently built my <a href="http://mattgeri.com/contact/">email contact form</a> on this website and thought I would share with you the method which I used to escape input to the PHP mail() function in order to avoid security vulnerabilities on your own contact form. You may think that the mail() function is a relatively safe function and data does not need to be cleaned, but quite the opposite is true. Lets quickly take a look as to why this is.</p>
<p>I am going to assume that your contact form on your website accepts a name, a persons email address and a message that they want to send to you. Lets also assume the contact form does a HTTP POST request to your page and we fetch the data that was sent with the following variables: $_POST['name'], $_POST['email'] and $_POST['message'].</p>
<p>Now our code looks something like this:</p>
<pre>
<code class="php">&lt;?php
if ( isset( $_POST['submit'] ) ) {
	$header = "From: " . $_POST['name'] . "<" . $_POST['email'] . ">\r\n";
	mail( "you@yourdomain.com", "Message from our contact form", $_POST['message'], $headers );
}
?&gt;
</code>
</pre>
<p>This is obviously a very simplified version of a script you would actually use. It doesn&#8217;t take into account validation etc. So, it looks pretty harmless doesn&#8217;t it? Well it&#8217;s not. And the reason for this is what if a user (read: spammer) entered the following in to the &#8216;email&#8217; form field on your website</p>
<pre><code>>\r\nBcc: spam@anotherdomain.com, spam2@anotherdomain.com, etc...</code></pre>
<p>As you can see, a spammer could easily use your contact form and server to send out spam emails to anyone he/she pleases by manipulating your email form field.</p>
<p>How do you combat this behavior and secure your form? It&#8217;s actually pretty easy. You need to escape any data going into your email header variable. In our case it is the name and email field. Lets look at two functions (from Zend) that will do the escaping for us.</p>
<pre>
<code class="php">// Filter Name
function filter_name( $input ) {
	$rules = array( "\r" => '', "\n" => '', "\t" => '', '"'  => "'", '<'  => '[', '>'  => ']' );
	$name = trim( strtr( $input, $rules ) );
	return $name;
}

// Filter Email
function filter_email( $input ) {
	$rules = array( "\r" => '', "\n" => '', "\t" => '', '"'  => '', ','  => '', '<'  => '', '>'  => '' );
	$email = strtr( $input, $rules );
	return $email;
}

// Your $header line now becomes
$header = "From: " . filter_name( $_POST['name'] ) . "<" . filter_email( $_POST['email'] ) . ">\r\n";
</code>
</pre>
<p>Those are 2 very straight forward functions that will escape your form input and remove the risk of someone using your contact form for spamming. There are a few other functions that have been written that basically do the same thing, but I like the two above.</p>
<p>That&#8217;s about all there is to it. Simple but effective functions for escaping input to the PHP mail() function.</p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2012/01/escaping-input-to-the-php-mail-function/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordCamp Cape Town 2011 slides</title>
		<link>http://mattgeri.com/blog/2011/09/wordcamp-cape-town-2011-slides/</link>
		<comments>http://mattgeri.com/blog/2011/09/wordcamp-cape-town-2011-slides/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 14:32:03 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Talks]]></category>
		<category><![CDATA[WCCT]]></category>
		<category><![CDATA[WordCamp]]></category>
		<category><![CDATA[WordCamp Cape Town]]></category>

		<guid isPermaLink="false">http://mattgeri.com/?p=221</guid>
		<description><![CDATA[I just got back yesterday evening from WordCamp Cape Town 2011. This years WordCamp was organized by Ashley Shaw and his team at LightSpeed. It was definitely one of the better run conferences that I have been to and I learned a ton. I gave a talk on using WordPress as a mobile publishing platform. [...]]]></description>
			<content:encoded><![CDATA[<p>I just got back yesterday evening from <a href="http://2011.capetown.wordcamp.org">WordCamp Cape Town 2011</a>. This years WordCamp was organized by Ashley Shaw and his team at <a href="http://lsdev.biz/">LightSpeed</a>. It was definitely one of the better run conferences that I have been to and I learned a ton.</p>
<p>I gave a talk on using WordPress as a mobile publishing platform. Below are my slides from the talk. Unfortunately, I didn&#8217;t use many bullet point lists in my preso but if you want to read my notes from each slide, do so on the actual slideshare page for this presentation.</p>
<p>Hopefully we will be getting the videos from the sessions shortly and as soon as I do, I will post up the video from my talk.</p>
<p><a href="http://www.slideshare.net/MattGeri/wordpress-as-a-mobile-publishing-platform" title="WordPress as a mobile publishing platform" target="_blank">WordPress as a mobile publishing platform</a></p>
<p><iframe src="http://www.slideshare.net/slideshow/embed_code/9279278" width="560" height="465" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://mattgeri.com/blog/2011/09/wordcamp-cape-town-2011-slides/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

