<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
	<channel>
		<title>Blog</title>
		<link>http://www.dind.com/blog/software-engineering/</link>
		<description></description>
		<language>en-us</language>
		<pubDate>Fri, 18 May 2012 20:00:26 PDT</pubDate>
		<lastBuildDate>Fri, 18 May 2012 20:00:26 PDT</lastBuildDate>
		<generator>SiteCrafting.com GearBox 1.1 (beta)</generator>
		
		<item>
			<title>Two Dollars</title>
			<link>http://www.sitecrafting.com/blog/dollars/</link>
			<description>Two dollars is a small amount, but two is a magical number. Despite it's seeming insignificance, two represents the difference between doing a job, and doing it right.One summer while I was still in college, I worked in a brewery in Colorado waiting tables. I recommend that everyone work in a restaurant at some time in their life. It teaches you a lot about life and service. While I was working there, I began to understand the value of such a small amount, and how much good work is worth.If you don't know, servers (at least in the US) rely on tips as their soruce of income. In Colorado, I earned a paltry $2.25 per hour, and that was only enough to cover the taxes on what I earned in tips. Washington is a little better, because retaurant owners are required to pay the minimum hourly wage, unlike Colorado where tips count towards that sum.Often, the difference between a great tip and an average tip is two  dollars, and the same is true between average tips and poor tips. In a place like the one where I worked, the average customer bill was around $12 ($8 for dinner, $4 for a drink). When 3 or 4 people came into eat, they usually ended up ordering about $40 worth of food and drinks. On that total, a 10% tip is $4.00. A 15% tip is $6.00. That's a two dollar difference, but it makes a huge difference for the server. The actual value of $2 is small - sometimes I can find that much in the seats of my car, and it costs me more than that to do my laundry. The result of the extra $2 is huge. Your server is happier, and happy servers mean better service, increased patronage, and more satisfied customers.What it comes down to is that the $2 represents a willingness to go the extra mile,&amp;nbsp; or the difference between just doing something, and doing it right. Or the difference between doing something right, and getting it perfect. I've heard many stories about people that wanted to make a website - to help their business, to show off their talents, or just for fun - but they balk when they hear what their idea is going to cost. Many people miss the fact that it takes effort to do anything, and whether the cost of that effort is time, money, or blood and sweat, the difference between doing it right and not is huge.This happened to me last year. For every day for about two weeks, and when ever I wasn't in class or asleep, I was working in my studio on a piece for my senior art exhibition. Every day I'd get up at 8:00am, and work until around midnight. I hated the piece while I was working on it because it was so much work, and took so much effort. But, I realized that I had come up with something that could be really good. And so I put in the effort to make sure that it was perfect, that every component of it worked like it was supposed to. When I was done, the only words that I could use to describe it was 'Wow.'For all you developers out there, heed my words. If you take the time to do your projects right, it will only benefit you. Encourage clients that are willing to let you do your job the way you know how. And for anyone looking to hire someone to make a website, establish a level of trust with your developers and then let them do their job. It's ok to want proof of their abilities, but if you don't trust them they will only disappoint you. The $2 attention to detail ends up producing products that are much more valuable than you could ever imagine. From the client point of view, if save two minutes of work a thousand times, that adds up to two thousand minutes, or 33 and a third hours. Little by little, those small savings add up into something huge. And for developers, having a few really happy clients makes more clients that are willing to refer you to people they know. And that means better work, and continued success. Anybody can do this, but you have to actually work for it. And make sure to go that extra mile for the people that take care of you.</description>
			<pubDate>Wed, 15 Nov 2006 10:39:00 PST</pubDate>
		</item>
			
		<item>
			<title>Two Dollars - Follow up</title>
			<link>http://www.sitecrafting.com/blog/dollars-follow-up/</link>
			<description>In response to my last post, one reader mentioned that sometimes clients take advantage of a developer's generosity, and that it seemed like I wanted the developers to grin and bear it to keep their clients happy. This is actually quite different from what I wanted to say, and so I want to expand on that a little, and why it's very important for both developers and clients to have a written set of guidelines to keep projects on track.In my last article, I wanted to tell developers that creating something that works perfectly is almost the only acceptable outcome of a job. For example: do you notice how the gas gauge in your car (or someone's car, if you don't have one) changes depending on the angle the car is sitting on? If the car is perfectly level, the gauge reads correctly, but on hills the level may be deceptively low or high, depending on where the sensor is in the tank. This is hardly a problem when it comes to using the car; it'll keep driving as long as there is some amount of gas in the tank, but it bugs me.I don't have a clue how modern fuel gauges work, but it's really easy  to solve this problem: put four sensors in the tank, one at each  corner. Average the output from the sensors, and you have a system that  will display exactly how much gas is in the tank, regardless of any  incline. You could even calibrate the sensors to return the exact  volume of the remaining gas if you wished. Drivers don't notice any change in functionality, it just works better.The confusion comes in when developers take the last article to mean that they have to do whatever the client wants, but that is far from the truth. It benefits both clients and developers greatly to have a Specifications Document written up and signed, before any work on a project begins. (Specifications Documents are documents that use plain but specific language to define the scope of a project)I'm sure that most people, developers and customers alike, have had a situation where a contracted project went horribly wrong. I am no different. Usually, it's a lack of communication that causes this problem. The developer may promise something, and then forget about until 6 months into a project, or the customer may forget to mention a vital part of the project. The best way to fix this is to write out the agreement before a project starts.Also, make sure to use very specific language that leaves no room for assumptions or interpretations. If you are creating reports from a webservice, stating that you will &quot;Create a handful of reports&quot; is a problem. How many is a handful? Two? Six? A hundred? I can hold a gigabyte flash drive in my hand, so does that mean I need to write a gigabyte worth of reports code? What you should do instead is put a specific number on how many reports you'll make, and then define each one. Developers don't really care how many you want, but we need to know up front.Then, when a customer asks for something new, or even a modification of an existing piece, you'll be able to point to your document and say, &quot;We never talked about this before.&quot; This is really handy when you have a signed document to point to, and it can be done when no document exists. It's as easy as, &quot;Have we talked about this before?&quot;. But, if the agreements were verbal, it's possible to forget what you agreed to especially months after work has started. Creating that document will save developers and designers many headaches, and it's also very beneficial to their clients as well. When the clients are sending out RFP's, they want to know for how long a project will take, and how much it'll cost. They also don't want surprises, and having a good, detailed proposal will go a long way. It's beneficial for them to be able to remind developers that some key functionality is missing. There aren't any nasty fights, or contract disputes, and that makes everyone happy.Writing that document is incredibly important, and there is no good reason to not create it. If you don't have any specifications, there is still hope. As a developer, you can ask the client if you have talked about this before. If you are talking about a new feature or modification, asking for additional payment will probably be needed. Sometimes, though, someone will ask for something new, but they won't want to pay for it. In this case, it's acceptable to politely say, &quot;I can't do that for free&quot;. After all, we do have to eat.Probably the most important part of any web project is the Specifications Document, but they are very seldom used. When they are used, they are usually vague and leave a lot of room for interpretation. This is the cause of most headaches relating to software, and I'm campaigning to get everyone to expect and demand good specifications. I've been bugging Brian about this so much that we're now doing it for every new project, no exceptions. Having this kind of document benefits everyone, so start writing. And remember, be specific.</description>
			<pubDate>Mon, 20 Nov 2006 11:55:00 PST</pubDate>
		</item>
			
		<item>
			<title>Use Functions for Readable Code</title>
			<link>http://www.sitecrafting.com/blog/functions-readable-code/</link>
			<description>  On my way to meeting with a client, I got into a conversation about using functions in your code. One of the guys learned to write assembly first, and so his stance was that creating functions was only feasible when you used the same code more than (about) three times. That view makes a certain sense - don't deal with the overhead of creating tons of functions for stuff you'll seldom use. I argue that you should use functions where ever possible, first because it makes code easier to generalize (and thus re-use), but also because it makes code much more readable.   To illustrate my point, here are two fictional but entirely probable examples. And here's some guidelines: Whitespace does not count as a line, but { and } do.Only  lines of code that are unique to the specific example will be counted, because if you can use 8 lines of code by writing one, it's really only one new line of code.Statement format is consistent throughout - that means that if I condense 3 statements into a single line of code, condensation is done universallyExample 1: Get All Rows From a Table    The Assembly (aka Code Soup) Way:$sql = &quot;SELECT * FROM table&quot;;$result = mysql_query($sql);if($result) {&amp;nbsp;&amp;nbsp;&amp;nbsp; $rows = array();&amp;nbsp;&amp;nbsp;&amp;nbsp; while($row = mysql_fetch_array($result)) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $rows[] = $row;&amp;nbsp;&amp;nbsp;&amp;nbsp; }}That's pretty straight forward, and takes 8 lines of code. Pretty simple, and easy to understand for most programmers with experience. The main drawback is that code is only useful in that one situation.Now my way:$rows = getRows('table');function getRows($table) {&amp;nbsp;&amp;nbsp;&amp;nbsp; $sql = &quot;SELECT * FROM $table&quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp; $result = query($sql);&amp;nbsp;&amp;nbsp;&amp;nbsp; return fetchAll($result);}function query($sql) {&amp;nbsp;&amp;nbsp;&amp;nbsp; return mysql_query($sql);}function fetchAll($result) {&amp;nbsp;&amp;nbsp;&amp;nbsp; $rows = array();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while($row = fetch($result)) {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  $rows[] = $row;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; return $rows;}function fetch($result) {&amp;nbsp;&amp;nbsp;&amp;nbsp; return mysql_fetch_array($result);}There's 19 lines of code in this method, however only one is unique to this situation (the first one - all the functions can be reused). This method is also readable by just about anyone including your boss (ok, so maybe that's not really a good thing). It's also terrifically easy to maintain and extend this code. True, in two cases (query and fetch), I'm just renaming PHP functions, but that makes them so much easier to type, it's worth doing to save time.Example 2: Displaying input fields for a form in a tableThis is a pretty common occurrence in web development. Let's say you want to create a form, and use a table to format it on the page nicely. We know that designing with tables is bad, but sometimes it happens. We'll have four fields in our table: a text field, a textarea, a file input, and a textarea following that. Think of this as a heading, some text, an image, and a caption for that image. Here's how the Code Soup version might look: (I've left off tag attributes except input types for brevity's sake)echo '&amp;lt;form&amp;gt;';echo '&amp;lt;table&amp;gt;';echo '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Heading&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;heading&quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';echo '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Content&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea name=&quot;content&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';echo '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Image&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;image&quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';echo '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Caption&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea name=&quot;caption&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';echo '&amp;lt;/table&amp;gt;';echo '&amp;lt;/form&amp;gt;';That's 8 lines of code, all legible and usable. But we can do better. Notice that we have two textareas, and the only thing that changes between them is the name of the field. We can generalize this, and also make that fragment much more readable, like this:echo '&amp;lt;form&amp;gt;';echo '&amp;lt;table&amp;gt;';echo inputRow('Heading', 'heading');echo textareaRow('Content', 'content');echo fileRow('Image', 'image');echo textareaRow('Caption', 'caption');echo '&amp;lt;/table&amp;gt;';echo '&amp;lt;/form&amp;gt;';function inputRow($label, $name) {&amp;nbsp;&amp;nbsp;&amp;nbsp; return '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'.$label.'&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&quot;text&quot; name=&quot;'.$name.'&quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';}function fileRow($label, $name) {&amp;nbsp;&amp;nbsp;&amp;nbsp; return  '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'.$label.'&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input  type=&quot;file&quot; name=&quot;'.$name.'&quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';}function textareaRow($label, $name) {&amp;nbsp;&amp;nbsp;&amp;nbsp; return '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'.$label.'&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea name=&quot;'.$name.'&quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;';}Again, the functions use slightly more lines of code than the Soup version, but there are two huge benefits from using functions. Number one is increased legibility, and number two is reuse. The main code block that uses functions is a whole lot easier to work with than the one that doesn't. Also, you can use those functions anywhere on your site, and get rid of the overhead of writing out '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;...&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;' every time you just want to add a text input to the form. I used this same method to shrink part of our CMS from ~700 lines of code to less than 100, and it's a lot easier to modify now.Properly using functions and classes can help your coding a lot. It can speed up development, make maintenance easier, and even help you make better software. So go function crazy. If you create a function that makes your life easier, try to make that function even easier to use. But remember, functions shouldn't do two (or more) different things. If you have a function that updates a database and prints out a page template, split it into two functions. Also, never, never ever declare a function in multiple places in the same project. If you have many instances of a function to update a database, or capture form submissions, it totally defeats the purpose of making functions in the first place.</description>
			<pubDate>Fri, 01 Dec 2006 08:41:00 PST</pubDate>
		</item>
			
		<item>
			<title>Diary of a Developing Developer</title>
			<link>http://www.sitecrafting.com/blog/diary-developing-developer/</link>
			<description>I never had any idea how complicated, confusing, and involved the development of web sites and web-based applications can truly be. When I was younger, every once in a while I would look at a web page and click the &quot;view source&quot; option and think, &quot;Wow, that really doesn't look too difficult to learn.&quot;Little did I know there is so much more behind the code than what is seen in that one snapshot of HTML.Working for SiteCrafting has really been a great experience and has given me the chance to work in an area I've always been interested in and am starting to enjoy more every day. On-the-job training, however, can be both the easiest and hardest way to learning something that's very involved and complicated. It's easy because I have a wealth of knowledge sitting all around me at work that can answer my questions and give me one-on-one assistance when I get stuck. I never dreamed of getting a job where I can have 9 teachers to 1 student when usually the ratio is turned around with something like 1 teacher to 25 students or more. The hard thing is that I'm starting out by looking at, what to me are, very complicated applications and involved coding and working back towards the basics instead of starting with the basics and working towards more difficult applications. Although I've read through helpful tutorials for HTML, CSS, and PHP, that only goes so far. Actually coding, testing, finding it wrong, getting frustrated, re-doing, and having things re-explained is where the actual learning takes place. Fortunately, I am enjoying ( mostly :) ) every minute of it.Seeing what's involved in the development of web applications SiteCrafting produces has certainly given me a new appreciation for the expertise, hard work, and effort put into clients and their projects. I am certainly eager to keep learning as I get more and more involved in development work.</description>
			<pubDate>Tue, 16 Jan 2007 11:23:00 PST</pubDate>
		</item>
			
		<item>
			<title>Making a PHP Script Timer</title>
			<link>http://www.sitecrafting.com/blog/making-php-script-timer/</link>
			<description>I've been ranting about a lot of things lately, but not many of them are related to my job description. I want to take a bit of time, and go back to good old PHP, CSS, and Javascript. Today, I'm going to go over how to create a execution timer that will let you know how much time has passed since it started. There are a number of benefits to using one of these things, for example to track down why a script would take 77 seconds to complete rather than 3 or less. (It was a bloated SQL query)First off, we need to figure out what kind of information we need. The only data we'll be dealing with is a time stamp, but we'll need a few functions. For example, we'll need a function to start the timer, and minimally one to tell us how much time has passed since it was started.It would be pretty simple to make this timer with procedural programming, ie functions, but I'm going to use an object simply for the encapsulation issue - I can store all variables and functions inside the object and not worry about scoping and how information gets passed around. The functions aren't such a big deal, but this is really helpful for the time variable.So, here's Timer, revision 1:class Timer {&amp;nbsp;&amp;nbsp;&amp;nbsp; var $time;&amp;nbsp;&amp;nbsp;&amp;nbsp; function set() {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  list($usec, $sec) = explode(&quot; &quot;, microtime());&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  $this-&amp;gt;time = ((float)$usec + (float)$sec);&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; function elapsed() {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  list($usec, $sec) = explode(&quot; &quot;, microtime());  &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; $now = ((float)$usec + (float)$sec);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; return $now - $this-&amp;gt;time;&amp;nbsp;&amp;nbsp;&amp;nbsp; }}Analysis:First off, it takes two lines of code to initialize, namely $timer = new Timer(); and $timer-&amp;gt;set(); It would be better if we could use one line to start it.Second, the method to get the current time is used twice. Since they are identical, why not make it a function?Timer, revision 2:class Timer {  &amp;nbsp;&amp;nbsp;&amp;nbsp; var $time;&amp;nbsp;&amp;nbsp;&amp;nbsp; function Timer() {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  $this-&amp;gt;set();&amp;nbsp;&amp;nbsp;&amp;nbsp; }    &amp;nbsp;&amp;nbsp;&amp;nbsp; function set() {  &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  $this-&amp;gt;time = $this-&amp;gt;now();  &amp;nbsp;&amp;nbsp;&amp;nbsp; }    &amp;nbsp;&amp;nbsp;&amp;nbsp; function elapsed() {  &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; return $this-&amp;gt;now() - $this-&amp;gt;time;  &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; function now() {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  list($usec, $sec) = explode(&quot; &quot;, microtime());      &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; return ((float)$usec + (float)$sec);&amp;nbsp;&amp;nbsp;&amp;nbsp; }  }Analysis:We took care of both problems from last revision, but it's not done yet. What happens if, after creating the timer, you want to reset it to the current time? Since we're explicitely calling the set() function, this isn't immediately possible. Sure, it could be done by an explicit call to the set() function, but that can get confusing. Grasshopper: &quot;The timer doesn't need to have the set function called?&quot;  PHP Guru: &quot;No, the object does that automatically.&quot;Grasshopper: &quot;So why do I have to call the set function?&quot;Guru: &quot;You must call the set function whenever you wish to set the timer time to the current time.&quot;Now that just doesn't make sense. Set is something you do to start a thing, and the functionality that was described there was more like a reset action. So, let's add a reset function. This could be done a couple of ways. Reset could just call $this-&amp;gt;set(), but then you end up with two functions with identical functionality. Instead, why not just rename set to reset? The user never sees the initial reset action, so it won't be confusing, and they can use the reset function and know exactly what it does every time.Final Thoughts:The now() function is kind of akward. It is possible to use get the time as a float right from that function via a boolean flag, but that wasn't added until PHP 5.1.0, and so it wouldn't work universally.It would be possbile to make $time an array, and allow labels to be set on start times. It wouldn't be difficult, and the semantic benefits of implementing that would be very big. However, I have other plans in mind that I'll share next time when I create an interface for this to be used on any website.</description>
			<pubDate>Fri, 26 Jan 2007 16:14:00 PST</pubDate>
		</item>
			
		<item>
			<title>Script Timing, v2</title>
			<link>http://www.sitecrafting.com/blog/script-timing-v2/</link>
			<description>  Last time, I outlined a way to create a simple PHP script timer. I use this timer in many of the projects that I work on, and it's really helpful to nail down trouble spots in scripts. The thing that it lacks, however, is a decent display. When you call the elapsed()  function, it only gives you a number. Creating a decent display for each timer call is tedious and boring. So I simplified it. Now, I'm going to extend the existing Timer class and add some new functionality - make it look better and make it easier to call and display the information.  Take a quick look at the class I developed last time, because I'm going to build on that this time. PHP, just like any Object Oriented language, offers the ability to build on classes using the extends keyword. Basically, this means that the new class is a variant, or child, of the class that's getting extended. The children classes inherit all functions and data not marked as private from the parent classes. This class will look prettier than the previous timer, so I'll call it Pretty_Timer. (Original, huh?)class Pretty_Timer extends Timer {}There's several things that I want to add to this timer, but the first one is a label for the timer. That will help minimize confusion when viewing the output of the timer.class Pretty_Timer extends Timer {&amp;nbsp;&amp;nbsp;&amp;nbsp; var $label;&amp;nbsp;&amp;nbsp;&amp;nbsp; function Pretty_Timer($label = &quot;&quot;) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parent::Timer();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;label = $label;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; function elapsed() {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $time = parent::elapsed();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;label.&quot;: &quot;.$time;&amp;nbsp;&amp;nbsp;&amp;nbsp; }}You'll notice that I put the label in the constructor rather than as a separate method. That's to avoid two lines of code to simply set the label. It's optional, so you're not forced into using the label if you don't want to. Also, we have to explicitely call the parent constructor, of the object's time value won't be initialized.In the elapsed function, I'm getting the elapsed time from the parent Timer, and displaying that and this object's label together. This is pretty useful, but it's still not much to look at. I want add some formatting and CSS to make it look good.class Pretty_Timer extends Timer {&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $style = 'padding: .25em; margin: .25em; font-family: arial, sans-serif; font-size: 9pt;';&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $green = 'background: #cfc; border-top: 2px solid #0c0; border-bottom: 2px solid #0c0;';&amp;nbsp;&amp;nbsp;&amp;nbsp; var $yellow = 'background: #ffc; border-top: 2px solid #fd0; border-bottom: 2px solid #fd0;';&amp;nbsp;&amp;nbsp;&amp;nbsp; var $red = 'background: #fcc; border-top: 2px solid #f00; border-bottom: 2px solid #f00;';&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $label;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function Pretty_Timer($label = &quot;&quot;) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parent::Timer();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;label = $label;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function elapsed($formatted = true) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $time = parent::elapsed();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($formatted) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $out = ''.($this-&amp;gt;label != &quot;&quot; ? ''.$this-&amp;gt;label.' ' : 'Elapsed Time: ').$time.'';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $out;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $time;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }}I've added in some styles, and set it up so that if the elapsed time is greater than half a second, the display will be yellow, as a warning. Your scripts should be running faster than that anyways. If they take more than two seconds, they show up red. People will begin to notice the delay at that point, and you don't want users waiting to use your application. There's also some basic formatting in there, for margins and padding. You should also take note that the elapsed function has a boolean parameter that will remove the formatting if you want it to.This is all well and good, but there's still something lacking. In the context of an HTML page, you might want to get time information after the page has begun to load. To make that easiser I created a function that has one line of code: echo $this-&amp;gt;elapsed(); There isn't a whole lot of difference using this function, display_elapsed(), or the single line of code that it executes, but most IDE's have auto complete, so it's easier and faster to call $timer-&amp;gt;display_elapsed();.So with a little tweaking, we can make the timer faster and easier to use. To show off the functionality, if we have some code that looks like this:$timer = new Pretty_Timer(&quot;My Timer&quot;);$second = new Pretty_Timer(&quot;Another Timer&quot;);echo &quot;Just started the timers...&quot;;$timer-&amp;gt;display_elapsed();echo &quot;doing some complex calculations...&quot;;intense_function();$second-&amp;gt;display_elapsed();$second-&amp;gt;reset();echo &quot;reset the second timer...&quot;;$second-&amp;gt;display_elapsed();echo &quot;A few more calculations that are even more intense...&quot;;complex_calculations();$timer-&amp;gt;display_elapsed(); The output will look like so:And here's the final class:class Pretty_Timer extends Timer {&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var $style = 'padding: .25em; margin: .25em; font-family: arial, sans-serif; font-size: 9pt;';&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var $green = 'background: #cfc; border-top: 2px solid #0c0; border-bottom: 2px solid #0c0;';&amp;nbsp;&amp;nbsp;&amp;nbsp; var $yellow = 'background: #ffc; border-top: 2px solid #fd0; border-bottom: 2px solid #fd0;';&amp;nbsp;&amp;nbsp;&amp;nbsp; var $red = 'background: #fcc; border-top: 2px solid #f00; border-bottom: 2px solid #f00;';&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var $label;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function Pretty_Timer($label = &quot;&quot;) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parent::Timer();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;label = $label;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function elapsed($formatted = true) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $time = parent::elapsed();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($formatted) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $out = ''.($this-&amp;gt;label != &quot;&quot; ? ''.$this-&amp;gt;label.' ' : 'Elapsed Time: ').$time.'';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $out;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $time;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function display_elapsed() {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo $this-&amp;gt;elapsed();&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; }?&amp;gt;</description>
			<pubDate>Fri, 02 Feb 2007 10:11:00 PST</pubDate>
		</item>
			
		<item>
			<title>if (date('z') == 256) echo("It's Programmers Day")</title>
			<link>http://www.sitecrafting.com/blog/if-datez-256-echoits-programmers-1/</link>
			<description>For those that aren't aware, Programmers' Day is today and marks the 256th day of the year. If you just thought to yourself &quot;wow, that's 1111 1111 in binary!&quot; then consider today to be a day in your honor. In case you're wondering why this particular day was chosen, consider this: 1111 1111 is the last of the 256 possible values of a byte.While Programmers' Day is largely informal, it makes for an excellent opportunity to appreciate the programmers in your life. If you happen to be a developer yourself, you may want to start passing along hints about that binary clock you've been eyeing over at ThinkGeek.com.In the spirit of Programmers' Day, post a comment suggesting what you will be doing today in order to celebrate. If you're feeling particularly nerdy, feel free to make your post in ASCII binary.</description>
			<pubDate>Thu, 13 Sep 2007 11:45:00 PDT</pubDate>
		</item>
			
		<item>
			<title>PHP Patterns, Part I</title>
			<link>http://www.sitecrafting.com/blog/php-patterns-part/</link>
			<description>  This is the first in a planned series of articles discussing the application of various PHP patterns. If you're still getting your feet wet developing in PHP (or programming languages in general), you may be wondering what a &quot;pattern&quot; is in the first place. The best place to find a quick explanation is over in Wikipedia's article (which does a much better job than I could hope to do within the scope of this article).Now, let's move on to the fun part . . .I. The Registry Pattern, an IntroductionI am going to kick off this series by introducing you to the registry pattern. First, imagine you are deep into a complex web application and you come to the realization that you have several objects that all require access to your database. Your first inclination may be to simply have each class initiate their own connection to the database and use it as they please. But then you'll start to hear that little voice in the back of your head, screaming something about how you're needlessly wasting valuable system resources and bandwidth. Naturally you ask what else you could do - this is where&amp;nbsp; a registry comes in handy.A registry object basically acts as a container for objects that you want to be universally accessible throughout your project, while avoiding the use of . . . gulp . . . global variables! You'll find that its implementation is fairly simple, but extremely powerful and convenient.II. Class DefinitionLet's take a look at what a registry class is made of:class Registry {&amp;nbsp;&amp;nbsp;&amp;nbsp; protected $_objects = array();&amp;nbsp;&amp;nbsp;&amp;nbsp; function set($name, &amp;amp;$object) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;_objects[$name] =&amp;amp; $object;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; function &amp;amp;get($name) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;_objects[$name];&amp;nbsp;&amp;nbsp;&amp;nbsp; }}Look at that! Pretty short and sweet eh? Now let's rip it apart and see what each component does:Following the class definition, we have a protected class variable called $_objects which is an array that holds all the objects that are added to the registry.Next we find our first function called set which is inherently public. This function is used to add an object instance to the registry. You pass it the object instance, and pick a friendly name to remember it by (don't forget it, you'll need it later!).Finally we have our second and final function get which retrieves an object previously added to the registry. Simply supply the friendly name you picked earlier and it will return the instance to you.You may be wondering what that ampersand (&amp;amp;) is doing up in front of the function name. This tells the function to return the object by reference rather than making a copy of it and returning the copy (which would make all this work pointless, since we again would be wasting resources). This means that any changes or actions performed on the object will be reflected everywhere else it is used in your application.III. Less Talk, More Action!Now that we have the basic concept outlined, let's take a look at how we might use our new creation. Let's say we have a simple class that returns a user's name, and another class that checks if a given user has &quot;admin&quot; status. In practice you would probably group this functionality into a single class, but for the sake of illustration we will pretend Captain Obvious is on vacation:// First we create our database and registry // objects$db = new databaseConnection();$registry = new registry();// Then we add the db object to the registry// It will now be available anywhere the registry // is also available!$registry-&amp;gt;add(&quot;database&quot;, $db);// Now we create the objet that gets our username // and checks for admin status$user = new username($registry);$admin = new admin($registry);$username = $user-&amp;gt;getUser(12);$isAdmin = $admin-&amp;gt;check($username);// Finally, we display the user's infoecho(&quot;Username: &quot;.$username.&quot;&amp;lt;br /&amp;gt;&quot;);echo(&quot;Is Admin? &quot;.$isAdmin);Now, you'll have to use your imagination to see how the two objects are able to use the same database instance, but let's take a peek into what they both do://----- snip -----// First they get the database object from the // registry$databaseObj = $registry-&amp;gt;get(&quot;database&quot;);// Then they use it as they see fit$databaseObj-&amp;gt;query(&quot;SELECT username FROM users&quot;.&amp;nbsp; &amp;nbsp; &quot; WHERE id=$userId&quot;);//----- snip -----Congratulations, you have just learned how to create and use a registry! Now go forth and use what you have learned to write more efficient code!</description>
			<pubDate>Thu, 27 Sep 2007 15:17:00 PDT</pubDate>
		</item>
			
		<item>
			<title>PHP Patterns, Part II</title>
			<link>http://www.sitecrafting.com/blog/php-patterns-part-ii/</link>
			<description>  In this installment, we will be looking at two patterns that have been 'borrrowed' from Java. If you've had any development experience with J2EE, you are probably well aware of how handy Data Access Objects and Value Objects can be. If you haven't, don't fret! This article was written especially for you!If you've never heard these terms before, you may be wondering why I  have chosen to group them together within one article. The simple  explanation is ... well you'll see. For now just accept that they go  hand-in-hand, much like salt and pepper or peanut butter and jelly or  .Excited? Let's dig deeper...I. Data Access Objects (DAOs) and Value Objects (VOs), an IntroductionThese two classes comprise what is often called the &quot;model&quot; layer of the MVC (Model View Control) model. If you aren't familiar with this concept do yourself a huge favor and read up on it - it will save you and your peers quite a bit of time further down the road on any project.The DAO is basically the object you use to query your data source within your application. Rather than sprinkling SQL queries throughout your code, it allows you to encapsulate everything related to accessing your database within a single class. That way, if you ever change databases or need to tweak a query, you can do it in one place that's easy to find. Think of it like a filing cabinet that keeps all your papers from floating all over your desk.The VO does what you might expect a &quot;value object&quot; to do - it holds values. It provides you with a nifty object to pass around your application and typically contains a single row of information from your database. Again the goal here is to simplify the process of handling data retrieved from the database.II. The VO, A Closer LookCreating a VO is probably one of the simplest classes you will ever create. It basically mirrors a table in your database, with setter and getter methods for each field in that table. First, let's pretend you have a simple database table called &quot;users&quot; that has the following columns:iduserpassUsing this information, we can create our very first Value Object:class&amp;nbsp;UserVO&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$id;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$username;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$password;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setId($id)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;id&amp;nbsp;=&amp;nbsp;$id;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getId()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;id;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setUsername($username)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;username =&amp;nbsp;$username;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getUsername()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;username;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setPassword($password)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;password =&amp;nbsp;$password;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getPassword()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;password;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}}Pretty simple and to the point, huh? You may be wondering why I have gone through and written explicit setters and getters for each value, rather than just making two generic functions (or simply making the class variables public). The primary reason for this has more to do with coding standards than anything else. It is usually good practice to prevent class variables from being accessed directly. This way you don't have to anticipate what might happen ouside the class. By declaring functions for each specific value, you have more control over the use of each value as well. For instance, where appropriate, you could use the addslashes() and stripslashes()&amp;nbsp; functions to automatically massage data before it is inserted into the database.II. The DAO, A Closer LookNow that we have created our first VO, let's take a look at its partner in crime, the DAO. Let's take a look at some code before we start picking it apart:class&amp;nbsp;UserDAO&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;var&amp;nbsp;$connect;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;var&amp;nbsp;$db;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Attempts&amp;nbsp;to&amp;nbsp;initialize&amp;nbsp;the&amp;nbsp;database&amp;nbsp;connection&amp;nbsp;using&amp;nbsp;the&amp;nbsp;supplied&amp;nbsp;info.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;UserDAO($host,&amp;nbsp;$username,&amp;nbsp;$password,&amp;nbsp;$database)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;connect&amp;nbsp;=&amp;nbsp;mysql_connect($host,&amp;nbsp;$username,&amp;nbsp;$password);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;db&amp;nbsp;=&amp;nbsp;mysql_select_db($database);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Executes&amp;nbsp;the&amp;nbsp;specified&amp;nbsp;query&amp;nbsp;and&amp;nbsp;returns&amp;nbsp;an&amp;nbsp;associative&amp;nbsp;array&amp;nbsp;of&amp;nbsp;reseults.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;function&amp;nbsp;execute($sql)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$res&amp;nbsp;=&amp;nbsp;mysql_query($sql,&amp;nbsp;$this-&amp;gt;connect)&amp;nbsp;or&amp;nbsp;die(mysql_error());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(mysql_num_rows($res)&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for($i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;$i&amp;nbsp;&amp;lt;&amp;nbsp;mysql_num_rows($res);&amp;nbsp;$i++)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$row&amp;nbsp;=&amp;nbsp;mysql_fetch_assoc($res);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO[$i]&amp;nbsp;=&amp;nbsp;new&amp;nbsp;UserVO();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO[$i]-&amp;gt;setId($row[id]);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO[$i]-&amp;gt;setUsername($row[username]);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO[$i]-&amp;gt;setPassword($row[password]);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$userVO;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Retrieves&amp;nbsp;the&amp;nbsp;corresponding&amp;nbsp;row&amp;nbsp;for&amp;nbsp;the&amp;nbsp;specified&amp;nbsp;user&amp;nbsp;ID.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getByUserId($userId)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;&quot;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&amp;nbsp;WHERE&amp;nbsp;id=&quot;.$userId;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;execute($sql);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Retrieves&amp;nbsp;all&amp;nbsp;users&amp;nbsp;currently&amp;nbsp;in&amp;nbsp;the&amp;nbsp;database.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getUsers()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;&quot;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;execute($sql);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Saves&amp;nbsp;the&amp;nbsp;supplied&amp;nbsp;user&amp;nbsp;to&amp;nbsp;the&amp;nbsp;database.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;save($userVO)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affectedRows&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if($userVO-&amp;gt;getId()&amp;nbsp;!= &quot;&quot;)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$currUserVO&amp;nbsp;=&amp;nbsp;$this-&amp;gt;getByUserId($userVO-&amp;gt;getId());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;If&amp;nbsp;the&amp;nbsp;query&amp;nbsp;returned&amp;nbsp;a&amp;nbsp;row&amp;nbsp;then&amp;nbsp;update,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;otherwise&amp;nbsp;insert&amp;nbsp;a&amp;nbsp;new&amp;nbsp;user.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(sizeof($currUserVO)&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;= &quot;UPDATE users SET &quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;username='&quot;.$userVO-&amp;gt;getUsername().&quot;', &quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;password='&quot;.$userVO-&amp;gt;getPassword().&quot;' &quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;WHERE id=&quot;.$userVO-&amp;gt;getId();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mysql_query($sql,&amp;nbsp;$this-&amp;gt;connect)&amp;nbsp;or&amp;nbsp;die(mysql_error());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affectedRows&amp;nbsp;=&amp;nbsp;mysql_affected_rows();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;&quot;INSERT&amp;nbsp;INTO&amp;nbsp;users&amp;nbsp;(username,&amp;nbsp;password)&amp;nbsp;VALUES('&quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO-&amp;gt;getUsername().&quot;', &quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$userVO-&amp;gt;getPassword().&quot;')&quot;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mysql_query($sql,&amp;nbsp;$this-&amp;gt;connect)&amp;nbsp;or&amp;nbsp;die(mysql_error());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affectedRows&amp;nbsp;=&amp;nbsp;mysql_affected_rows();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$affectedRows;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Deletes&amp;nbsp;the&amp;nbsp;supplied&amp;nbsp;user&amp;nbsp;from&amp;nbsp;the&amp;nbsp;database.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;delete($userVO)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affectedRows&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Check&amp;nbsp;for&amp;nbsp;a&amp;nbsp;user&amp;nbsp;ID.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if($userVO-&amp;gt;getId()&amp;nbsp;!= &quot;&quot;)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$currUserVO&amp;nbsp;=&amp;nbsp;$this-&amp;gt;getByUserId($userVO-&amp;gt;getId());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Otherwise delete a user.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(sizeof($currUserVO)&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;&quot;DELETE&amp;nbsp;FROM&amp;nbsp;users&amp;nbsp;WHERE&amp;nbsp;id=&quot;.$userVO-&amp;gt;getId();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mysql_query($sql,&amp;nbsp;$this-&amp;gt;connect)&amp;nbsp;or&amp;nbsp;die(mysql_error());&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affectedRows&amp;nbsp;=&amp;nbsp;mysql_affected_rows();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$affectedRows;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}}The Data Access Object consists a handful of basic methods. First is the constructor, which basically initiates the connection to the database. You pass it the database connection info and credentials, and it takes care of the rest. Next comes the getter functions, which basically represent a collection of the queries used to access the database. For example, you might have a getByUserId() method that returns the UserVO we created above filled with the corresponding data for a particular user ID.Following the getters is the save() function, which essentially does what you would imagine it does. You pass a VO to it and it will either update an existing record if it finds one that matches the VO or will insert a new row. I'll bet you're thinking what I thought the first time I learned of this function: &quot;holy cow! that just reduced 8+ lines of code down to one!&quot;Finally we have the big scary delete() function that, you guessed it, deletes a record from the database. To make it slightly less scary, it requires that you pass it a VO that matches a database row exactly. This will force you to have first retrieved the row you want to delete before calling this method. This helps prevent the accidental deletion of a record.And there you have it! Together these two classes can save you a tremendous amount of effort and time, makes it much easier to maintain say 6-12 months from now when you have completely forgotten how you wrote that file manager script.A side note: If you live in fear of having to write these classes for databases with 100 tables that have 200 columns each, don't despair! With the help of Google you can find countless PHP DAO and VO generators that will build the code for you (take a look here for example). Some will do it based on existing database tables, and others will do it based on what you tell them. They might still require some tweaking afterwards, but at least that way the hard part would be done and over with.</description>
			<pubDate>Wed, 14 Nov 2007 15:48:00 PST</pubDate>
		</item>
			
		<item>
			<title>Android: The REAL Next Gen of Web Apps</title>
			<link>http://www.sitecrafting.com/blog/android-real-gen-web-apps/</link>
			<description>  If the iPhone is web apps to go, Google and the Open Handset Alliance's new open source mobile phone API, dubbed Android, is The Joy Of Cooking Webapps. Once again Google has seen a good idea (packing a cell phone full of convenient little apps and widgets that sync with websites and external systems) and figured out a way to make it a great one.  If you haven't been following the news on Android, here's the basic scoop: Google has teamed with a group of phone manufacturers (T Mobile, Motorola, etc, just to name a few of the biggies) to create the Open Handset Alliance, who are running on a pretty basic principle (and one that Big OS Developers) have still failed to grasp. If everyone is competing to get the best developers to work on their system, nobody is going to get the best software. So much time is wasted working within proprietary systems and on cross-platform compatibility that the chance for true innovation is weakened, if not lost altogether. Let software engineers come up with what they're trained for: good software ideas. Someone who wants to write a killer chat widget for a cell phone shouldn't have to sit around trying to decide what phone they're going to sink their time and code into. The telecom industry is in such flux that it's impossible to tell just which company is going to be big, or bought, or gone tomorrow.Hence, the OHA introduces a common API, one that the involved parties are commited to using (some say they'll have Android-ready handsets come Q4 of 2008), one that allows open source developers all over the world to simply code, writing Java programs secure in the knowledge (unless something goes horribly awry) that they won't be tied to a single manufacturer.On top of the usefullness of a generalized API, this alliance fosters innovation in another way: once a group of competing vendors band together on something like this, proprietary development concerns go out the window. Apple is still stuck trying to keep most of the iPhone development in house. Android, on the other hand, is blatantly relying on the open source community. And since it is built on the backs of pure hardware vendors, no one has a service provider looking over their shoulder going &quot;Oh no, what if someone ports Skype to this phone? We're doomed!&quot; Well, maybe they are still looking... but they no longer have the power to stop it.What really excites me here, though, is just how much force Google is putting behind getting the developer community involved. With Monday's SDK release, a full year before the first Android-enabled handsets will hit the market, they took a major step toward ensuring the success of the project. I've toyed with the system a bit, and I tell you it is sweet. In addition to command line tools and serious documentation, they've also wrapped the whole toolkit up in an Eclipse plug-in, complete with an incredibly thorough simulation setup: a visual representation of a full-keypad handset, complete with already installed and fully functional browser, Google maps, and address book... you can even place calls (no, they don't go through, but it does record them in a recent call list for you). As if just putting the tools out there wasn't enough, suddenly there's the Android Developer Challenge, complete with $10 million in cash prizes to encourage innovation and development.I don't know about anyone else, but this whole thing excites me to no end. I don't really have aspirations of winning any of that money... I've only done minimal Java development in the last couple years. But it feels good to get in on the ground floor of something that feels like it could be genuinely revolutionary. This really is the next step. Here at SiteCrafting we've already started building mobile web interfaces for some of our clients' more complex business management apps. I'm eagerly anticipating the day when we don't have to put together tiny webpages for field managers to use, because they've got a genuine application on their phone, grabbing and updating live data from the system we've built them.So maybe I won't win $25,000 by having and executing one of the best 50 ideas by February, but everyone in telecommunications, software engineering, web development, and, well... pretty much everyone has a lot to gain from the work that's going to be spawned here in the next few months. I've already started work on my new Android app. Have you?</description>
			<pubDate>Wed, 14 Nov 2007 00:01:00 PST</pubDate>
		</item>
			
		<item>
			<title>Technical Debt</title>
			<link>http://www.sitecrafting.com/blog/technical-debt/</link>
			<description>The concept of technical debt (first coined by Ward Cunningham) has been something that has wandered about my head without a name for quite some time. The other day I read an article that finally put it into words. It is what I have always seen as the reason writing beautiful code is not just an endeavor in aesthetics. At this point you're probably wondering what the heck I'm rambling on about. Don't give up on me yet, I'm about to explain . . .For most developers, time is a commodity that is often scarce and very expensive for our employers. With a resource in such high demand, it is no surprise that there is a temptation to do what we can to conserve it. Certainly there is nothing wrong with being efficient, but there is also a point at which efficiency ends and technical debt begins. Technical debt is created when we start to write sloppy code, &quot;hacks,&quot; or make other wreckless time-saving maneuvers. While we may save time in the immediate future, we are actually incurring a debt that will eventually have to be repaid, with interest.The interest basically encompasses the extra time and effort we have to spend fixing bugs and making improvements as a result of the earlier shortcuts that were made. Just like financial debt, technical debt can be paid off. This is done  through code rewrites and corrections to bring the quick-and-dirty code  up to snuff. The longer we leave the debt unpaid, the more the interest grows until it ultimately can bring a development team to its knees.Technical debt can actually be a useful tool,  if handled responsibly. You can choose the quick-and-dirty route to save time and meet a deadline, and then later repay that debt by fixing the code afterwards. This way you can release planned functionality on-time and &quot;save face&quot; if you are developing software for a client or third party. Be weary of this practice though, while clients may only be concerned that something &quot;works&quot; they will also be the first ones to complain when something goes wrong and it takes you unusually long to fix it. Just like a credit card, this approach requires that you follow through with your obligation to repay your balance later.So the next time you're deep into a project and you think &quot;I could throw something together in 5 minutes and everything will work&quot; don't forget that the 5 minutes you saved could cost you hours six months later when a client requests new features or bug fixes. Make sure it's a debt you are able and willing to repay.</description>
			<pubDate>Fri, 21 Dec 2007 10:19:00 PST</pubDate>
		</item>
			
		<item>
			<title>PHP Patterns, Part III</title>
			<link>http://www.sitecrafting.com/blog/php-patterns-part-iii/</link>
			<description>The Template Object (or TO) is a design pattern of my own that I developed to fill the role of the View layer in the MVC model. As you have probably figured out, the purpose of the TO is to handle everything related to the user interface. The idea here is to separate the interface as much as possible from the rest of the application, so that we could do a complete rewrite of an application without ever touching (or accidentally &quot;breaking&quot;) the view portion.This object was designed around a template model, in which the HTML/CSS is stored completely independent of the template object. Using this approach, the appearance of the web application and how it operates are completely decoupled. Both the view layer and the rest of the application can be completely replaced without affecting each other.So before I bore you to death with my talking, let's take a look at some code. Below is some sample code for an abstract TemplateObject class, and then a basic FormTO class that would be useful for a basic web form:/**&amp;nbsp;*&amp;nbsp;Abstract&amp;nbsp;TemplateObject&amp;nbsp;Class&amp;nbsp;*/abstract&amp;nbsp;class&amp;nbsp;TemplateObject&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;abstract&amp;nbsp;function&amp;nbsp;render();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;abstract&amp;nbsp;function&amp;nbsp;setTemplate($template);}/**&amp;nbsp;*&amp;nbsp;Generic&amp;nbsp;Form&amp;nbsp;Template&amp;nbsp;Object&amp;nbsp;*/class&amp;nbsp;FormTO&amp;nbsp;extends&amp;nbsp;TemplateObject&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$template;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$method;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$action;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;$name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Default&amp;nbsp;Constructor&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$method&amp;nbsp;the&amp;nbsp;form&amp;nbsp;method&amp;nbsp;(post/get)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$action&amp;nbsp;the&amp;nbsp;form&amp;nbsp;action&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$name&amp;nbsp;the&amp;nbsp;name&amp;nbsp;of&amp;nbsp;the&amp;nbsp;form&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$template&amp;nbsp;the&amp;nbsp;location&amp;nbsp;of&amp;nbsp;the&amp;nbsp;template&amp;nbsp;file&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;__construct($method&amp;nbsp;=&amp;nbsp;post,&amp;nbsp;$action&amp;nbsp;=&amp;nbsp;,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$name&amp;nbsp;=&amp;nbsp;,&amp;nbsp;$template&amp;nbsp;=&amp;nbsp;)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;template&amp;nbsp;=&amp;nbsp;$template;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;method&amp;nbsp;=&amp;nbsp;$method;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;action&amp;nbsp;=&amp;nbsp;$action;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;$name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;Renders&amp;nbsp;the&amp;nbsp;page&amp;nbsp;using&amp;nbsp;the&amp;nbsp;currentlyl&amp;nbsp;stored&amp;nbsp;values.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;render()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;include($this-&amp;gt;template);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&amp;nbsp;Exception($ex)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(The&amp;nbsp;specified&amp;nbsp;template&amp;nbsp;was&amp;nbsp;invalid.);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setTemplate($template)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;template&amp;nbsp;=&amp;nbsp;$template;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setMethod($method)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;method&amp;nbsp;=&amp;nbsp;$method;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;function&amp;nbsp;printMethod()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print($this-&amp;gt;method);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getMethod()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;method;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setAction($action)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;action&amp;nbsp;=&amp;nbsp;$action;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;function&amp;nbsp;printAction()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print($this-&amp;gt;action);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getAction()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;action;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setName($name)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$this-&amp;gt;name&amp;nbsp;=&amp;nbsp;$name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected&amp;nbsp;function&amp;nbsp;printName()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print($this-&amp;gt;name);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;getName()&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$this-&amp;gt;name;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}}As you can see this is a fairly simple setup. We have a simple Template Object that we can use to set various values for the page it reperesents. It essentially acts as an interface to the actual web page. Now lets take a look at what a template file might look like. Remember, the added felxibility here is that the template file can do anything it wants with the data that has been stored in the TO. It has full control over how the information is presented. For illustrative purposes, I will make my example as simple as possible:&amp;lt;form method=&quot;&amp;lt;?php $this-&amp;gt;printMethod() ?&amp;gt;&quot; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action=&quot;&amp;lt;?php $this-&amp;gt;printAction() ?&amp;gt;&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name=&quot;&amp;lt;?php $this-&amp;gt;printName() ?&amp;gt;&quot;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- FORM CONTENT WOULD GO HERE --&amp;gt;&amp;lt;/form&amp;gt;I'm sure you can imagine how easy it becomes to expand upon this simple design to build a very flexiple and complex web application in very little time. Using this approach, a developer could build a site without any concrete design in place, using a simple layout that could easily be replaced further down the road without rewriting or refactoring any code. This also allows designers to build an interface without having to understand the backend structure of the application. Pretty handy if you ask me!</description>
			<pubDate>Tue, 29 Jan 2008 15:15:00 PST</pubDate>
		</item>
			
		<item>
			<title>PHP 5.3 - A Heavy Hitter in Training</title>
			<link>http://www.sitecrafting.com/blog/php-53-heavy-hitter-in/</link>
			<description>The evolution of PHP into an object-oriented programming language has been a very exciting process to watch. I'll admit its advancement seems to move at a glacial pace at times, but looking back we certainly have come a long way. With the release of 5.0 we saw PHP leave its childhood and enter its awkward adolescent stage. At this point there is evidence of a mature and complex object-oriented language while stilll exhibiting many of its younger habits.So what's in store for us next? Find out after the jump . . .This release may be the most significant update PHP has seen since PHP 5. This is because many of the features planned for the first release of PHP 6 are being backported to 5.3. Anyone that has been folowing the  development of PHP is likely aware that 6.0 will represent its entrance  into what I like to call its adulthood. This milestone will mark the  end of support for deprecated non compliant code, and will fully  embrace an OO coding style. It's not going to be the  end-all be-all version of PHP, but it will no longer attempt to cling  to its procedural roots.Let's take a look at some of the goodies in store for us in PHP 5.3:I. Native MySQL SupportAs of right now PHP has made use of the external library libmysql to access MySQL databases, which is fine - it works and it works well, so no complaints here. However, the relationship that has developed between PHP and MySQL is quite widespread, and I must admit it seems odd that MySQL has never truly been natively supported. All that will change in 5.3, when PHP will natively support MySQL resulting in a significant performance boost.II. Variable Static CallsYou are probably already familiar with variable variables and variable function calls. Variable static calls are the next logical addition to this feature set. This concept is best illustrated with an example, so consider the following:$className&amp;nbsp;=&amp;nbsp;'StringUtils';  $functionName&amp;nbsp;=&amp;nbsp;'FormatPhoneNumber';    $phoneNumber&amp;nbsp;=&amp;nbsp;'2535552552';  $newPhoneNumber&amp;nbsp;=&amp;nbsp;$className::$functionName($phoneNumber);    echo&amp;nbsp;$newPhoneNumber;  If we assume that the function StringUtils::FormatPhoneNumber() formats the phone number into a friendly layout, we could expect the above script to output &quot;(253) 555-2552&quot; or something similar. This adds a tremendous degree of flexibility to your code, as I'm sure you can already imagine.III. Error ReportingError reporting has been expanded and has split E_STRICT into two separate reporting levels. E_STRICT now only reports on bad coding style and leaves deprecated code (code that will not be supported much longer) to the E_DEPRECATED level.Additionally, E_ALL will actually include E_STRICT errors as well (which is what most of us expected to happen when it was first introduced).IIV. NamespacesI saved the best for last. Namespace support is hands-down the feature I am most excited about. This is some thing many developers with experience in other languages have been clamoring for since PHP first started supporting classes. Namespaces allow you to group related classes together and help to avoid naming conflicts in more complex applications.Currently the only way to accomplish this is to simulate namespace funcionality by using very long class names. Consider the Zend Framework as an example, in which you end up with class names like &quot;Zend_Auth_Adapter_Http_Resolver_File&quot; or &quot;Zend_Controller_Router_Route_Module&quot; - just mildly inconvenient, isn't it?As of PHP 5.3 one could place these classes in namespaces, making them much more manageable:namespace&amp;nbsp;Zend::Auth::Adapter::Http::Resolver    class&amp;nbsp;File&amp;nbsp;{  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;__construct()&amp;nbsp;{  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Do&amp;nbsp;something&amp;nbsp;here...  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;function&amp;nbsp;setFile($path)&amp;nbsp;{  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Do&amp;nbsp;something&amp;nbsp;else&amp;nbsp;here...  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}  }  We could then instantiate the class like this:use&amp;nbsp;Zend::Auth::Adapter::Http::Resolver&amp;nbsp;as&amp;nbsp;HttpResolver;  &amp;nbsp;  $file&amp;nbsp;=&amp;nbsp;new&amp;nbsp;HttpResolver::File();  $file-&amp;gt;setFile('/home/testuser/file.tmp');In the above case, we can now instantiate all classes within this namespace using a similar declaration. As you can see, the addition of namespaces allows you to declare the namespace in which a script will execute, greatly shortening the required class declaration. This also introduces the possiblity of namespace aliases, allowing you to reference a namespace with a shorter 'nickname.'We could have called the class directly from the namespace (like &quot;new Zend::Auth::Adapter::Http::Resolver::File()&quot;) and left out the use construct, but then we would be back to a long class declaration. Even then, this time around PHP will actually be aware of the namespace (and potentially future IDEs, leading to more powerful code-hinting).ConclusionThat was just a sample of what you can expect when 5.3 is released. With so many additions that were originally planned for PHP 6, this release is going to feel like an early birthday present. This also means we can see these features added to our production environments more quickly considering an upgrade to 5.3 will go much more quickly than a migration to an entirely new verison.
</description>
			<pubDate>Wed, 12 Mar 2008 16:34:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Make PHP Growl</title>
			<link>http://www.sitecrafting.com/blog/php-growl/</link>
			<description> I stumbled upon a fantastic PHP class today and felt compelled to comment on it. Originally written by Tyler Hall, this class allows you to send notifications to any system running Growl from a PHP script. For those of you that don't know, Growl is an application written for Mac OS X that is intended to act as a universal notification tool (much like the taskbar notification bubbles we've all come to know and love in Windows XP/Vista).  The class itself is incredibly simple and straightforward, and allows you to send notifications using only 5 lines of code. Consider this simple example://&amp;nbsp;Setup$growl&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Growl();$growl-&amp;gt;setAddress('127.0.0.1');$growl-&amp;gt;addNotification(&quot;Test&quot;);$growl-&amp;gt;register();//&amp;nbsp;Send&amp;nbsp;Notification$growl-&amp;gt;notify(&quot;Test&quot;,&amp;nbsp;&quot;Test&amp;nbsp;Alert&quot;,&amp;nbsp;&quot;The&amp;nbsp;body&amp;nbsp;of&amp;nbsp;the&amp;nbsp;test&amp;nbsp;alert!&quot;);Pretty nifty isn't it? One could very easily integrate this into a logger to notify you immediately of any critical errors with your scripts, or even tell you every time a given page is viewed. So if you want to check out my modified version (a bit more standards-compliant with PHP 5) you can see it here, or view the original author's site to see the original.Download: Growl PHP Classvar dzone_url = 'http://www.sitecrafting.com/blog/php-growl/';var dzone_title = '';var dzone_blurb = '';var dzone_style = '1';&amp;nbsp;</description>
			<pubDate>Wed, 26 Mar 2008 12:41:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Got API?</title>
			<link>http://www.sitecrafting.com/blog/got-api/</link>
			<description>gotAPI.com is one of the most useful online resources I've come across, primarily because it places resources spread all over the internet into one simple site. I've been using this for quite some time, and have for the most part I have taken its usefulness for granted. Then it occurred to me that I might not be the only one that could find this tool useful (I know, it was a big 'DUH!' moment). So now I will share this gem with others...gotAPI acts as a portal to almost any API/language reference available on the internet. Wondering what that PHP string function is that splits a string into an array? Pour yourself a nice tall glass of gotAPI and find it in seconds. Or if JavaScript is more your thing, browse the DOM to find the function or property you need. The advantage is that it can all be accessed from here, no need to remember countless URLs or stumble through a poorly designed site to find the documentation page. Simply hit up the site and you're set.Customization is another advantage, with the tabbed interface allowing you to pull up multiple reference pages (all searchable with an expandable tree view to your left). Load up all the API's related to your current project finding an obscure function is now seconds away. Fantastic!The fact that I am still excited about this site after months of using it should tell you just how nifty it is. So stop wasting time reading blogs and go check it out!Link: gotAPI.com</description>
			<pubDate>Mon, 31 Mar 2008 11:40:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Google's Search Appliance</title>
			<link>http://www.sitecrafting.com/blog/googles-search-appliance/</link>
			<description>I recently had the opportunity to work with one of Google's latest search applances, the Mini. Having no previous experience with any of Google's search hardware, this seems an excellent opportunity to offer a newcomer's first impressions.I. Setup &amp;amp; ConfigurationSetting things up turned out to be more painless than I had expected. Upon opening the box, I found the contents to be only what was necessary. It consisted of 5 things: the Mini itself, a yellow Cat5 cable, an orange Cat5 crossover cable, a power cable, and the manual/quick-start guide (and a snazzy tshirt!). That's it, nothing else! No product catalogs, no coupons, no massive collection of multilingual warranty booklets, and most importantly no unnecessary clutter.II. User InterfaceThe UI of the administration panel is clean and to the point - very much what one would expect from Google, and consistent with Google's overall style across the rest of their product line. All the administrative functions are organized categorically and only one menu-level deep, making virtually any administrative action no more than 2 clicks away.III. API/Programmatic UsabilityAccessing the mini's search capabilities programmatically works very much as one might expect - executing search queries via GET or POST and returning the results in an easily parsable XML format. Additional options are also available, though I found the XML format to be the most flexible for the circumstances. It is so easy to use I actually had to debate whether or not writing a PHP wrapper class was actually necessary. In the end I decided it would make sense, though even then writing the class itself was a breeze.IV. ThoughtsOverall I am very impressed with this little beast. It clearly isn't over-engineered and for its intended scale of use it is not underpowered. I would have liked to see more flexibility in managing the crawling process and in how results were returned, but these things would have been icing on a cake that is already fantastic on its own.For anyone considering the acquisition of one of these, I highly recommend it. For small to medium applications you can't beat the price, especially when compared to the mini's bigger brother. And its usability both through the UI and programatically are very intuitive and easy to dive into. Well done Google, well done!</description>
			<pubDate>Wed, 04 Jun 2008 10:50:00 PDT</pubDate>
		</item>
			
		<item>
			<title>'M' is for Model, 'V' is for View . . .</title>
			<link>http://www.sitecrafting.com/blog/model-view-1/</link>
			<description>During my morning blog-scan I came across four videos that really set my day off on the right foot. And that song! Oh that song! As much as I can't stand it, I'll be humming it all afternoon today. If you're familiar with the MVC model, then these videos were made for you.So without further adue, enjoy:PSA #1: Controller Obesity&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; PSA #2: The Importance of Tests&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; PSA #3: Keeping Views Stupid&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; PSA #4: Staying RESTful&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Link: Original Site</description>
			<pubDate>Thu, 05 Jun 2008 09:43:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Write .NET Applications in PHP</title>
			<link>http://www.sitecrafting.com/blog/write-applications-in-php/</link>
			<description>That's right, you heard me! It's all thanks to a fantastic project called Phalanger, which adds a super-fast execution environment for a very large portion of the PHP scripting language. Certainly this was only a matter of time, combining one of the most popular open-source languages of the web with one of the most powerful enterprise-grade frameworks.One of the coolest things about Phalanger is the way it allows you to decide how to implement PHP syntax. There is almost no barrier to entry, as it is designed to implement PHP the same way it is handled natively, but also allows you to use PHP syntax in an ASP.NET application just as though PHP was simply another option among VB.NET and C#.I'll admit I have yet to take a crack at it, but having worked with both .NET and LAMP technologies I can't help but imagine the possiblities. SiteCrafting in particular could benefit from this tremendously, allowing our PHP devs to easily port PHP-based solutions into some of our existing .NET projects. It also means essentially all of our developers could make contributions to a .NET project if the need arose.I should warn Phalanger is still in it's beta phase, and has not yet fully implemented the entire PHP language and common libraries. Though it may not be enterprise-ready yet, I see good things ahead.Link: PhalangerLink: Tutorials</description>
			<pubDate>Mon, 16 Jun 2008 08:56:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Coding Fonts</title>
			<link>http://www.sitecrafting.com/blog/coding-fonts/</link>
			<description>Having recently discovered the plethora of coding fonts available online, it occurred to me that quite a bit of thought has been put into something I have always seen as rather trivial. The more I read about it, the more I have come to realize that using a font specifically designed for software development can be extremely beneficial.My first thought was, &quot;what on earth could require so much thought?&quot; As I continued my browsing, the all the pieces started to fall into place. Some of the things coding fonts specifically try to emphasize/improve upon include:Appropriately styled for typically used sizes (~8pt - 10pt)Smaller line-height (means seeing more lines of code at once)More readable symbols (esp. brackets, parenthesis, etc.)Designed to be monospaced from the ground up (full-width/centered characters, etc.)Reasonable tab sizing.I'm sure there are plenty of others, but these are some of the things I found valuable right off the bat.If you're interested in giving some programming fonts a whirl, I highly recommend you start your exploration with Proggy Programming Fonts. I particularly like (and currently use) the one called CodingFontTobi which really makes reading through large blocks of code a breeze. I discovered it wasn't fully compatible with OS X (tabs would appear as funky symbols), so if you've got a Mac I recommend downloading my modified version.</description>
			<pubDate>Thu, 10 Jul 2008 15:36:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Onload Collisions and How to Fix them</title>
			<link>http://www.sitecrafting.com/blog/onload-collisions-to-fix/</link>
			<description>There is no other variable more fought over then the coveted window.onload. Its job is to run a function after a page has been loaded. The problem is that there is only one variable, and therefore only one function can run. Once you have set this you would think you are in the clear. That is until another script comes in and overwrites onload.But all can be made well in JavaScript land once one of four choices is made. I give four ways to get around this problem, and suggest a way for modern browsers to be rid of this problem once and for all.JavaScript, love it or hate it, it's here to stay. In the last generation of web design it was abused to accomplish silly things like turning your mouse into a analog clock or, my favorite, change the color of the background depending on where your mouse was on the page (I almost had a seizure when I first saw that one).Since then we have learned to separate our pages into three parts: Information (HTML), Presentation (CSS), and Function (JS). The latter is where I have found my niche in recent years. The web is now flooded with JavaScripts that do everything. Most of which require the page to be loaded before doing any work. This isn't an issue because there is a variable aptly named window.onload. To make a function run after the page has loaded, you just assign it to this variable.And there in lies the problem: there is only one variable. Only the last script that assigns to this variable will run successfully. In the past this generally wasn't an issue because you were the author and rarely had mismanaged conflicts. But times have changed.With only one onload variable what are we to do. Well, I have discovered 4 options: check and wrap it, make onload an array, wrap onload with a function, make onload a function that sends an event. Each of these have their pros and cons. I'll discuss them briefly below.Check and WrapThis method is a quick check to see if anything is already set to run onload. If there is, then you create a function that first runs what ever was in the onload, then does what ever you need it to. It should look something like this:if(window.onload != undefined) {&amp;nbsp;&amp;nbsp; &amp;nbsp;var tempFunct = window.onload;&amp;nbsp;&amp;nbsp; &amp;nbsp;window.onload = function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;tempFunct();&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;yourFunction();&amp;nbsp;&amp;nbsp; &amp;nbsp;}} else window.onload = yourFunction;The advantage of this is that there is that you don't have to rewrite any old code, nor do you have to load any code before had. But the downsides are numerous. First, if you find yourself with a dozen onloads, then you will be in a very deep chain of functions, and that will slow things down. Also, if your tempFunct variable is overwritten then a link in the chain is broken, and nothing after it will run. Lastly, if someone changes the onload variable after you, your whole chain is gone.Onload ArrayAs a way of getting around these problem, I believe that modern browsers should allow onload to be an array of functions. The browser could then iterate over the array, running every function it encounters. This would allow for many more functions to get access to this crucial resource. I came up with a quick way to accomplish this now in preparation for browser integration.window.onload = function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;for(var key in onload.functs)&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;onload.functs[key]();}onload.functs = [];onload.push = function(funct) {&amp;nbsp;&amp;nbsp; &amp;nbsp;onload.functs.push(funct);}This would give the onload variable the ability to have the push method to add functions. To add a function, you would use:onload.push(yourFunction);// ORonload.push(function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;yourFunction();});Simple, isn't it? This fixes most of the cons in the check and wrap method, but still have some problems. If another script still uses the old onload method then, again, the whole chain is broken.Onload WrapperThe major problem with the Onload Array is legacy code messing up your functions. You could update your code, but that is a lot of work. So there is the thrid method, the onload wrapper. This is very similar to the onload array in the sense that it stores functions in an array and pulls them out using onload. But the difference is that you call a function to add it to the onload. This function can then detect if old code has overwritten the onload variable. The code is as follows:var onDomReady = function(funct) {&amp;nbsp;&amp;nbsp; &amp;nbsp;if(window.onload != onDomReady.run) onDomReady.functs.push(window.onload);&amp;nbsp;&amp;nbsp; &amp;nbsp;onDomReady.functs.push(funct);&amp;nbsp;&amp;nbsp; &amp;nbsp;window.onload = onDomReady.run;}onDomReady.run = function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;for(var key in onDomReady.functs)&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(onDomReady.functs[key]) onDomReady.functs[key]();}onDomReady.functs = [];To use this method you:function onLoadKiller() {&amp;nbsp;&amp;nbsp; &amp;nbsp;alert('onload killer');}onload = function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;alert('onload');}onDomReady(function() {&amp;nbsp;&amp;nbsp; &amp;nbsp;alert('onDomReady');});onload = onLoadKiller;onDomReady();The code above will display three alert boxes. The first one is caused because the onload variable is set to a function that created the 'onload' alert. The onDomReady function then adds both the onload (the 'onload' alert) and the 'onDomReady' alert. Then the onload gets overwritten by onLoadKiller. We take that pecky guy out by running the onDomReady() function again, which fixes the chain. (And all is well in JS land)This gets around all the set backs of the first two methods, except that, again, setting that pesky onload variable will blow out your chain. Luckily, this code has a way to get around that by simply rerunning the onDomReady() function without any parameters. This will allow you to insert this line of code where ever you find a colision and it will repair the chain. There is always a downside, namely that if two places set onload consecutively without a onDomReady() in-between, the first will be lost.Event Driven OnloadThe final method uses something completely different for the onload. Rather then setting this variable, you attach a function to an event (the 'load' event). This gives you the ability to add multiple functions to onload without collisions. Events are exactly how Prototype and other frameworks deal with onload. The downside is again that the change will require a rewrite of old code, and there for isn't much better then the first two.Browser ImprovementsAs I hinted at earlier, I believe we need a way to natively allow more functions to run onload. The easiest way I see to accomplish this is to allow the onload variable to be an array, and run every function associated with it. While this wouldn't fix some of the problems in old scripts, it would be a way to move foreward and allow many more scripts to be run concurently within the browser.ConclusionSo what's a scripter to do? There is no good answer for this. Each situation is different. Below I break it down into which category each method is useful for.If you are starting your code base from scratch, I would suggest the Onload Array. This would give fall-foreward compatibility and would start to pressure browser makers to include this kind of onload scheme.If you already have a code base, but know it fairly well, then the Onload Wrapper is a good option. It is the most forgiving when breaking the chain, and will repair itself as much as possible.If you have a large code base, and really don't know how things interact, then the check and wrap is a good choice. It will protect your little chunk of code while preserving anyone else's (assuming you are tagging on to the end of the chain).Lastly, if you are writing a script from scratch, and it needs to interact with an unknown environment, then your best bet is to go event driven. It's like taking a higher path where you don't monkey around with those lesser scripts still using the onload variable.</description>
			<pubDate>Tue, 22 Jul 2008 16:41:00 PDT</pubDate>
		</item>
			
	</channel>
</rss>
		
