<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
	<channel>
		<title>Blog</title>
		<link>http://www.sitecrafting.com/blog/php/</link>
		<description></description>
		<language>en-us</language>
		<pubDate>Thu, 17 May 2012 00:00:55 PDT</pubDate>
		<lastBuildDate>Thu, 17 May 2012 00:00:55 PDT</lastBuildDate>
		<generator>SiteCrafting.com GearBox 1.1 (beta)</generator>
		
		<item>
			<title>The Three 'M'-igos</title>
			<link>http://www.sitecrafting.com/blog/butter-fingers-break-apps/</link>
			<description>Happens all the time, right? One minute you're cranking out line after line of quality code then the next it all comes to a screeching halt for no apparent reason. I immediately go into troubleshooting mode. A quick and simple redirect using a header(&quot;Location: ...&quot;) function should pose no danger of messing up my app -- but today it did.It kept throwing me to a &quot;Page Not Found&quot; message and, since it was  technically only moving me to the exact same script, I couldn't see why. For such a simple line of code to push things so far out of whack seemed preposterous. Well, it's always good to check your digital ego at the door and go through it all rationally.Here's how I thought this out:the redirect tossed me to the same script yet gave me a &quot;Page Not Found&quot;any GET variables I passed were fine and weren't even being relied upon heavilythe server was running fine since the previous and other pages were displaying just fineI was redirecting to the correct URL -- wait a minute!Turns out I wasn't at all. I was routing the script from comments.php to commments.php and that just ain't right. I suppose when you have so many of the same characters in a row the brain tends to skip over them once in a while. Whatever the reason, it took me a few minutes to catch and I just had to chalk it up to another hard lesson learned since I neglected to believe in Occam's Razor. Next time, I'll check to see if it's spelled correctly first.</description>
			<pubDate>Wed, 11 Oct 2006 19:29:00 PDT</pubDate>
		</item>
			
		<item>
			<title>A Piece of Query Cake</title>
			<link>http://www.sitecrafting.com/blog/piece-query-cake/</link>
			<description>If you've ever created SQL queries with PHP, you probably know what a pain it can be to create insert and update statements. I really, really (really) don't like it. As I was working on my personal site, and exploring possible frameworks to use, I came across CodeIgniter. They have a great database interaction library, especially the function for creating the insert queries.Today, armed with only the descriptions of CodeIgniter's query helper functions, I spent 20 minutes trying to duplicate some the effect of the insert and update functions. I've never seen the code, or even used it, but I didn't have to see the code to write a similar function. Both functions take a table name and an associative array of column names and values. The update function also requires a WHERE statement, and it can't be blank. This is different from CodeIgniter, and that's so you don't accidentally reset all of the passwords in the mysql users table, or any table for that matter. And then, *poof*, the function gives you a nice sql statement.I'll never have to write another &quot;INSERT blah blah blah&quot; again. Yay!&amp;lt;?php/**&amp;nbsp;*&amp;nbsp;Generates&amp;nbsp;an&amp;nbsp;insert&amp;nbsp;sql&amp;nbsp;query&amp;nbsp;from&amp;nbsp;the&amp;nbsp;parameters&amp;nbsp;*&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$table&amp;nbsp;The&amp;nbsp;name&amp;nbsp;of&amp;nbsp;the&amp;nbsp;table&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;array&amp;nbsp;$array&amp;nbsp;An&amp;nbsp;associative&amp;nbsp;array&amp;nbsp;with&amp;nbsp;the&amp;nbsp;values&amp;nbsp;similar&amp;nbsp;to&amp;nbsp;column=&amp;gt;value&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;string&amp;nbsp;The&amp;nbsp;sql&amp;nbsp;query&amp;nbsp;*/function&amp;nbsp;getInsertSQL($table,&amp;nbsp;$array)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;'INSERT&amp;nbsp;INTO&amp;nbsp;'.$table;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$columns&amp;nbsp;=&amp;nbsp;'';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$values&amp;nbsp;=&amp;nbsp;'';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach($array&amp;nbsp;as&amp;nbsp;$key&amp;nbsp;=&amp;gt;&amp;nbsp;$value)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$columns&amp;nbsp;.=&amp;nbsp;$key.',&amp;nbsp;';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if($value&amp;nbsp;!=&amp;nbsp;&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;$values&amp;nbsp;.=&amp;nbsp;&quot;'&quot;.addslashes($value).&quot;',&amp;nbsp;&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;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;$values&amp;nbsp;.=&amp;nbsp;&quot;'NULL',&amp;nbsp;&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;$columns&amp;nbsp;=&amp;nbsp;substr($columns,&amp;nbsp;0,&amp;nbsp;-2);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$values&amp;nbsp;=&amp;nbsp;substr($values,&amp;nbsp;0,&amp;nbsp;-2);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;.=&amp;nbsp;&quot;($columns)&amp;nbsp;VALUES&amp;nbsp;($values)&quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$sql;}/**&amp;nbsp;*&amp;nbsp;Generates&amp;nbsp;an&amp;nbsp;update&amp;nbsp;sql&amp;nbsp;query&amp;nbsp;from&amp;nbsp;the&amp;nbsp;parameters&amp;nbsp;*&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$table&amp;nbsp;The&amp;nbsp;name&amp;nbsp;of&amp;nbsp;the&amp;nbsp;table&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;array&amp;nbsp;$array&amp;nbsp;An&amp;nbsp;associative&amp;nbsp;array&amp;nbsp;with&amp;nbsp;the&amp;nbsp;values&amp;nbsp;similar&amp;nbsp;to&amp;nbsp;column=&amp;gt;value&amp;nbsp;*&amp;nbsp;@param&amp;nbsp;string&amp;nbsp;$where&amp;nbsp;What&amp;nbsp;to&amp;nbsp;limit&amp;nbsp;the&amp;nbsp;update&amp;nbsp;to.&amp;nbsp;Cannot&amp;nbsp;be&amp;nbsp;blank.&amp;nbsp;*&amp;nbsp;@return&amp;nbsp;string&amp;nbsp;The&amp;nbsp;sql&amp;nbsp;query&amp;nbsp;*/function&amp;nbsp;getUpdateSQL($table,&amp;nbsp;$array,&amp;nbsp;$where)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(trim($where)&amp;nbsp;==&amp;nbsp;&quot;&quot;)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;=&amp;nbsp;'UPDATE&amp;nbsp;'.$table.'&amp;nbsp;SET&amp;nbsp;';&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach($array&amp;nbsp;as&amp;nbsp;$key&amp;nbsp;=&amp;gt;&amp;nbsp;$value)&amp;nbsp;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if($value&amp;nbsp;!=&amp;nbsp;&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;$sql&amp;nbsp;.=&amp;nbsp;$key.&quot;='&quot;.addslashes($value).&quot;',&amp;nbsp;&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;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;$key.&quot;='NULL',&amp;nbsp;&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;$sql&amp;nbsp;=&amp;nbsp;substr($sql,&amp;nbsp;0,&amp;nbsp;-2);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$sql&amp;nbsp;.=&amp;nbsp;&quot;&amp;nbsp;WHERE&amp;nbsp;$where&quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$sql;}?&amp;gt;</description>
			<pubDate>Fri, 13 Oct 2006 10:59:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Cross Table Content Search</title>
			<link>http://www.sitecrafting.com/blog/cross-table-content-search-1/</link>
			<description>One of the more interesting adventures working with data storage is trying to aggregate information meaningfully from multiple very different data structures. Imagine you've got a website filled with content (say, a few hundred pages). All the content is stored and output dynamically - who wants to create and maintain 500 static html pages, anyway? And of course, you need a bit of variety, so all this content is spread across five different page designs, each requiring its own template and data structure.Now you say you want to search your site? All the content? And you want the results all together in one big happy sorted-by-relevancy list? How on earth am I going to do that?Well... like this.BackgroundOur basic data structures are pretty well cemented for dynamic front-end content. Every page has an entry in a core table (we'll call it page). The page entry has all the data that is universal. ID number, meta information, title, as well as parent and order numbers (for navigation hierarchy. In addition, we have a template id and a content id.The template id points to an entry in page_templates. Here you find the template names and, more importantly, the content table names. Remember that each template needs its own table as content block layout varies. With content table name and content id handy, you can leap to the actual page content.The SearchSearching a single table's content is a relatively easy matter. Put a FULLTEXT index on the relevant fields and runSELECT idFROM tableWHERE MATCH(search_columns) AGAINST (search_string)Since you designed the table, you know what fields to search on, right? Heck, this would work even for multiple tables. Just loop through the searches, writing a custom set of search indices for each straight into your queries.This is all well and good when you're working on a search for a single website. But working for a fairly prolific development company, who conveniently use the same basic table layout for the vast majority of their content managed front-end sites, the smart move is to write a function that discovers these indices on its own. This can be achieved using SHOW INDEX FROM content_table. From there, parse the relevant indices like so:while($row = mysql_fetch_assoc($res)){if($row['Index_type'] == 'FULLTEXT'){$search_cols .= $row['Column_name'].', ';}}Stick $search_cols up there in your single-table search, and suddenly you've got a dynamic FULLTEXT search that you can use on any table.Aggregating the DataUnfortunately, on a seven template site you've still got seven different sets of search results. The FULLTEXT search will return each result set in weighted order, but the user doesn't care what's using what template. They want the whole list to be in weighted order. To handle this, I tossed in a bit of array processing. First, restructure the query a bit to actually return the weight value itself:&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT id, MATCH(search_columns) AGAINST('search_string') AS weight&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM content_table&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE MATCH(search_columns) AGAINST('search_string')I ran this for each content table, and appended all the results onto a single array. From there I just wrote a simple php usort comparison function to sort on the table weight (and obviously the queries were expanded a bit to draw some actual useful information, beyond just the page id).Of course, with anything that works, the big question is always &quot;How can I make it better?&quot; So... how can I make it better? Right now our production servers are running MySQL 4.0 (to paraphrase Peter Zaistev, as long as it works, why put a whole lot of data in danger for an upgrade that isn't necessary?). I've got some notions regarding putting more of the load on the database side, but those will take stored routines (5.0) and/or subqueries (4.1). But with where we're at now, does anyone else have a notion of how to improve this solution? Or perhaps a completely different solution to the same problem?</description>
			<pubDate>Fri, 27 Oct 2006 11:34:00 PDT</pubDate>
		</item>
			
		<item>
			<title>File Extensions</title>
			<link>http://www.sitecrafting.com/blog/file-extensions-1/</link>
			<description>I've been using a fairly complicated function to grab the extension of an uploaded file. I have run across many instances where I have wanted to split up the file name from the file extension, or just find the file type. Since MIME types are not reliable enough for grabbing a true extension, I have been using this aforementioned function.The following is a snippet of code that I had been using to retrieve the extension of a file:&amp;lt;?php$filename = 'image.jpg'; //name of file$nombres = split('.', strtolower($filename));$nombre_start = '';for($k=0; $k&amp;lt;count($nombres)-1; $k++){&amp;nbsp;&amp;nbsp;&amp;nbsp; $nombre_start .= $nombres[$k];&amp;nbsp;&amp;nbsp;&amp;nbsp; }$nombre_ext = $nombres[count($nombres)-1];?&amp;gt;However, there had to be an easier, cleaner way to get this information. So here is the code I came up with the following code for retrieving the extension of a file:&amp;lt;?php$filename = 'image.jpg'; //name of file$ext = substr(strrchr($filename, &quot;.&quot;), 1);?&amp;gt;In this case, printing $ext would give you &quot;jpg&quot;.Grabbing just the filename was a bit more involved, but still relied on the same principal:&amp;lt;?php$filename = 'image.jpg'; //name of file$name = substr($filename, 0, strpos($filename,substr(strrchr($filename, &quot;.&quot;), 0)));?&amp;gt;    In this case, printing $name would give you &quot;image&quot;.</description>
			<pubDate>Mon, 16 Oct 2006 12:57:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Printing without the Dialog</title>
			<link>http://www.sitecrafting.com/blog/printing-dialog/</link>
			<description>One day, one of our clients came to us with a very unusual request - they wanted to be able to print something directly from the browser, but without displaying the usual print dialog box. I don't have much time in the webdev business, but I've never heard of this kind of request, and neither had anyone else in the office.Initially, we didn't think that it was possible. The browser File &amp;gt; Print command uses a dialog box. So does the javascript print() function. The only reason that we knew this was possible was that the client's current system was already doing it. With a little research, we figured out how to print directly from the browser without displaying a dialog box.Tools you'll need:1 local Unix or Linux serverA pinch of Javascript1 PHP exec() callPHP to format your dataFirst: your server MUST be a local server, on the same network as the printer. This is because we'll be using the lp command to shoot off the print job.Second, to get this to work from the browser, you need a little javascript to call a file using XMLHttpRequest that will call the lp command and execute the print job.The actual command to start off the print job looks something like this: lpr -p printer file.txtThe final ingredient of this system is to use PHP to format the data you need to print, and then save it to a file. The lpr command then works on that file.In the end, we were able to get this whole thing working, but only because Dustin over at out co-location facility knew what needed to be done. Part of the command line printing involves manually creating a print spool - a task not for the faint of heart. The spool is defined in /etc/printcap, and looks something like this:printer:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :ml=0:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :mx=0:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :sd=/var/spool/lpd/printer:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :af=/var/spool/lpd/printer/printer.acct:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :sh:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :rm=XXX.XXX.XXX.XXX:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :rp=text:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :if=/etc/magicfilter/ibmpro-filter:\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :lpd_bounce=true:Replace the XXX string with your printer's IP address. Then, when you click on a print button, the javascript fires off the XMLHttpRequest, which calls the PHP script to create the print file, and executes the command to print that file. Or, you can call the script with a PHP function on a page load.Shout outs to Dustin and Andrzej, for making the printing work, and for getting the scripts to call the print action.</description>
			<pubDate>Mon, 09 Apr 2007 16:36:00 PDT</pubDate>
		</item>
			
		<item>
			<title>The Joys of Object Oriented PHP</title>
			<link>http://www.sitecrafting.com/blog/joys-object-oriented-php/</link>
			<description>It's pretty common for PHP developers to make complex and difficult to maintain scripts, and I am no exception. I write my code in two distinctly different ways: scripts that do a whole bunch of things depending on input, and classes that do a bunch of things depending on how they are called, but from lots of different scripts. But which is better? It's a nice ego boost for any prrogrammer to know they created a script/function/class that is really useful, and well designed, but at some point the code stops being well designed, and becomes gross. I think that point is when you have one script that displays an entire (SQL) table of data, views a particular row, edits that row, can delete that row, or can add new row to the table.If my Software Engineering professor sees me doing that, I imagine that he'll reevalute my grade in his class.The first version of my coding style (a script that does everything), generally looks like this (psuedo code for the sake of brevity):&amp;nbsp;check permissionsif edit request sent&amp;nbsp;&amp;nbsp;&amp;nbsp; create edit sql&amp;nbsp;&amp;nbsp;&amp;nbsp; query databaseif delete request sent&amp;nbsp;&amp;nbsp;&amp;nbsp; create delete sql&amp;nbsp;&amp;nbsp;&amp;nbsp; query databaseif add request sent&amp;nbsp;&amp;nbsp;&amp;nbsp; create add sql&amp;nbsp;&amp;nbsp;&amp;nbsp; query databaseinclude header html fileif adding a new row&amp;nbsp;&amp;nbsp;&amp;nbsp; display blank html formelseif editing a row&amp;nbsp;&amp;nbsp;&amp;nbsp; display html form with values filled inelseif viewing a row&amp;nbsp;&amp;nbsp;&amp;nbsp; display row previewelse&amp;nbsp;&amp;nbsp;&amp;nbsp; display all rowsinclude footer fileSome of you out there might be copying that down to use in your own code, and I don't mind at all. That kind of structure is easy enough to work with when you only have four or five columns for data, but as you get more and more complicated data structures, and incorporate more and more tables into this style, using files like this can get extremely difficult. There is a better alternative, and that is using Object Oriented PHP. You create a control class for each table of data, and call its seprate methods to perform the tasks you want to accomplish. CodeIgniter gets this design spot on, as each class and function is also translated into a url. For example, if you have a Library class and you want to call the preview method, you would simply point your browser to www.mysite.com/library/preview. My designs aren't quite as good as CodeIgniter's, but they are good (the reason that CodeIgniter is able to have such good url's is due to some pretty complex File Not Found processing). Here's an overview of my classes:class something&amp;nbsp;&amp;nbsp;&amp;nbsp; variables according to the columns in the table&amp;nbsp;&amp;nbsp;&amp;nbsp; function load (id)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; queries database for the row that has the specified id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assigns the values to the classes' variables&amp;nbsp;&amp;nbsp;&amp;nbsp; function save ()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; takes the variables from $this and creates an sql statementand so on as I need. For each different script, I name it something_save.php or something_view.php, where the first word is the class, and the second is the function name. Somethings I leave up to the php file, like xhtml templates and style, but all I have to put in those files is two lines of PHP code: load() and the function call. This makes the control logic of components of your application really easy to use, and also is better from a Software Engineering view.I hope you can implement this methodology into your own coding, and I welcome comments on how to improve this idea.Disclaimer: I left out a lot of details on the psuedo code, for several reasons, but mainly because I wanted to talk about a concept, rather than a tutorial.</description>
			<pubDate>Wed, 08 Nov 2006 13:36: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>The &lt;select&gt; Tag and innerHTML</title>
			<link>http://www.sitecrafting.com/blog/ltselectgt-tag-innerhtml/</link>
			<description>While I was working on a recent project, I ran into a weird bug with IE 6. I was using some AJAX to dynamically fill a &amp;lt;select&amp;gt; tag with options depending on what element was selected from the tag's parent. It worked fine, and quite seamlessly in Firefox, but broke for inexplicable reasons in IE.I was using a php script to get all the selectable options, and then passing that back to the javascript handler to be inserted into the document. The problem was that, apparently, you can't use the .innerHTML property to set content on a select tag.This makes no sense, for two reasons: 1) Microsoft created the innerHTML property, and it doesn't work in their software and 2) All you really need to do is find the node, and replace it's children with some abritrary string. It's not terribly complicated. Every other (modern) browser seems to handle it perfectly fine.After Mark had pointed out that fact, I just used the php script to return an entire select element with the options already populated, but that broke the event listener I had placed on the tag to change the select options for that select's children. But that was quick and easy to fix: just reload the event listener on the completion of the AJAX call.I've gotten to the point that most browser inconsistencies don't really faze me. I know what to expect and how to work around it, but this one really threw me for a loop. So, take note developers, &amp;lt;select&amp;gt; + innerHTML = broken. But you should really be using the DOM anyways.</description>
			<pubDate>Wed, 13 Dec 2006 16:12:00 PST</pubDate>
		</item>
			
		<item>
			<title>Emulating Form POST in PHP</title>
			<link>http://www.sitecrafting.com/blog/emulating-form-post-in-php-1/</link>
			<description>
Recently, I had a need to POST a form, using PHP script, to a remote url.&amp;nbsp; As I started to research a solution, I soon realized there were very few limited options.

Here's the situation, a customer has added a number of items to his shopping cart and ready to submit the final order. When the submit button is pressed, the PHP script processees the order locally, and then the next step is to POST the shopping cart to a remote url, which I have no control over. This system is very similar to integrating a website with PayPal.Here are my choicesJavascriptThe shopping cart is processed locally. Afterwards the php script creates an html page with a hidden POST form with the needed values. We add Javascript to submit the form when the page loads.CommentUnfortunately, this was not an option, since there's a strong possibility that some customers will have javascript disabled.cURL and Header(&quot;Location:&amp;nbsp; http://www.theremoveurl.com&quot;)In this example, cURL (or fsockopen) is used to post the variables to the remote. After the cURL operation is complete use Header(&quot;Location: url&quot;) to redirect to the website.It would also be possible to get the response, which should be a html and echo() or print() it to the customer's browser.CommentThis was not an option since the remote creates a session and redirects to an unknown URL after the form has been submitted. There's no way to transfer the session information (well maybe) to the customer's browser and then redirect the browser to the final url by using the header information from the cURL response.  Intermediate PageAfter the customer presses the submit button, the PHP script processes the order locally. Next, an intermediate page is used that says something like, &quot;Thank you, your order has been submitted. Please press the OK button to continue on to your next companies web site. If you don't, then your company will not know about the order you just placed and bad things might happen.&quot;CommentThis was the best solution to the problem at hand.</description>
			<pubDate>Fri, 19 Jan 2007 16:52: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>Query conservationist</title>
			<link>http://www.sitecrafting.com/blog/query-conservationist/</link>
			<description>  I always enjoy trying to do my work creating web applications using the fewest number of database queries possible. It's kind of a pride thing, I guess. That and I suppose it makes to improve an app's performance and reduce the load on a server. If you're into that kind of thing. ;)A technique I use subtitutes the temptation of using queries whose results call queries and instead uses only two.  Something that commonly comes up involves a needing to learn something specific about every item of a query result. While looping through the first set of results it's easy to just run a query each time to get what I need. Problem comes when your apps scale up from result sets in the double digits to those in the thousands or more. Running thousands of queries just to get what you want is a little selfish, don't you think?When I create dynamic reports for clients that show row upon row and  column upon column of totals pulled from the four corners of a vast  datascape the number of queries needed can skyrocket. One technique I'm rather fond of employing does everything needed in two queries. Let's play pretend here and say we're working with a grocer who wants to see a report of how many of different kinds of fruit have been sold everyday for the last month.The first query might look like this:SELECT name AS fruit_nameFROM produceWHERE type = 'fruit'...And might return results looking like this:FRUIT_NAMEapplebananaorangeraspberriesFor each of the items in that result set, you could run a query to get the total sold for each day of a month. For the shortest month of the year with 28 days, this would mean 112 queries! You can see how this could easily get out of hand.Instead, try a second query that gathers up the dates for every fruit sale during the month, en masse. You can then dump these results into an array who's indexes match the name for each type of fruit. For each fruit you can put another array with a slot for each day of the given month that stores the total number each was sold on a given day. It may end up looking like this:Array()&amp;nbsp;&amp;nbsp;&amp;nbsp; [apple] =&amp;gt; Array()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-03] =&amp;gt; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-07] =&amp;gt; 12  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-10] =&amp;gt; 9&amp;nbsp;&amp;nbsp;&amp;nbsp; [orange] =&amp;gt; Array()  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-01] =&amp;gt; 8  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-03] =&amp;gt; 19    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [2006-02-04] =&amp;gt; 13From here it's pretty easy to loop through the first set of data and match on the second set using those spiffy associative indexes.This is a pretty rudimentary example but it's important for me to be mindful of such techniques as I build bigger and bigger apps. Like I mentioned, when creating reports sometimes the data is being mined from many different areas of the database all with different calculations that would make a single query nearly impossible. By finding a common bit of data like an ID and leveraging some arrays you can keep the number of queries down.</description>
			<pubDate>Fri, 02 Feb 2007 10:53: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>Optimizing GROUP BY  with Multiple LEFT JOINS</title>
			<link>http://www.sitecrafting.com/blog/optimizing-group-by-multiple-left/</link>
			<description>At SiteCrafting, I enjoy working with a large number of different projects, each with their own requirements, technology, and problems to be solved, unfortunately, I sometimes forget about past solutions, until after I have finished writing a piece of code. Such is the case with a query that was eating up some serious processing time.The problem was with a GROUP BY query with LEFT JOINs to several other tables and summing up totals from those joined tables. This query was taking about 4 minutes 45 seconds to run, and worse yet, it was affecting searches which had nothing to do with that query, and probably also eating up precious memory and cpu resources.In order to optimze the table I used the EXPLAIN
statement to figure out where the bottle necks were and then
restructured the primary keys and indexing for the tables I was trying
to left join to. This reduced the time of the query to about 35
seconds, this was still too slow and was still eating up too many
resources. I decided to put the problem to the side and
continued working another project. That's when I remembered using
temporary tables to solve a similar problem for a past project. The
temporary tables solution reduced the query time to about .5 seconds.Below is an example of the temporary table solution that I implemented for MySQL 4.1 and PHP 4.0. PLEASE NOTE: The database user must have the CREATE TEMPORARY TABLE privelege to the database.Let's start with three sample tables that a hotel uses.CREATE TABLE `rooms` (&amp;nbsp; `room_id` int(11) NOT NULL auto_increment,&amp;nbsp; `floor_number` int(10) NOT NULL, &amp;nbsp; `room_number` varchar(10) default NULL,&amp;nbsp; `size` varchar(10) default NULL,&amp;nbsp; `beds` int(11) default NULL,&amp;nbsp; `towel_allotment` int(11) default NULL,&amp;nbsp; PRIMARY KEY&amp;nbsp; (`room_id`)) TYPE=MyISAMCREATE TABLE `room_services` (&amp;nbsp; `service_id` int(11) NOT NULL auto_increment,&amp;nbsp; `room_id` int(11) default NULL,&amp;nbsp; `date_serviced` datetime default NULL,&amp;nbsp; `serviced_by` varchar(50) default NULL,&amp;nbsp; `order_amount` float default NULL,&amp;nbsp; PRIMARY KEY&amp;nbsp; (`service_id`),&amp;nbsp; KEY `room_id` (`room_id`)) TYPE=MyISAMCREATE TABLE `room_cleanings` (&amp;nbsp; `cleaning_id` int(11) NOT NULL auto_increment,&amp;nbsp; `room_id` int(11) default NULL,&amp;nbsp; `date_cleaned` datetime default NULL,&amp;nbsp; `cleaned_by` varchar(50) default NULL,&amp;nbsp; PRIMARY KEY&amp;nbsp; (`cleaning_id`),&amp;nbsp; KEY `room_id` (`room_id`)) TYPE=MyISAMFor some bizarre reason, the management wants a single report that lists the&amp;nbsp; number of times a room received room service and cleaning, even for the new rooms that were added, which have not received any services or cleaning. We start with this query.SELECT rooms.room_id, rooms.floor_number, rooms.room_number,COUNT( DISTINCT room_services.service_id) AS vTotalServices, COUNT( DISTINCT room_cleanings.cleaning_id) AS vTotalCleaningsFROM rooms LEFT JOIN room_services ON room_services.room_id = rooms.room_idLEFT JOIN room_cleanings ON room_cleanings.room_id = rooms.room_idGROUP BY rooms.room_id ORDER BY rooms.floor_number, rooms.room_number This looks like a good query. All three tables use the room_id as an index, which is numeric, another plus that queries like. However, this query is too slow, but why should that be.In order to figure that out, we need to take a look at the total number of records that is being generated by this query. Let's say that there are 100 records for the rooms table, 40,000 for room_services, and 10,000 for room_cleanings. When using left joins, to get the total number of records, where there is a one-to-many relationship, we multiple all the records together.100 rooms * 40,000 services * 10,000 cleanings = 3,990,000 totalThe sample query has almost 4 million records to count up.This is where a single temporary table can be of help. The room_services table has the most records, a temporary table can be used to store the total number of services for that room. PLEASE NOTE: In PHP, a temporary table will exist as long as a connection remains open.Here's a step-by-step example in PHP and MySQLSTEP 1 - create the temporary table// $connection is a mysql_connection$sql = &amp;lt;&amp;lt;&amp;lt;EODCREATE TEMPORARY TABLE `tmp_service_totals` (&amp;nbsp; `room_id` int(11) NOT NULL default '0',&amp;nbsp; `total_services` int(11) default NULL,&amp;nbsp; PRIMARY KEY&amp;nbsp; (`room_id`)) TYPE=MyISAMEOD;$res = mysql_query($sql, $connection);STEP 2 - Populate the temporary table// the temporary table stores the total number of services for each room$sql = &amp;lt;&amp;lt;&amp;lt;EODINSERT INTO `tmp_service_totals` (room_id, total_services )SELECT room_services.room_id, COUNT(DISTINCT room_services.service_id )FROM room_services GROUP BY rooms_services.room_idEOD;$res = mysql_query($sql, $connection);STEP 3 - Update our original query using the temporary table// query to get the totals for each room$sql = &amp;lt;&amp;lt;&amp;lt;EODSELECT rooms.room_id, rooms.floor_number, rooms.room_number,tmp_service_totals.total_services AS vTotalServices, COUNT( DISTINCT room_cleanings.cleaning_id) AS vTotalCleaningsFROM rooms LEFT JOIN tmp_service_totals ON tmp_service_totals.room_id = rooms.room_idLEFT JOIN room_cleanings ON room_cleanings.room_id = rooms.room_idGROUP BY rooms.room_id ORDER BY rooms.floor_number, rooms.room_number EOD;$res = mysql_query($sql, $connection);STEP 4 - Store the records into an arraywhile( $record = mysql_fetch_assoc($res) ){&amp;nbsp;&amp;nbsp;&amp;nbsp; $records[] = $record;}    STEP 5 - Destroy the temporary table$sql = &amp;lt;&amp;lt;&amp;lt;EODDROP TABLE tmp_service_totalsEOD;SummaryLet's take another look at the query in step 3. Since the left join between rooms and  tmp_service_totals is one-to-one, we will not need to factor that in to determine the total number of records that was generated. 100 rooms * 10,000 cleaning = 100,000 total recordsSo, we went from having four million records TO one hundred thousand records.For my real world query, after optimizing tables structures and indexes the time was averaging 34 seconds. After implementing the temporary table, the final average time was about .5 seconds, including the creation of the temporary table and inserting data into that table.  </description>
			<pubDate>Tue, 20 Feb 2007 14:53:00 PST</pubDate>
		</item>
			
		<item>
			<title>PHP Strings - Gotcha!</title>
			<link>http://www.sitecrafting.com/blog/php-strings-gotcha/</link>
			<description>Yesterday I was working with a script that saves an uploaded image to a database. If you've ever seen a binary file as a string, there's a ton of gobbelty-gook that is unreadable to people. For some very odd and inexplicible reason, my script only saved the first four character's worth of data to the database, and that's not very helpful. I did some digging, and revealed a weird gotcha in the way PHP treats strings.  My first debug technique is to print the data I'm working with. The image data looked normal - that is to say it had lots of weird characters. Since I was using my nifty function to generate the sql for the INSERT, I printed that out as well. The data was fine going into the function, but everything after the 4th character was missing.I wasn't sure what was going on, so I rewrote the sql, and noticed a curious thing. There were a lot of instances of the '\' character followed by the '0' character. If you've ever worked with C/C++, you know the single character '\0' means 'end of string'. It occurred to me that some PHP functions treat string data very differently, even though PHP is built on C or C++.My guess is that the echo command works something like this (in C/C++/Java psuedo code):public void echo(char* str) {    int i = 0;    while(i &lt; str.length) {        stdout  $value) to break apart the data array in the insert function, that worked much differently, ie it worked like this:while(str[i] != '\0') {    ...do stuff...}Notice the difference? '\0' is actually an implied end of string, not the actual end of string. This is because in C and C++, you have to actually declare the length of your character array that holds strings because they don't have a string datatype. So that command stopped prematurely, basically meaning that foreach($array as $key =&gt; $value) is not binary safe because foreach copies the array and doesn't use the original. Using foreach($array as $key =&gt; &amp;$value) (note the &amp;) may work because it uses a reference to the original data.I was pretty surprised when I ran into this problem, but it's not too hard to work around, I only had to write one more INSERT statement.</description>
			<pubDate>Wed, 28 Feb 2007 13:25:00 PST</pubDate>
		</item>
			
		<item>
			<title>Character Set Troubleshooting</title>
			<link>http://www.sitecrafting.com/blog/character-set-troubleshooting/</link>
			<description>Over the past few weeks, Reena has been building a new website off and on for a local Jesuit parish.&amp;nbsp; Everything was going along smoothly until we hit a bump in the road when dealing with a particular page with some Vietnamese text.&amp;nbsp; After some small (but not obvious) changes in configuration and more research than I cared to do on the subject of character sets, it's all working properly.The initial problem was that the content being copied wasn't showing up in the editor as it was in the original document.&amp;nbsp; Whenever I run into a situation like this, I usually fall back to my high school methods of building websites and open up a text editor.&amp;nbsp; Simple, plain, no extra features to get in the way, just give me the code.&amp;nbsp; Copy and paste worked just fine for me, so I figured that there must be a problem with the file type that Reena was using.&amp;nbsp; A quick &quot;Save As&quot; with the text encoding set to &quot;Unicode UTF-8&quot; and everything looked great.Unfortunately that wasn't enough; loading the page via a browser resulted in more broken text.&amp;nbsp; I certainly don't speak or read Vietnamese, but I was pretty sure that » and ? characters in the middle of words weren't part of the language.&amp;nbsp; Back to the research desk.&amp;nbsp; After some digging around online, I came across a great article written by Dave Shea that covered some of the issues that can arise when dealing with HTML and foreign languages.Following his tips, I slightly changed the header of the page to the following:&amp;lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;vi&quot;&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&amp;gt;Once these changes were in place, everything was looking great.&amp;nbsp; The page loaded correctly on our local test environment, so I let Reena know and went on to something else.&amp;nbsp; A couple weeks later, Reena was uploading the page to the live site and noticed some of the same text problems again.&amp;nbsp; So I jumped to conclusions and figured that the encoding was off again.&amp;nbsp; It wasn't, so I did some more testing of the transfer to make sure that the file was making it to the server in the same format as it was on our local server.&amp;nbsp; Everything looked good, so now I move on to the configuration settings for Apache.Since we were dealing with a foreign language, the first place I checked in the httpd.conf file was the AddLanguage and AddCharSet directives.&amp;nbsp; There were some differences between our live server and test server, so I modified them to match, gracefully restarted, and gave it another test.&amp;nbsp; Still no luck.&amp;nbsp; By this point I'm starting to run out of places to check, so it's back to Google for some more research.Most of the resources I found that related to the problem we were experiencing referred to a previously-unknown-to-me directive called AddDefaultCharset.&amp;nbsp; Because of some cross site scripting issues, this directive can be used to force text/html documents on your server to be encoded using a specific character set.&amp;nbsp; If this directive is turned on, all text/html files will come out encoded as ISO-8859-1, whether you specify the character encoding in your file or not.# Default charset to iso-8859-1 (http://www.apache.org/info/css-security/).AddDefaultCharset onI set this to &quot;off&quot;, gracefully restarted, and the page looked as it should.&amp;nbsp; I really didn't want to leave this potential security hole open and I really didn't want to specify a default character set either.&amp;nbsp; Part of the description of the AddDefaultCharset directive caught my eye when I went back and reread it.&amp;nbsp; This directive would only be applied &quot;to any response that does not have any parameter on the content type in the HTTP headers.&quot;&amp;nbsp; So unless you're specifically sending a character set in a header, the character set defined by AddDefaultCharset takes over.In the end, I added a little PHP header at the top of the Vietnamese page and turned the AddDefaultCharset directive in Apace back on.&amp;nbsp; The headers are being sent properly, so Apache isn't applying the ISO-8859-1 character set.&amp;nbsp; Since character sets aren't being applied on other pages via PHP, Apache takes over and sets the character set automatically.header( 'Content-Type: text/html; charset=utf-8' );So, long story short, check your file encoding as well as the headers being sent by your server if you're running into issues.&amp;nbsp; While Dave Shea's article is a few years old, there's still some great info in it, give it a read.Want even more information?&amp;nbsp; Check out some of the links below to learn what should be more than enough.AddDefaultCharset is bad, bad, badDebian Bug report logs #211889Cross Site Scripting Info: Encoding ExamplesThe Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)</description>
			<pubDate>Tue, 20 Mar 2007 16:55:00 PDT</pubDate>
		</item>
			
		<item>
			<title>PHP cURL and SSL Connection Timeout</title>
			<link>http://www.sitecrafting.com/blog/php-curl-ssl-connection-timeout/</link>
			<description>I've been working on a web site that uses cURL for request/response transactions and I was encountering a number of problems with empty responses from the server. This caused some frustrations, since these empty responses caused entire sections of a web page to be empty, especially on searches. Well, I couldn't have that, since people using the website would be confused on why a search for an item only worked occasionally. Trust in the web application would drop dramatically.My first instinct was to blame the server for returning empty responses, but realized that I shouldn't jump to conclusions about other people's servers. So, I launched myself into debugging the request/response transaction.Let's take a look at some PHP code for performing a cURL transaction. The most important thing to remember is that I can't stop the processing if an error occurs. So, if there is an error, the function returns an empty string.// keep looping until we get a response$count = 0;// try to get a good response by looping 10 timeswhile( $response == &quot;&quot; ){&amp;nbsp;&amp;nbsp; &amp;nbsp;$count++;&amp;nbsp;&amp;nbsp; &amp;nbsp;$response = curl_request( &quot;https://php.net&quot;, &quot;search=curl&quot; );&amp;nbsp;&amp;nbsp; &amp;nbsp;// if we looped ten times and still no response, lets quit to avoid never ending loop&amp;nbsp;&amp;nbsp; &amp;nbsp;if( $count == 10 )&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;break;}&amp;nbsp;&amp;nbsp; &amp;nbsp;//end while loopfunction curl_request($server_url, $values){&amp;nbsp;&amp;nbsp; &amp;nbsp;// this array stores all the information for a cURL transaction&amp;nbsp;&amp;nbsp; &amp;nbsp;$arrCurlInfo = array();&amp;nbsp;&amp;nbsp; &amp;nbsp;$arrCurlOptions = array();&amp;nbsp;&amp;nbsp; &amp;nbsp;$arrCurlOptions[CURLOPT_HEADER] = 1;&amp;nbsp;&amp;nbsp; &amp;nbsp;$arrCurlOptions[] = &quot;&quot;;&amp;nbsp;&amp;nbsp; &amp;nbsp;// set to 1 to include header info from response&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;$arrCurlOptions[CURLOPT_HEADER] = 1;&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 the output from the cURL session rather than displaying in the browser.&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //If already set, don't overwrite&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $arrCurlOptions[CURLOPT_RETURNTRANSFER] = 1;&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 page redirects, curl will follow&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;setCurlOption(CURLOPT_FOLLOWLOCATION, 1, false); // &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 already set, don't overwrite&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $arrCurlOptions[ CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; / attempt the request/response&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;&amp;nbsp;&amp;nbsp; $fp = curl_init();&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; curl_setopt_array($fp, $arrCurlOptions);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $response = curl_exec($fp);&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; $arrCurlInfo = curl_getinfo($fp);&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; //end try&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // catch any errors that occur and return an empty response&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; catch( Exception $e)&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; $strResponse = &quot;&quot;;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $strErrorCode = $e-&amp;gt;getCode();&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $strErrorMessage = $e-&amp;gt;getMessage();&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; log_curl_error($arrCurlInfo, $strErrorCode, $strErrorMessage);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; //end catch&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; curl_close($fp);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $fp = null;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $response;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; //end functionThe log_curl_error() is a function that simply stores the cUrl information and the error code and message to a database table. Now, let's pretend that I run this script a large number of times. Once in a while, no response is returned. I take a look at the log table and notice that I get the same error message of &quot;SSL connection timeout&quot; and they are always in groups of ten.Hmm, that must mean that even though we're re-initializing the cURL each time we loop through, it must be using the same connection each time. So, once the first connection is bad, each call to curl_request() uses the same connection. After some research, I found out that the cURL connection is cached.I'm thinking that for some reason, the web site and the server have trouble connecting using &quot;HTTPS,&quot; but since the connection is cached, we keep getting an empty response, no matter how many times we loop. During the afore mentioned research, I also discovered a cURL option,CURLOPT_FRESH_CONNECT, for clearing the cache. Additional cURL options.Using this new insight, I added one more cURL option to the curl_request() function.$arrCurlOptions[CURLOPT_FRESH_CONNECT] = 1;By adding this option, the connection is cleared each time we run the loop. For example, the first time through the loop, the SSL connection between the web site and server is bad, and we get a &quot;SSL connection timeout&quot; error. The second time through, the connection is refreshed, this time the SSL connection between the web site and server is good. The function is now able to return a response from the server. </description>
			<pubDate>Mon, 02 Apr 2007 14:36:00 PDT</pubDate>
		</item>
			
		<item>
			<title>How To Run PHP Code In The Background</title>
			<link>http://www.sitecrafting.com/blog/to-run-php-code-in/</link>
			<description>If you have php code that would take longer than 5 minutes to run, what would you do? You could update the configuration file for apache, or whatever web server you're running, to increase the amount of time a script page is allowed to run&amp;nbsp; and then use php's ini_set(&quot;max_execution_time&quot;, seconds) to increase the amount of time php will allow a script to run.Or you could use a session variable to mark the last position of the script and then use meta-refresh to start the script at the last position.Or you could try an asynchronous call by using php's exec command.Asynchronous ExampleHere's an oversimplified example. Let's say that you've been charged with resizing all the images in the Products folder. You decide to write some fancy php script to iterate through all the sub-folders and resize each image. Everything works beautifully on your test server with 50 images and 10 sub-directories. You upload your script to the live server, with a couple thousand images, and attempt to run it. After about 5 minutes the page times out and only about 200 images were resized.Now what? One possible solution is to create two pages, one that does all the image resizing, image_resize.php, and another that calls that page, resize_exec.php using the exec command.resize_exec.php&amp;lt;%$command = &quot;/usr/bin/php4 -f /var/www/myweb/image_resize.php&quot;;exec( &quot;$command &amp;gt; /dev/null &amp;amp;&quot;, $arrOutput );%&amp;gt;$command is a linux/debian command for running a php page through a command line. Normally, exec() will wait for the script to finish running and will return any output to the array $arrOutput, like error messages. However, by adding &quot; &amp;gt; /dev/null &quot;, the exec() will not wait for the script to finish, allowing the php script to run in the background.Your image_resize.php script is now able to run completely to the end.What to watch forOn the page that does the actual work, be sure to use ini_set(&quot;max_execution_time&quot;, seconds) to increase the amount of time php will allow your page to run.Be sure to use absolute paths for the command line and the&amp;nbsp; working page.Make sure that permissions are set up correctly to allow the php command line to run.The command line and &quot; &amp;gt; /dev/nul/&quot; works with linux/debian. This may be different, depending on your system.This example will not work with windows, although it may be possible to do same thing using a similar method.Additional FeaturesWhat if you wanted to keep track of the image resize process. One idea is to have image_resize.php update a text file with the percent done as it's running. Then on the resize_exec.php page, have a little bit of ajax that reads that file every few seconds and displays it on the page.You could also have image_resize.php send out an e-mail informing you that it has finished.</description>
			<pubDate>Fri, 13 Apr 2007 14:19:00 PDT</pubDate>
		</item>
			
		<item>
			<title>PHP PEAR and include_path</title>
			<link>http://www.sitecrafting.com/blog/php-pear-includepath/</link>
			<description>        When attempting to use the SMTP library from PEAR for a project, I was having problems with including the file. I kept getting a file stream error for this code:    	require 'Net/SMTP.php';I figured the problem had to be related to the include_path setting in the configuration file.When PEAR is installed, the include path in the PHP ini file is updated with the path to PEAR. Also, there's another path to the php folder, which is used by PEAR. So, if it's missing, PEAR includes will not work.      	Here's an example of the master include path:path = .:/usr/share/php:/usr/share/pear    	However, in the configuration,  the ini_set( &quot;include_path&quot;, &quot;../include/&quot;); overrides that setting,  which prevents the require() function from working.&amp;nbsp; At first, I&amp;nbsp; figured I only needed to add the path for pear, so I tried setting the include_path this way.ini_set(&quot;include_path&quot;,&quot;/usr/share/pear:../include/&quot; );But that include failed also. That's when I figured out that PEAR also uses the &quot;/usr/share/php&quot; path and possibly the &quot;.&quot; path, which is the path for the&amp;nbsp; current directory. Being the lazy programmer that I am, I didn't want to have to worry about updating these paths for different environment and settings, so I used this code snippet instead.$strMasterInclude = get_include_path();ini_set( 'include_path', &quot;{$strMasterInclude}:../include/&quot;);Now, the paths required for PEAR will always be included, no matter the environment.NOTE:In this example, the file paths are separated by a colon &quot;:&quot;, but the paths could also be separated by a semi-colon &quot;;&quot;, depending on your setup.</description>
			<pubDate>Wed, 18 Apr 2007 13:08:00 PDT</pubDate>
		</item>
			
		<item>
			<title>PHP Code in The Background Part 2</title>
			<link>http://www.sitecrafting.com/blog/php-code-in-background-part/</link>
			<description>The blog entry How To Run PHP Code In The Background discussed how to run a php file through the command line using php's exec() command.&amp;nbsp; Recently, I needed to pass a querystring to the php file, but this is not possible through the command line. If you try to pass a querystring, the exec() command will fail.Fortunately, after some googling, I came across a forum post that mentioned how the global array $_SERVER[&quot;argv&quot;] can be used to get arguments being passed through php. I then followed the link on that page to Chapter 43. Using PHP from the command line on&amp;nbsp; the php.net website. Under the user contributed notes, I found a nice little function for getting the arguments and placing them into an array, similar to $_GET, $_POST, and $_REQUEST.Let's take the example from the original How To Run PHP Code In The Background blog entry.resize_exec.php&amp;lt;%$command = &quot;/usr/bin/php4 -f /var/www/myweb/image_resize.php&quot;;exec( &quot;$command &amp;gt; /dev/null &amp;amp;&quot;, $arrOutput );%&amp;gt;Now, let's say I want to allow the user to enter a directory and image width when executing the command. Here's the updated code.&amp;lt;%$command = &quot;/usr/bin/php4 /var/www/myweb/image_resize.php --dir=/var/www/myeb/images --width=250&quot;;exec( &quot;$command &amp;gt; /dev/null &amp;amp;&quot;, $arrOutput );%&amp;gt;Notice that the -f option has been removed, since it appears that that option removes the first argument after the file name. Use the double dash to identify an argument with a key/value pair.Now, let's take a look at the code for image_resize.phpimage_resize.php&amp;lt;%$_ARG = arguments($_SERVER['argv']);$dir = $_ARG[&quot;dir&quot;];$width = $_ARG[&quot;width&quot;];function arguments($argv) {&amp;nbsp;&amp;nbsp;&amp;nbsp; $_ARG = array();&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($argv as $arg) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ereg('--([^=]+)=(.*)',$arg,$reg)) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_ARG[$reg[1]] = $reg[2];&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } elseif(ereg('-([a-zA-Z0-9])',$arg,$reg)) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $_ARG[$reg[1]] = '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; return $_ARG;}print &quot;dir = $dir&amp;lt;br /&amp;gt;&quot;;print &quot;width = $width&amp;lt;br /&amp;gt;&quot;; %&amp;gt;image_resize.php outputdir = /var/www/myeb/imageswidth = 250Now you can setup any php script file to accept arguments through a command line. </description>
			<pubDate>Fri, 27 Jul 2007 14:56:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Getting the Client?s IP Address</title>
			<link>http://www.sitecrafting.com/blog/getting-clients-ip-address/</link>
			<description>There are a number of reasons why you may want to capture a  web user's IP address. You may want to only allow certain IP addresses to view  your website, to allow only one vote per IP address, track unique clicks on  links and buttons, a location of web users on Google Maps using MASHUP, and whatever else you can think of.Below are a couple of examples to get the client's IP address in PHP and ASP.net, along with a couple of things to watch for.PHP Examples You could use the following to get the client's IP address &amp;lt;? $client_ip = $_SERVER[&quot;REMOTE_ADDR&quot;];// MAC Xserve may also have this server variable$client_ip = $_SERVER[&quot;PC-Remote-Addr&quot;];  ?&amp;gt;  To confirm which one to use, try looking at all the server variables by using print_r( $_SERVER). Another one to look for is $_SERVER[&quot;HTTP_PC_REMOTE_ADDR). It depends on upon on the server, IIS has a different set of names, apache has it's own set, etc.  ASP.net Examples Here are a couple of different methods in VB.net&amp;lt;% dim strClientIp AS string = &quot;&quot;  strClientIp = Me.Request.UserHostAddress  ' or use sever variables, just like the PHP examplesstrClientIp = Me.Request.ServerVariables(&quot;LOCAL_ADDR&quot;) %&amp;gt; If you're trying to capture the client IP inside of a class, use HttpContext. &amp;lt;% Public Class Client  Public IPAddress AS string  Sub New()   Me.IPAddress = HttpContext.Current.Request.UserHostAddress   End Sub  End Class %&amp;gt; What to watch for:  If the client's computer is inside of a network, the IP address will usually be the IP address of the router/firewall that connects to the Internet. Which could be a problem if your allowing one anonymous vote per IP address. If there are 20 computers within a network, then they could only have a total of one vote.Other server variables to look out for:The server variable HTTP_X_FORWARDED_FOR can also be used to find the client's IP address. Sometimes, this variable will have the computer's IP address inside of the network, which may be a worthless LAN address. However, this header can be easily faked and can also be a comma-separated list of IP addresses.  Another thing to watch for is how the router/firewall sends Internet traffic to the web server that is trying to capture the client's IP address. It's possible that the router/firewall has been setup to replace the REMOTE_ADDR or LOCAL_ADDR header values with a hard coded IP address. Setting the DMZ configuration for a router or running some code on the firewall can do this. For an example, download the Web Interface 4.0 troubleshooting guide and refer to the code on page 43.The last item is one that caught me. For a client's intranet site, I was attempting to validate an intranet user by capturing their IP address and validating it to a list of valid IP addresses. However, when browsing from the internet, from several computers at different locations, the IP address kept coming up as a LAN address, such as 10.0.1.15. This was because of the way the client's IT department setup the DMZ configuration.</description>
			<pubDate>Thu, 09 Aug 2007 16:14:00 PDT</pubDate>
		</item>
			
	</channel>
</rss>
		
