<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Mathew Davies</title>
 <link href="http://mathew-davies.co.uk/atom.xml" rel="self"/>
 <link href="http://mathew-davies.co.uk/"/>
 <updated>2011-01-16T19:06:31+00:00</updated>
 <id>http://mathew-davies.co.uk/</id>
 <author>
   <name>Mathew Davies</name>
   <email>thepixeldeveloper@googlemail.com</email>
 </author>

 
 <entry>
   <title>Upgrading Kohana 3.0 to 3.1</title>
   <link href="http://mathew-davies.co.uk/2011/01/16/kohana-3.0-to-3.1.html"/>
   <updated>2011-01-16T00:00:00+00:00</updated>
   <id>http://mathew-davies.co.uk/2011/01/16/kohana-3.0-to-3.1</id>
   <content type="html">&lt;p&gt;&lt;em&gt;Last updated on Sunday the 16th of January 2011&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Common things to look out for when upgrading from Kohana 3.0 to 3.1&lt;/p&gt;

&lt;h2 id='auth'&gt;Auth&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hashing is now done with &lt;a href='https://github.com/kohana/auth/blob/3.1%2Fdevelop/classes/kohana/auth.php#L156'&gt;hash_hmac&lt;/a&gt;. &lt;em&gt;This will break all your current logins&lt;/em&gt;. To upgrade your user passwords, use the old function to check their passwords. If they match, generate a new hash.&lt;/li&gt;

&lt;li&gt;The ORM driver has been moved into the ORM module.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='controller'&gt;Controller&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The constructor takes 2 arguments &lt;code&gt;(Request $request, Response $response)&lt;/code&gt; over just &lt;code&gt;(Request $request)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='core'&gt;Core&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Kohana::exception_handler($e)&lt;/code&gt; has been moved to &lt;code&gt;Kohana_Exception::handler($e)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='orm'&gt;ORM&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;save()&lt;/code&gt; and &lt;code&gt;check()&lt;/code&gt; now have a Validation argument, make sure you update any child classes to ensure you don&amp;#8217;t break strict compatibility.&lt;/li&gt;

&lt;li&gt;Rules, filters and labels are now defined in public functions (rules, filters and labels) which return an array.&lt;/li&gt;

&lt;li&gt;A DB group is now specified with &lt;code&gt;$_db_group&lt;/code&gt; over &lt;code&gt;$_db&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='request'&gt;Request&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$this-&amp;gt;request-&amp;gt;controller, action, directory&lt;/code&gt; are now methods: &lt;code&gt;$this-&amp;gt;request-&amp;gt;controller(), action(), directory()&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;A response is set with: &lt;code&gt;$this-&amp;gt;response-&amp;gt;body(&amp;#39;content&amp;#39;)&lt;/code&gt; over &lt;code&gt;$this-&amp;gt;request-&amp;gt;response = &amp;#39;content&amp;#39;;&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;A new set of exceptions has been created to deal with http errors. They range from &lt;code&gt;Http_Exception_400&lt;/code&gt; to &lt;code&gt;Http_Exception_505&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='validation'&gt;Validation&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Validate has been split into two classes: &lt;code&gt;Valid&lt;/code&gt; and &lt;code&gt;Validation&lt;/code&gt;. The former houses all the rules and the latter has the logic for checking, messages, etc &amp;#8230;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;filter()&lt;/code&gt; no longer exists. Either filter manually or use &lt;code&gt;Arr::map&lt;/code&gt; if you need to filter on all values.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='php'&gt;&lt;span class='cp'&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class='c'&gt;// Filtering post values using a lambda function.&lt;/span&gt;
&lt;span class='nx'&gt;Arr&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='na'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$value&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nb'&gt;trim&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$value&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;},&lt;/span&gt;
&lt;span class='nv'&gt;$_POST&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;callback()&lt;/code&gt; has gone. Instead, &lt;code&gt;rule()&amp;#39;s&lt;/code&gt; 2nd argument can take any valid &lt;a href='http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback'&gt;PHP callback&lt;/a&gt;. The 3rd argument is an array containing the arguments to pass to the callback.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='php'&gt;&lt;span class='cp'&gt;&amp;lt;?php&lt;/span&gt; &lt;span class='nv'&gt;$validation&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;rule&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;email_available&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='k'&gt;array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;:validation&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;:field&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Callback syntax has changed from &lt;code&gt;array(&amp;#39;function&amp;#39; =&amp;gt; $params)&lt;/code&gt; to &lt;code&gt;array(&amp;#39;function&amp;#39;, $params)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id='changelog'&gt;Changelog&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sun 16 Jan 2011 - Initial version&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Nginx HTTP Server Book Review</title>
   <link href="http://mathew-davies.co.uk/2010/08/28/nginx-http-server-book-review.html"/>
   <updated>2010-08-28T00:00:00+01:00</updated>
   <id>http://mathew-davies.co.uk/2010/08/28/nginx-http-server-book-review</id>
   <content type="html">&lt;div style='float:right;margin-left:20px;'&gt;
&lt;p&gt;&lt;a href='http://www.packtpub.com/nginx-http-server-for-web-applications/book?utm_source=mathew-davies.co.uk&amp;amp;utm_medium=link&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_004261'&gt;&lt;img src='/files/nginx-server-book.jpg' alt='Nginx HTTP Server by Clement Nedelcu' /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id='introduction'&gt;Introduction&lt;/h2&gt;

&lt;p&gt;A little bit about myself before I jump into the review. My name is Mathew Davies, I&amp;#8217;m a PHP developer from a small village in England called Barton-Le-Clay and I&amp;#8217;m also roller coaster enthusiast. I run a fairly big website dedicated to my hobby (&lt;a href='http://nolimits-exchange.com'&gt;nolimits-exchange&lt;/a&gt;) so I&amp;#8217;m always on the lookout to improve performance while keeping the costs down. That&amp;#8217;s how I came to understand Nginx with its low memory and CPU requirements, perfect for my small VPS.&lt;/p&gt;

&lt;p&gt;I was kindly asked to review the book and I couldn&amp;#8217;t miss out reviewing the first Nginx book. Special thanks go to PacktPub for giving me the opportunity to do so.&lt;/p&gt;

&lt;p&gt;The book is about Nginx (aka Engine x) which is gaining a lot of popularity throughout the server world. This is down to its asynchronous architecture and low memory and CPU requirements; Perfect for squeezing more performance out of your current hardware. The book aims to convert over Apache users and anyone with an interest in &lt;em&gt;optimizing their infrastructure&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id='the_review'&gt;The Review&lt;/h2&gt;

&lt;p&gt;I was confused about the first chapter &lt;em&gt;Preparing your Work Environment&lt;/em&gt;. It explains such basics as: How to use a terminal emulator (Putty), the Linux directory layout and file permissions. The blurb gave me the impression that you should be able to administer a Linux server to a basic level, so to find this information was a bit odd. I don&amp;#8217;t expect the first chapter to be useful to the target audience. Putting this into consideration, I would remove the first chapter and make it up by going into Nginx module development; A subject which could benefit.&lt;/p&gt;

&lt;p&gt;I found one mistake in the first chapter. On page 44, the octal permissions are wrong, here is what is in the book:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 = Read&lt;/li&gt;

&lt;li&gt;2 = Write&lt;/li&gt;

&lt;li&gt;4 = Execute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and what the values should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 = Execute&lt;/li&gt;

&lt;li&gt;2 = Write&lt;/li&gt;

&lt;li&gt;4 = Read&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next chapter &lt;em&gt;Downloading and Installing Nginx&lt;/em&gt; is basic and teaches the reader how to compile Nginx along with its dependencies. It would have been educating to show the reader how to install the packages with apt-get or aptitude. I suggest this because the first chapter assumes the reader has little to zero knowledge of Linux.&lt;/p&gt;

&lt;p&gt;Chapters three till five are about the Nginx configuration directives and modules. A lot of the content here can be found online at websites like the Nginx Wiki, but it goes into more detail with real life examples. They serve as a great reference and will probably be the most used after the initial learning is over.&lt;/p&gt;

&lt;p&gt;We then get into the realm of setting up a PHP-FPM/Python combo. Just a note about the PHP-FPM guide: FPM is now part of PHP from version 5.3.3 onwards, you no longer need to apply the FPM patch. It&amp;#8217;s recommenced you avoid the patch as it&amp;#8217;s no longer maintained. I did learn something new from this chapter: Setting up PHP as an upstream server in Nginx. Normally I&amp;#8217;d just use fastcgi_pass directly to the server, but the upstream block makes it easier to scale out your application servers.&lt;/p&gt;

&lt;p&gt;If you don&amp;#8217;t want to move to Nginx right away, it might be a good idea to keep Apache as the backend and use Nginx as the front-end. This means you can free Apache of processing your static files (css and js) which gives it a bit more memory to play with; Your static content will get served faster too! &lt;em&gt;Apache and Nginx Together&lt;/em&gt; goes into how you would set this up and describes common problems you might encounter (forwarding client IP addresses, SSL issues, etc &amp;#8230;)&lt;/p&gt;

&lt;p&gt;So, you&amp;#8217;ve decided to move to Nginx after hearing how great it is, now you&amp;#8217;re thinking &amp;#8220;Where do I start?&amp;#8221;. &lt;em&gt;From Apache to Nginx (Chapter 8)&lt;/em&gt; will be able to help you there. Personal experience of being on the Nginx mailing list tells me this chapter is going to be helpful to those who are strugging to port over their rewrite rules and server configurations. Direct comparisons have been between both software configuration styles so it&amp;#8217;s easy to see how Apache directives translate. Rewrite rules for popular web applications such as Wordpress have been included for convenience and even more can be found online at the Nginx Wiki.&lt;/p&gt;

&lt;h2 id='conclusion'&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The book was an enjoyable read and I took away some methods which will help scale my website in the future. I&amp;#8217;d certainly recommend the book to anyone who doesn&amp;#8217;t use Nginx (just to see what they&amp;#8217;re missing out on) or a basic Nginx user who wants to further their knowledge on the subject. It covers most of what you&amp;#8217;ll need and makes improvements where the Nginx Wiki is lacking.&lt;/p&gt;

&lt;p&gt;One suggestion: Page 105 &lt;em&gt;Upgrading Nginx Gracefully&lt;/em&gt; should include how to switch back to your old Nginx process if the new one failed to work. Here is how that would be done:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nb'&gt;kill&lt;/span&gt; -HUP 123 - this will restart the workers under the old master process
&lt;span class='nb'&gt;kill&lt;/span&gt; -QUIT 321 - shuts down the new master process workers
&lt;span class='nb'&gt;kill&lt;/span&gt; -TERM 321 - shuts down the new master process
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Source: &lt;a href='http://www.softwareprojects.com/resources/programming/t-recompileupgrade-nginx-binary-with-no-down-time-1520.html'&gt;Software Projects Inc - Upgrade nginx binary with no down-time&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also spotted a minor syntax error (missing “;”) and a bit of code that was copied and pasted, but not changed. That said, it&amp;#8217;s a great book and despite its mistakes I recommend purchasing it.&lt;/p&gt;

&lt;p&gt;A free chapter is available from PacktPub, check it out: &lt;a href='https://www.packtpub.com/sites/default/files/0868-chapter-3-basic-nginx-configuration_1.pdf'&gt;Basic Nginx Configuration&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='more_nginx_resources'&gt;More Nginx Resources&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The Nginx Wiki: Great for documentation and tips. These two pages are invaluable; Read and understand them: &lt;a href='http://wiki.nginx.org/Pitfalls'&gt;Nginx Pitfalls&lt;/a&gt; and &lt;a href='http://wiki.nginx.org/IfIsEvil'&gt;If Is Evil&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;The &lt;a href='http://nginx.org/mailman/'&gt;Nginx Mailing list&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='biography'&gt;Biography&lt;/h2&gt;

&lt;p&gt;I specialize in PHP development and work with the Kohana framework. I have several open source modules available and they can be found on my github page: &lt;a href='http://github.com/thepixeldeveloper'&gt;thepixeldeveloper&lt;/a&gt;. I&amp;#8217;m available for hire and can be contacted using the email address in the website footer.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>What I've learned in the past year while running a website.</title>
   <link href="http://mathew-davies.co.uk/2010/08/16/what-ive-learnt-in-the-past-year-while-running-a-website.html"/>
   <updated>2010-08-16T00:00:00+01:00</updated>
   <id>http://mathew-davies.co.uk/2010/08/16/what-ive-learnt-in-the-past-year-while-running-a-website</id>
   <content type="html">&lt;p&gt;It&amp;#8217;s been one year since my little hobby project &lt;a href='http://nolimits-exchange.com'&gt;Nolimits-Exchange&lt;/a&gt; went online. I&amp;#8217;ve learned a lot over that year and I&amp;#8217;d like to share some of what I&amp;#8217;ve learned with you.&lt;/p&gt;

&lt;h2 id='advertising'&gt;Advertising&lt;/h2&gt;

&lt;p&gt;Adsense was very poorly suited to the content of my website. I had a lot of Public Service Ads which although nice, don&amp;#8217;t make &lt;em&gt;any&lt;/em&gt; money. It was not worth annoying my users for the sake of 30 dollars a year.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re currently experimenting with another company. I&amp;#8217;d love to say who, but that would be a breach of contract.&lt;/p&gt;

&lt;h2 id='backups'&gt;Backups&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve always backed up data with Amazon S3 via Duplicity; It&amp;#8217;s cheap enough and works well, but I came across something better. I switched to an alternative called &lt;a href='http://www.tarsnap.com/'&gt;tarsnap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write only encryption keys: I can be sure my backups wont be destroyed when the server is compromised.&lt;/li&gt;

&lt;li&gt;Pay as you go: This avoids any nasty surprises that could occur in my Amazon invoice.&lt;/li&gt;

&lt;li&gt;It has a similarity to tar, hence the name. It makes writing backup scripts easier.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It&amp;#8217;s slightly more expensive at $0.30/GB-month versus Amazon&amp;#8217;s $0.15/GB-month.&lt;/p&gt;

&lt;h2 id='community'&gt;Community&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;ve had to ban a few members and one thing to look out for is suicide threats. I made the the assumption it was an empty threat and didn&amp;#8217;t do anything about it. Don&amp;#8217;t make that mistake and &lt;strong&gt;report the incident to the local police department&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;&lt;cite&gt;Source: &lt;a href='http://webmasters.stackexchange.com/questions/1031/how-do-you-handle-suicide-threats'&gt;How do you handle suicide threats&lt;/a&gt;.&lt;/cite&gt;
&lt;p&gt;You should handle it just like any other threat to someone&amp;#8217;s life. A person threatening suicide, or to kill someone else, is still threatening to kill someone. The only sensible thing to do is try and report it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Beyond that it&amp;#8217;s been a lot of fun meeting up with the community in real life.&lt;/p&gt;

&lt;p&gt;I had a lot of help from &lt;a href='http://www.communityspark.com/'&gt;Community Spark&lt;/a&gt; when starting. It features a lot of advice about choosing your staff, kick-starting your community, banning members, etc &amp;#8230;&lt;/p&gt;

&lt;h2 id='development'&gt;Development&lt;/h2&gt;

&lt;p&gt;The amount of improvement I&amp;#8217;ve seen in my programming is a reminder that I&amp;#8217;m not progressing as slowly as I&amp;#8217;d thought. Take this example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original code&lt;/strong&gt;: The XML is a string ($this-&amp;gt;output) that was concatenated at various points.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='php'&gt;&lt;span class='cp'&gt;&amp;lt;?php&lt;/span&gt; &lt;span class='nb'&gt;defined&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;SYSPATH&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;OR&lt;/span&gt; &lt;span class='k'&gt;die&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;No direct access allowed.&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Sitemap_Driver&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='c'&gt;// XML header&lt;/span&gt;
	&lt;span class='k'&gt;const&lt;/span&gt; &lt;span class='no'&gt;header&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='c'&gt;// XML output&lt;/span&gt;
	&lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='nv'&gt;$output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='c'&gt;// Change frequency&lt;/span&gt;
	&lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='nv'&gt;$changefreq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;always&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;hourly&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;daily&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;weekly&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;monthly&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;yearly&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;never&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

	&lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; &lt;span class='nf'&gt;__construct&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
	&lt;span class='p'&gt;{&lt;/span&gt;
		&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;output&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;self&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='na'&gt;header&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;PHP_EOL&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
	&lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1 year later&lt;/strong&gt;: I&amp;#8217;m using the DOMDocument class which offers formatting, syntax checking and an easier API to work with.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='php'&gt;&lt;span class='cp'&gt;&amp;lt;?php&lt;/span&gt; &lt;span class='nb'&gt;defined&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;SYSPATH&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;or&lt;/span&gt; &lt;span class='k'&gt;die&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;No direct script access.&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Kohana_Sitemap&lt;/span&gt;
&lt;span class='p'&gt;{&lt;/span&gt;
	&lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;	 * @var DOMDocument&lt;/span&gt;
&lt;span class='sd'&gt;	 */&lt;/span&gt;
	&lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='nv'&gt;$_xml&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;	 * @var DOMElement&lt;/span&gt;
&lt;span class='sd'&gt;	 */&lt;/span&gt;
	&lt;span class='k'&gt;protected&lt;/span&gt; &lt;span class='nv'&gt;$_root&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

	&lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;	 * Setup the XML document&lt;/span&gt;
&lt;span class='sd'&gt;	 */&lt;/span&gt;
	&lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; &lt;span class='nf'&gt;__construct&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
	&lt;span class='p'&gt;{&lt;/span&gt;
		&lt;span class='c'&gt;// XML document&lt;/span&gt;
		&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_xml&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;DOMDocument&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;Kohana&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='nv'&gt;$charset&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

		&lt;span class='c'&gt;// Attributes&lt;/span&gt;
		&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_xml&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;formatOutput&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;TRUE&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

		&lt;span class='c'&gt;// Root element&lt;/span&gt;
		&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_root&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_xml&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;createElement&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;urlset&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

		&lt;span class='c'&gt;// Append to XML document&lt;/span&gt;
		&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_xml&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;appendChild&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;_root&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
	&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So take a look at your old code and be proud that you&amp;#8217;re improving.&lt;/p&gt;

&lt;h2 id='deployment'&gt;Deployment&lt;/h2&gt;

&lt;p&gt;When you have a busy website, you realise how important it is to keep the downtime to a minimum when pushing an update. The horror of FTP&amp;#8217;ing a tarball to a server, then unpacking it only to find it didn&amp;#8217;t work is a crap feeling (at best). This is why I learnt about version control, proper website deployment and database migrations.&lt;/p&gt;

&lt;p&gt;I now use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://git-scm.com/'&gt;Git&lt;/a&gt; for code version control,&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.capify.org/'&gt;Capistrano&lt;/a&gt; for deploying the websites &amp;amp;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.liquibase.org/'&gt;LiquiBase&lt;/a&gt; for database migrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downtime is no longer than 10 seconds and if I ever need to, can revert to an earlier state. I know &lt;em&gt;very&lt;/em&gt; few developers that know all three, how are you surviving without migrations?&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;d like to learn more about Capistrano, then my article &lt;a href='http://mathew-davies.co.uk/2009/10/28/php-deployment.html'&gt;PHP Deployment&lt;/a&gt; might be helpful to you.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Nginx Server Book Preview</title>
   <link href="http://mathew-davies.co.uk/2010/08/15/nginx-server-book-preview.html"/>
   <updated>2010-08-15T00:00:00+01:00</updated>
   <id>http://mathew-davies.co.uk/2010/08/15/nginx-server-book-preview</id>
   <content type="html">&lt;div style='float:right;margin-left:20px;'&gt;
&lt;p&gt;&lt;a href='http://www.packtpub.com/nginx-http-server-for-web-applications/book?utm_source=mathew-davies.co.uk&amp;amp;utm_medium=link&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_004261'&gt;&lt;img src='/files/nginx-server-book.jpg' alt='Nginx HTTP Server by Clement Nedelcu' /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I will be reviewing &lt;a href='http://www.packtpub.com/nginx-http-server-for-web-applications/book?utm_source=mathew-davies.co.uk&amp;amp;utm_medium=link&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_004261'&gt;Nginx HTTP Server by Clement Nedelcu&lt;/a&gt; very shortly. So to you get excited, here is a preview of what the book covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get started with Nginx to serve websites faster and safer&lt;/li&gt;

&lt;li&gt;Learn to configure your servers and virtual hosts efficiently&lt;/li&gt;

&lt;li&gt;Set up Nginx to work with PHP and other applications via FastCGI&lt;/li&gt;

&lt;li&gt;Explore possible interactions between Nginx and Apache to get the best of both worlds&lt;/li&gt;

&lt;li&gt;A step-by-step guide to switching from Apache to Nginx&lt;/li&gt;

&lt;li&gt;Complete configuration directive and module reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Source: &lt;a href='https://www.packtpub.com/nginx-http-server-for-web-applications/book?utm_source=mathew-davies.co.uk&amp;amp;utm_medium=link&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_004261'&gt;PacktPub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a Nginx fanatic, I am glad to see it get some face time.&lt;/p&gt;

&lt;p&gt;If you can&amp;#8217;t wait for the review and would like to purchase it, then visit the PacktPub store by clicking on the book image.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Nginx Logwatch Configuration</title>
   <link href="http://mathew-davies.co.uk/2010/06/22/nginx-logwatch-configuration.html"/>
   <updated>2010-06-22T00:00:00+01:00</updated>
   <id>http://mathew-davies.co.uk/2010/06/22/nginx-logwatch-configuration</id>
   <content type="html">&lt;p&gt;My installation of logwatch did not detect I was running Nginx and thus did not create the configuration files for me. Here is how I fixed that:&lt;/p&gt;

&lt;p&gt;This will only work if you use the &lt;em&gt;combined&lt;/em&gt; access log format. Create the following file:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;/usr/share/logwatch/dist.conf/logfiles/http.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and insert the data below:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='nv'&gt;LogFile&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; /usr/local/nginx/logs/access.log
&lt;span class='nv'&gt;Archive&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; /home/website/logs/old/access.*.log.*.gz

&lt;span class='c'&gt;# Expand the repeats (actually just removes them now)&lt;/span&gt;
*ExpandRepeats

&lt;span class='c'&gt;# Keep only the lines in the proper date range...&lt;/span&gt;
*ApplyhttpDate
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Hopefully that helped someone out.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Uninstalling Lubuntu</title>
   <link href="http://mathew-davies.co.uk/2010/06/19/uninstalling-lubuntu.html"/>
   <updated>2010-06-19T00:00:00+01:00</updated>
   <id>http://mathew-davies.co.uk/2010/06/19/uninstalling-lubuntu</id>
   <content type="html">&lt;p&gt;If you tried lubuntu-desktop and decided you didn’t like it, you’d probably be right in thinking a quick removal of the lubuntu-desktop package would do the job. Well it didn’t (for me). Here’s how I fully removed it:&lt;/p&gt;

&lt;p&gt;Open a terminal and run this command:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;sudo aptitude purge abiword aqualung cheese epdfview galculator gnome-mplayer
gnumeric gpicview leafpad lubuntu-artwork lubuntu-default-settings lubuntu-desktop 
lubuntu-plymouth-theme lxappearance lxdm lxinput lxlauncher lxrandr lxsession-edit
lxshortcut lxterminal mtpaint ntp obconf osmo parcellite pidgin powernowd 
pyneighborhood simple-scan sylpheed transmission wvdial xarchiver xfburn 
xfce4-taskmanager xserver-xorg-input-evtouch
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In order to &lt;strong&gt;fully&lt;/strong&gt; remove it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Free Admin Template</title>
   <link href="http://mathew-davies.co.uk/2010/03/13/free-admin-template.html"/>
   <updated>2010-03-13T00:00:00+00:00</updated>
   <id>http://mathew-davies.co.uk/2010/03/13/free-admin-template</id>
   <content type="html">&lt;p&gt;A professional admin template ready to use in your personal and commerical projects free of charge.&lt;/p&gt;
&lt;div class='clearfix'&gt;

&lt;div style='float:right;margin-left:20px;'&gt;
&lt;p&gt;&lt;img src='/files/admin-template/dashboard.png' alt='The Dashboard' /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Dashboard&lt;/h2&gt;

&lt;p&gt;Inspired by the BBC homepage. The dashboard features moveable blocks allowing the user to customise the website to their liking.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides a quick overview of system information.&lt;/li&gt;

&lt;li&gt;Links in the header can be used to dynamically load more data or jump to a section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href='/admin-template/dashboard.html'&gt;View the dashboard&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;hr /&gt;&lt;div class='clearfix'&gt;

&lt;div style='float:left;margin-right:20px;'&gt;
&lt;p&gt;&lt;img src='/files/admin-template/form.png' alt='Form' /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Forms&lt;/h2&gt;

&lt;p&gt;Clean, smooth and user friendly.&lt;/p&gt;

&lt;p&gt;&lt;a href='/admin-template/news.html'&gt;View the form&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;hr /&gt;&lt;div class='clearfix'&gt;

&lt;div style='float:right;margin-left:20px;'&gt;
&lt;p&gt;&lt;img src='/files/admin-template/list.png' alt='Table' /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Table&lt;/h2&gt;

&lt;p&gt;&lt;a href='/admin-template/user.html'&gt;View the table&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id='donations'&gt;Donations&lt;/h2&gt;

&lt;p&gt;If this template helped to speed up your day to day work then consider a donation. My paypal email address is in the website footer.&lt;/p&gt;

&lt;h2 id='modifications'&gt;Modifications&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Robert Jan Dreu has made a jQuery port. &lt;a href='http://www.dreu.info/resources/Admin-Template-JQuery.zip'&gt;Download it&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='download'&gt;Download&lt;/h2&gt;

&lt;p&gt;The template source code is open-source and can &lt;a href='http://github.com/ThePixelDeveloper/admin-template'&gt;downloaded at github&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Smush.it PHP Class</title>
   <link href="http://mathew-davies.co.uk/2010/01/01/smushit-php-class.html"/>
   <updated>2010-01-01T00:00:00+00:00</updated>
   <id>http://mathew-davies.co.uk/2010/01/01/smushit-php-class</id>
   <content type="html">&lt;p&gt;This small class makes use of the &lt;a href='http://smush.it'&gt;Smush.it&lt;/a&gt; service provided by Yahoo to compress images.&lt;/p&gt;

&lt;p&gt;So far only web accessible images can be compressed, but I&amp;#8217;m working on a solution so local images can be compressed too.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='php'&gt;&lt;span class='cp'&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt; * Description: Compresses images using Smush.it&lt;/span&gt;
&lt;span class='sd'&gt; * &lt;/span&gt;
&lt;span class='sd'&gt; * @license MIT&lt;/span&gt;
&lt;span class='sd'&gt; * @author  Mathew Davies &amp;lt;thepixeldeveloper@googlemail.com&amp;gt;&lt;/span&gt;
&lt;span class='sd'&gt; */&lt;/span&gt;
&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;smushit&lt;/span&gt; 
&lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;const&lt;/span&gt; &lt;span class='no'&gt;user_agent&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;Smush.it PHP Class (+http://mathew-davies.co.uk)&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

    &lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='nv'&gt;$curl&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;NULL&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

    &lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;     * Smush.it request URL&lt;/span&gt;
&lt;span class='sd'&gt;     */&lt;/span&gt;
    &lt;span class='k'&gt;const&lt;/span&gt; &lt;span class='no'&gt;url&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;http://www.smushit.com/ysmush.it/ws.php&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

    &lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;     * Make sure any prerequisite are installed.&lt;/span&gt;
&lt;span class='sd'&gt;     */&lt;/span&gt;
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; &lt;span class='nf'&gt;__construct&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt; &lt;span class='nb'&gt;extension_loaded&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;json&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;RuntimeException&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;The json extension was not found&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt; &lt;span class='nb'&gt;extension_loaded&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;curl&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;RuntimeException&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;The cURL extension was not found.&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;

        &lt;span class='c'&gt;// cURL handler&lt;/span&gt;
        &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;curl&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;curl_init&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

        &lt;span class='c'&gt;// Return HTTP response&lt;/span&gt;
        &lt;span class='nb'&gt;curl_setopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;curl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;TRUE&lt;/span&gt; &lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    
    &lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;     * Compress image using smush.it. Image must be available online&lt;/span&gt;
&lt;span class='sd'&gt;     *&lt;/span&gt;
&lt;span class='sd'&gt;     * @param  string url to image.&lt;/span&gt;
&lt;span class='sd'&gt;     * @throws Smush_exception&lt;/span&gt;
&lt;span class='sd'&gt;     * @return object&lt;/span&gt;
&lt;span class='sd'&gt;     * &lt;/span&gt;
&lt;span class='sd'&gt;     *  src       = source location of input image&lt;/span&gt;
&lt;span class='sd'&gt;     *  src_size  = size of the source image in bytes&lt;/span&gt;
&lt;span class='sd'&gt;     *  dest      = temporary location of the compressed image&lt;/span&gt;
&lt;span class='sd'&gt;     *  dest_size = size of compressed image in bytes&lt;/span&gt;
&lt;span class='sd'&gt;     *  percent   = how much smaller the compressed image is&lt;/span&gt;
&lt;span class='sd'&gt;     */&lt;/span&gt;
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; &lt;span class='nf'&gt;compress&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$image&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='c'&gt;// Set appropriate URL.&lt;/span&gt;
        &lt;span class='nb'&gt;curl_setopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;curl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;CURLOPT_URL&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;self&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='na'&gt;url&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;?&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nb'&gt;http_build_query&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='k'&gt;array&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;img&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;$image&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='c'&gt;// Set user agent&lt;/span&gt;
        &lt;span class='nb'&gt;curl_setopt&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;curl&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;CURLOPT_USERAGENT&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;self&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='na'&gt;user_agent&lt;/span&gt; &lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='c'&gt;// Execute the HTTP request&lt;/span&gt;
        &lt;span class='nv'&gt;$request&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;curl_exec&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;curl&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='c'&gt;// JSON response&lt;/span&gt;
        &lt;span class='nv'&gt;$result&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;json_decode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$request&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nb'&gt;isset&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt; &lt;span class='nv'&gt;$result&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;error&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;Smush_exception&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$result&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;error&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;$image&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
        
        &lt;span class='nv'&gt;$result&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;dest&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;urldecode&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$result&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;dest&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        
        &lt;span class='c'&gt;// Return response data&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nv'&gt;$result&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt; * Custom exception handler&lt;/span&gt;
&lt;span class='sd'&gt; */&lt;/span&gt;
&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Smush_exception&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nx'&gt;Exception&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;

    &lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;     * Path to image&lt;/span&gt;
&lt;span class='sd'&gt;     * @var string $image&lt;/span&gt;
&lt;span class='sd'&gt;     */&lt;/span&gt;
    &lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='nv'&gt;$image&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

    &lt;span class='sd'&gt;/**&lt;/span&gt;
&lt;span class='sd'&gt;     * Overload the exception construct so we can provide an image name&lt;/span&gt;
&lt;span class='sd'&gt;     * @param string $message&lt;/span&gt;
&lt;span class='sd'&gt;     * @param string $image&lt;/span&gt;
&lt;span class='sd'&gt;     */&lt;/span&gt;
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt;  &lt;span class='nf'&gt;__construct&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$message&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;$image&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;image&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nv'&gt;$image&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='k'&gt;parent&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='na'&gt;__construct&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;$message&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='c'&gt;// Return image path.&lt;/span&gt;
    &lt;span class='k'&gt;final&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; &lt;span class='nf'&gt;getImage&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nv'&gt;$this&lt;/span&gt;&lt;span class='o'&gt;-&amp;gt;&lt;/span&gt;&lt;span class='na'&gt;image&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;On average I save 17% per image. Not bad when you have thousands like I do.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Happy New Year</title>
   <link href="http://mathew-davies.co.uk/2009/12/31/happy-new-year.html"/>
   <updated>2009-12-31T00:00:00+00:00</updated>
   <id>http://mathew-davies.co.uk/2009/12/31/happy-new-year</id>
   <content type="html">&lt;p&gt;This year wasn&amp;#8217;t bad!&lt;/p&gt;

&lt;p&gt;I launched a new roller coaster website called &lt;a href='http://nolimits-exchange.com'&gt;Nolimits-Exchange&lt;/a&gt; in mid August. It had over 300,000 page views in the space of 5 months so I’m quite impressed with that, I’ll be aiming for 2 million in 2010. I also created a little PHP class which may be of use to some of you.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d like to thank you for the comments left on my deployment article. Hopefully the world of PHP is a better place.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>PHP Deployment</title>
   <link href="http://mathew-davies.co.uk/2009/10/28/php-deployment.html"/>
   <updated>2009-10-28T00:00:00+00:00</updated>
   <id>http://mathew-davies.co.uk/2009/10/28/php-deployment</id>
   <content type="html">&lt;p&gt;Learn how to deploy PHP applications the &lt;em&gt;proper&lt;/em&gt; way using Capistrano.&lt;/p&gt;

&lt;h2 id='introduction'&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Picture this scenario: You’ve finished your work for the week, it’s time to relax, but you get an urgrent call from your client, “Matt!, There’s a bug on the site. It needs fixing now!”. You quickly scramble to get it fixed as fast as possible, so you login to the server, edit the file from the terminal and the day is saved “hooray”.&lt;/p&gt;

&lt;p&gt;There are a few flaws with this method of fixing bugs, lets see what they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since the file was edited directly there’s no change log, so you’ll have to keep a personal record. Wouldn’t it be easier if you could add notes (or messages) when you commit changes to code?&lt;/li&gt;

&lt;li&gt;The patch didn’t work and now you have to roll back (sigh). You should have tested locally first, but you were so frantic you forgot (it happens). How would you roll back quickly and easily? If it takes more than a second then it’s too long.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a slow and error prone way of dealing with an emergency. I wonder how we can make this better &amp;#8230;&lt;/p&gt;

&lt;h2 id='using_version_control'&gt;Using version control&lt;/h2&gt;

&lt;p&gt;I’ll be using &lt;a href='http://bazaar.canonical.com/en/'&gt;bazaar&lt;/a&gt; for my deployment, but there’s a huge choice out there. Here are a few you might be interested in: &lt;a href='http://git-scm.com/'&gt;Git&lt;/a&gt;, &lt;a href='http://subversion.tigris.org/'&gt;Subversion&lt;/a&gt;, &lt;a href='http://www.nongnu.org/cvs/'&gt;CVS&lt;/a&gt; or &lt;a href='http://mercurial.selenic.com/'&gt;Mercurial&lt;/a&gt;&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;sudo aptitude install bzr
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='set_up_capistrano'&gt;Set up Capistrano&lt;/h2&gt;

&lt;p&gt;Capistrano is client side software which means we are done touching the server (for now). Prerequisites for deployment are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href='http://www.capify.org/index.php/Capistrano'&gt;capistrano&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/jamis/capistrano-ext'&gt;capistrano-ext&lt;/a&gt; (used for its multi-stage plugin)&lt;/li&gt;

&lt;li&gt;&lt;a href='http://github.com/leehambley/railsless-deploy'&gt;railsless-deploy&lt;/a&gt; (overrides rails actions that don’t apply to PHP)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='writing_the_recipe'&gt;Writing the recipe.&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I’ll assume you have a local code repository setup and populated with content.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From a directory outside of the code repo (unless you want to version your recipe files) run:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;capify .
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here is the output of that command:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;&lt;span class='o'&gt;[&lt;/span&gt;add&lt;span class='o'&gt;]&lt;/span&gt; writing &lt;span class='s1'&gt;&amp;#39;./Capfile&amp;#39;&lt;/span&gt;
&lt;span class='o'&gt;[&lt;/span&gt;add&lt;span class='o'&gt;]&lt;/span&gt; making directory &lt;span class='s1'&gt;&amp;#39;./config&amp;#39;&lt;/span&gt;
&lt;span class='o'&gt;[&lt;/span&gt;add&lt;span class='o'&gt;]&lt;/span&gt; writing &lt;span class='s1'&gt;&amp;#39;./config/deploy.rb&amp;#39;&lt;/span&gt;
&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;done&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; capified!
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since I’ll be using the multi-stage plugin (you don’t have to) I need to modify the “Capfile” that was generated.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;load&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;deploy&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nb'&gt;respond_to?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:namespace&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='c1'&gt;# cap2 differentiator&lt;/span&gt;

&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;railsless-deploy&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;capistrano/ext/multistage&amp;#39;&lt;/span&gt;

&lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:stages&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='sx'&gt;%w(staging production)&lt;/span&gt;
&lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:default_stage&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;staging&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here we have included the extensions, defined our stages and setup a default stage. All self explanatory. Recipes follow the following structure:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='bash'&gt;config/deploy/:stage
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can find an &lt;a href='http://gist.github.com/211105'&gt;example recipe on my gist page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From here on out it’s normal capistrano deployment procedure so I wont bother repeating what’s on the internet already. I’m happy to answer any questions you may have though.&lt;/p&gt;</content>
 </entry>
 
 
</feed>