<?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>Edward Yarnold &#187; PHP</title>
	<atom:link href="http://www.edwardyarnold.co.uk/blog/category/web-development/php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.edwardyarnold.co.uk/blog</link>
	<description>PHP &#38; MySQL Web Developer</description>
	<lastBuildDate>Mon, 12 Dec 2011 18:12:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Commenting code &#8211; a minor but invaluable investment of time</title>
		<link>http://www.edwardyarnold.co.uk/blog/commenting-code-invaluable-investment-of-time</link>
		<comments>http://www.edwardyarnold.co.uk/blog/commenting-code-invaluable-investment-of-time#comments</comments>
		<pubDate>Wed, 03 Nov 2010 18:56:04 +0000</pubDate>
		<dc:creator>Ed Yarnold</dc:creator>
				<category><![CDATA[Best Practice]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.edwardyarnold.co.uk/blog/?p=133</guid>
		<description><![CDATA[I&#8217;m a strong believer in code being written in such a way that it is self documenting, but would not use this as an excuse for not adding in English language comments to go alongside the code. After all, comments add a tiny amount to the size of a PHP file and don&#8217;t slow down [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a strong believer in code being written in such a way that it is self documenting, but would not use this as an excuse for not adding in English language comments to go alongside the code.  After all, comments add a tiny amount to the size of a PHP file and don&#8217;t slow down the application at all.  Also, the English language comments alongside the code can be used to justify decisions or assumptions you have made, which might make the next programmer&#8217;s visit to the file a lot quicker and more productive.</p>
<p><span id="more-133"></span></p>
<h3>Explaining and justifying your decisions</h3>
<p>At the most very basic level, take this bit of code for example:</p>
<p><code>ksort($files);</code></p>
<p>To most PHP developers it is obvious that this bit of code sorts the $files array in key order.  But it is not obvious to any PHP developer *why* I have done this.  Adding a comment to say what I am doing and why would help speed up the recognition of what this code does; but more importantly, explain why this code is here.:</p>
<p><code><br />
/**<br />
 * Sort the $files array in Key order. We want them displayed on the<br />
 * page in added order,  and the $files array is not necessarily<br />
 * sorted in that order before this stage.<br />
 */<br />
ksort($files);<br />
</code></p>
<h3>Using code comments as a tool: Autocompletion</h3>
<p>There are other areas of an application where documentation can be even more useful.  Modern Code Editors and IDEs will read what are called &#8216;<a href="http://en.wikipedia.org/wiki/PHPDoc#DocBlock">docblocks</a>&#8216; at the top of class, method or function definitions and add the information in the docblock in to your autocomplete prompts.  So how do these docblocks work?</p>
<p>Docblocks are generally in this format (opened by /**, closed by */, with a * at the start of every line inbetween) and always apply to the next uncommented line of code.  In this case, the line of code beginning with $page_posted_to = is documented by the docblock above.:</p>
<p><code><br />
/**<br />
 * Determine if the page has been posted to with an action.<br />
 */<br />
$page_posted_to = (array_key_exists('action', $_POST) &#038;&#038; !empty($_POST['action']));<br />
</code></p>
<p>Within docblocks you can contain &#8216;tags&#8217;.  These &#8216;tags&#8217; begin with an @ symbol and are often read or interpreted by documentation generation utilities or IDEs/Editors for autocompletion.  A comprehensive list can be found on the <a href="http://en.wikipedia.org/wiki/PHPDoc#Tags">Wikipedia page for Docblocks</a>.   Using these tags can encourage you to include information in your documentation that you might forget to include normally, ie the expected data type of function parameters.</p>
<p>At it&#8217;s most basic use, docblocks usually look something like this when describing a function or method:</p>
<p><code><br />
/**<br />
 * This function adds two values together<br />
 * @param int $a The first value<br />
 * @param int $b The second value<br />
 * @return int The value of $a + $b<br />
 */<br />
function add_together($a, $b) {<br />
     return $a + $b;<br />
}<br />
</code></p>
<p>As you can see, including these docblocks explains in plain english what the function does, what parameters it expects, and what it will return.  This can save the next developer that reads your code tonnes of time and headaches, but most importantly of all, will make your code editor or IDE (if it supports autocompletion and docblock parsing) much more intelligent when it comes to helping you call your own methods or functions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edwardyarnold.co.uk/blog/commenting-code-invaluable-investment-of-time/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coding things the quick way &#8211; often a false economy</title>
		<link>http://www.edwardyarnold.co.uk/blog/coding-things-the-quick-way-often-false-economy</link>
		<comments>http://www.edwardyarnold.co.uk/blog/coding-things-the-quick-way-often-false-economy#comments</comments>
		<pubDate>Wed, 04 Aug 2010 07:37:41 +0000</pubDate>
		<dc:creator>Ed Yarnold</dc:creator>
				<category><![CDATA[Best Practice]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.edwardyarnold.co.uk/blog/?p=129</guid>
		<description><![CDATA[I have recently been tasked with making some changes to the central &#8216;library&#8217; of code that an E-Commerce platform is based on.  Essentially, the &#8216;models&#8217; for this application are all in a central, shared location, and all of the &#8216;installations&#8217; of the e-commerce platform have their own set of controllers and views that interact with [...]]]></description>
			<content:encoded><![CDATA[<p>I have recently been tasked with making some changes to the central &#8216;library&#8217; of code that an E-Commerce platform is based on.  Essentially, the &#8216;models&#8217; for this application are all in a central, shared location, and all of the &#8216;installations&#8217; of the e-commerce platform have their own set of controllers and views that interact with these models.  The changes I am making involve making the deletion of products reversible; so instead of actually deleting products and associated assets, a flag is merely set in the database; is_deleted = 1.  This, at first glance, seems to be quite a simple task; alter the database tables to add the extra column in, and make a change to the central models in Model_Product::deleteProduct and any product &#8216;getter&#8217; functions, eg Model_Product::getProductsByCategoryId.  However, due to the way that the platform has been developed and individual customisations to the installations of that platform have been made, things aren&#8217;t quite so simple.</p>
<p><span id="more-129"></span>The idea of the &#8216;architect&#8217; of this system was that any interaction with databases or storage of data; ie the models; would be shared in the central library.  This would mean that changes such as the one I worked on with is_deleted = 1 would be simple and made in one place, and one place only.  A true implementation of the &#8216;Don&#8217;t Repeat Yourself (DRY)&#8217; principle.</p>
<p>The nature of this platform is that it is exactly that. A platform.  This typically means that no two implementations of the platform are identical, so to speak.  The platform is built upon and &#8216;extended&#8217; to do what the individual customers want from their online shop.  This sometimes means that custom product &#8216;getter&#8217; blocks of code are written.  Often, the &#8216;quick and easy&#8217; approach had been taken with these , and they had simply been added as standalone functions in the <strong>individual project&#8217;s library</strong>, called things such as getAllProductsFlaggedAsSpecial()  This obviously meant that when I implemented my is_deleted changes in the central library, and wasn&#8217;t aware of the custom nature of these custom product selectors, the sites that used those custom product selectors continued to display deleted products.  Big oops!</p>
<p>This now means that I will need to go through the individual implementations of the platform, search for any custom product SQL that is being built, and add the AND p.is_deleted = 0 in to them.</p>
<p>This whole problem got my thinking about how I would approach this issue (The need to build custom product getter functions in individual implementations of the platform), and here&#8217;s how I think I&#8217;d do it.</p>
<p>I think I would ensure that all custom product getter functions were in fact methods in an extension of the main Model class that then called a buildWhereClause method that added any global product SQL (eg AND is_deleted = 0) in, like this:</p>
<p><code><br />
class Model_Product extends Base_Model {<br />
...<br />
function buildWhereClause($sql) {<br />
return 'WHERE p.is_deleted = 0 AND '.$sql;<br />
}<br />
...<br />
}<br />
</code></p>
<p><code><br />
class MyShopNameModel_Product extends Model_Product {<br />
function getProductsFlaggedAsSpecial() {<br />
...<br />
$sql = "SELECT * FROM product ".$this-&gt;buildWhereClause('is_special = 1');<br />
...<br />
}<br />
}</code></p>
<p>Essentially, what I learnt here was that the developer to begin with that wrote these &#8216;quick functions&#8217; saved his or herself half an hour or so, but cost me (2-3 years later) a fair amount of time in debugging.  I think this is evidence that coding things the quick way and implementing a fast solution is often a false economy, and someone later in the life of the software will have to spend the time saved (and possibly more) to work around the disadvantages of the quick approach.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edwardyarnold.co.uk/blog/coding-things-the-quick-way-often-false-economy/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Should you sanitise your HTML before or after you save to your database?</title>
		<link>http://www.edwardyarnold.co.uk/blog/when-to-sanitise-data</link>
		<comments>http://www.edwardyarnold.co.uk/blog/when-to-sanitise-data#comments</comments>
		<pubDate>Mon, 19 Apr 2010 12:52:58 +0000</pubDate>
		<dc:creator>Ed Yarnold</dc:creator>
				<category><![CDATA[Best Practice]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.edwardyarnold.co.uk/blog/?p=85</guid>
		<description><![CDATA[In starting a new project completely from scratch we need to decide whether to sanitise html (that is, convert &#38; to &#38;amp;, &#60; to &#38;lt;, and strip out blacklisted html) before or after we saved to database.  In projects I&#8217;d worked on in the past this had been done inconsistently in different areas of the [...]]]></description>
			<content:encoded><![CDATA[<p>In starting a new project completely from scratch we need to decide whether to sanitise html (that is, convert &amp; to <code>&amp;amp;</code>, &lt; to <code>&amp;lt;</code>, and strip out blacklisted html) before or after we saved to database.  In projects I&#8217;d worked on in the past this had been done inconsistently in different areas of the application &#8211; ie, pre save in some areas and on select in others.  After having thought through the problem I think I&#8217;ve decided on which option I prefer: Sanitise after selecting from the database, rather than before saving to the database.</p>
<p><span id="more-85"></span>My reasons for this decision are as follows:</p>
<ol>
<li><strong>Database collation</strong>.  Searching for strings <code>LIKE '%Ed, Ed &amp; Eddie%'</code> starts to get complicated if you have converted &amp; to &amp;amp; &#8211; you have to remember to convert entities in your search string as well.  This could also potentially mess up the effect ORDER BY clauses in the SQL queries you write have on the dataset.</li>
<li><strong>Data Integrity</strong>.  If in the future I decide that I all HTML, or just specific previously blacklisted HTML tags to be allowed, the data is all still complete and certain aspects of the data have not been removed.</li>
<li><strong>Application Consistency</strong>.  I know that if I am ever displaying data selected from the database it will need to be &#8216;sanitised&#8217; before being displayed to the user either in repopulated &#8216;edit&#8217; forms or in a normal &#8216;view&#8217; type screen.</li>
</ol>
<p>I also did a little bit of research in the cakephp manual (as we will be using cakephp for this next project) to see what cakephp creators thought about this and it seems they reached the same conclusion (quoted from <a href="http://book.cakephp.org/view/153/Data-Sanitization">this page</a>):</p>
<blockquote><p>For sanitization against XSS its generally better to save raw HTML in  database without modification and sanitize at the time of  output/display.</p></blockquote>
<p>They don&#8217;t give any specific reasons but I imagine that their thought process was similar to mine.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.edwardyarnold.co.uk/blog/when-to-sanitise-data/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

