<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
	<channel>
		<title>Blog</title>
		<link>http://www.sitecrafting.com/blog/coding-technique/</link>
		<description></description>
		<language>en-us</language>
		<pubDate>Wed, 16 May 2012 23:25:16 PDT</pubDate>
		<lastBuildDate>Wed, 16 May 2012 23:25:16 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>Into the Nested Table Abyss</title>
			<link>http://www.sitecrafting.com/blog/nested-table-abyss-1/</link>
			<description>While I was taking some time to evaluate a 3rd-party application for a customer I took a peak at their site's HTML. I was pretty shocked when I found some very strictly organized code that contained gobs of nested tables. At one count I found a structure that was 10 tables deep! I suppose since enjoying creating clean mark-up and mostly table-less designs for the last few years I've forgotten my roots.Warning: Don't click to enlarge the following unless you have a strong stomach.Table-heavy  layouts used to be big and I was certainly guilty of a few back 'round  the turn of the century. Nevertheless, it's pretty shocking for me to  see pages laid out like this today. They are even kind enough to  include plenty of inline styles so we know what's what color. Yikes!  I'm pretty sure I speak for everyone here in the office when I say,  &quot;Good riddance!&quot;Tables are good for propping food up to where it's easily eaten not for propping up modern web designs.</description>
			<pubDate>Fri, 13 Oct 2006 16:56:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Smart Keyword Searching</title>
			<link>http://www.sitecrafting.com/blog/smart-keyword-searching-1/</link>
			<description>Earlier this week the brand new Pierce County Library website officially launched. It was a pretty complex build that took a lot of effort between ourselves and the library's staff to make sure that everything worked right for the site's users. One of the more important features on any website with a large amount of content is a solid search function, and this site was no different. With over 300 pages (and still growing), a user could easily have some difficulty tracking down the information that they are looking for. So what can you do to make finding information easier?Well, an intuitive structure for the pages on the site is a good start. Well-written copy and Meta information can also make it easier for a user or your search function to key in on what is important on a page. But even doing all this can still end up with more clicks and additional searching than are really needed.To try to alleviate some of this, we decided to use a slightly modified method for searching all the content on the site. In addition to searching page content and Meta information, the search function we developed now checks a table of keywords for matches. These keywords can be associated with a specific page on the site, which allows administrators a way to create some &quot;most likely&quot; matches.Administrator view of the smart keywords and the associated pagesPerforming a search for &quot;catalog&quot; will show a list of pages on the site that have something to do with the library catalog. What sets this search apart from any other search, say &quot;summer reading,&quot; is that there is a &quot;Quick Results&quot; section at the top of the list. If the search term that you've searched for is present in the keyword table, this section will highlight the page that administrators think is most relevant.Of course, this requires a bit of legwork up front to create a number of keyword and page associations, but it can greatly cut down on the frustration that your users can experience. The flexibility of the keyword mapping function also allows administrators to keep their search function current as certain keywords become more popular. When there is a large amount of data to search through, sometimes it can be tough to find the best info to show a user. By setting up these associations, you can help users find the information they're looking for a little quicker.</description>
			<pubDate>Tue, 17 Oct 2006 11:33: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>Navigation Nightmare pt. 1</title>
			<link>http://www.sitecrafting.com/blog/navigation-nightmare-pt-1-1/</link>
			<description>foreach ($left_elements AS $le) {&amp;nbsp;&amp;nbsp;&amp;nbsp; ?&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;table class=&quot;leftnav_&amp;lt;?=$le['class']?&amp;gt;&quot;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;tr&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;td class=&quot;leftnav_&amp;lt;?=$le['class']?&amp;gt;&quot;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;a href=&quot;&amp;lt;?=$le['target']?&amp;gt;&quot; class=&quot;&amp;lt;?=$le['theme']?&amp;gt;&quot;&amp;gt;&amp;lt;?=$le['name']?&amp;gt;&amp;lt;/a&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/td&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/tr&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/table&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;?}Nobody wants to see that. Especially not seven different times with seven tiny variants covering seven different if conditions.Each higher 'class' number is a deeper indentation. Apparently it's necessary for this class identification to be repeated for the table, table cell and link. Converting this to a nested list format (part of my current task) is going to be an adventure.Well... at least it's indented nicely.</description>
			<pubDate>Wed, 18 Oct 2006 10:46:00 PDT</pubDate>
		</item>
			
		<item>
			<title>Group By Queries for MS SQL Server</title>
			<link>http://www.sitecrafting.com/blog/group-by-queries-ms-sql/</link>
			<description>Back in the day, we worked on developing a specialty application that was basically a lead generation system with a database that stored over 200,000 records, with a potential for a lot more. The web application displayed numerous reports that calculated totals from disparate sources. We discovered that once our client began adding all their data that those reports were running slower and slower and slower. The problem was that we had one primary query to pull the records out, then, as the code looped through each record, several other queries were needed to calculate the disparate totals. That resulted in numerous database calls that slowed the entire web application. That's when Mike discovered MySQL Wizardry, that used the SUM(IF()) and the GROUP BY clause, problem solved.One way to improve the speed and efficiency of a dynamic page is to pull all the needed information that is to be displayed in one query, that's where the MySQL Wizardry comes into play. This wizardry performs cross tabulations, which are great for statistical analysis. If you're planning on creating reports, I strongly suggest you read this article.Ever since we discovered this methodology, I've used it on numerous specialty applications, from calculating amounts and costs for a shopping list to determining totals for outstanding invoices.Below is an example of the MySQL Wizardry query.MySQL Query SELECT SUM( IF( company_size = &quot;large&quot;, 1, 0) ) as vLargeCount, SUM( IF(company_size = &quot;medium&quot;, 1, 0) ) as vMediumCount, SUM( IF(company_size = &quot;small&quot;, 1, 0) ) as vSmallCount, SUM( IF( company_age &amp;lt; = 4, 1, 0) ) as vYoungCompaniesCount, SUM( IF( company_age &amp;gt; 4, 1, 0) ) as vOlderComaniesCount, COUNT(companies.id) AS vTotalCompanyCountFROM companiesThe key here is the SUM(IF()) statements, this simple little piece of query magic aggregated a number of different queries into one query and turned out to be extremely efficient. As a side note, it's also important to index fields that are are used for the LEFT JOIN, in this case campaign.id and contacts_mail.campaign.Now, the Pierce County Library was developed in ASP.NET 2.0 and MS SQL Server 2005, but I wanted to apply the MySQL Wizardry magic to MS SQL server. The problem was that MS SQL Server does not have an IF statement, but this was easily remedied by using the CASE statement. Below is an example of the MySQL Wizardry for MS SQL Server.MS SQL Server QuerySELECT movies.title, movies.date,COUNT(movie_reviews.review_id) AS vReviewCount, SUM(CASE movie_reviews.thumbs WHEN &quot;UP&quot; THEN 1 ELSE 0 END) AS vThumbsUp, SUM(CASE movie_reviews.thumbs WHEN &quot;DOWN&quot; THEN 1 ELSE 0 END) AS vThumbsDown, FROM&amp;nbsp; movies LEFT OUTER JOIN movie_reviews&amp;nbsp; ON movies.code = movie_reviews.movie_codeGROUP BY movies.title, movies.dateORDER BY movies.date DESCVoilï¿½, SUM(IF()) is replaced by SUM(CASE) and we now have MS SQL Server Wizardry. There are two things that are important to note about this query. First is that MS SQL Server GROUP BY queries are much more restrictive than MySQL's GROUP BY functionality. Each data field (NOT expressions) in the SELECT statement MUST BE in the GROUP BY clause. The second item is that MS SQL Server does not allow ntext, text, and xml data types in the SELECT statement when performing a GROUP BY. There may be a way to include these data types, but since I was short on time and didn't really need those fields and decided to tackle this problem at a later date.Tweet</description>
			<pubDate>Tue, 24 Oct 2006 09:41:00 PDT</pubDate>
		</item>
			
		<item>
			<title>MS SQL Server 2005 text and ntext</title>
			<link>http://www.sitecrafting.com/blog/ms-sql-server-2005-ntext-1/</link>
			<description>How I discovered that text, ntext, and image data types have been deprecated and replaced by varchar(max), ntext(max), and varbinary(max).Recently, I needed to perform a query to update a number of links for the Pierce Count Library website. I thought I could use a simple REPLACE() string function, unfortunately, this turned out not to be the case. In order to update text and ntext datatypes using a query you're limited to a few functions, in my case I would be forced to use SUBSTRING() or UPDATETEXT().My original plan was to update all links in a field using a query like this:UPDATE web_pages SET web_pages.article1 = REPLACE( web_pages.article1, &quot;http://bad_link//&quot;, &quot;http://&quot;)Of course, when I tried this, I got an error that ntext datatypes are not allowed for the REPLACE function. So, I went online and begin searching for a function similar to REPLACE() that would work with ntext, that's when I found the msdn page for working with text, ntext, and image data types. I could have figured out a way to use SUBSTRING() or UPDATETEXT(), but  I determined that it would be much quicker to just look for the records that contained the bad links and update them manually.Later, I decided to do some research on the subject, because I just couldn't believe that there wasn't a way to use simple string functions with text and ntext. That's when I came across an informit article about Date, Math and Text Functions in SQL Server 2000 that explains how string functions don't work with text and ntext. Undaunted, I continued researching some more and that's when I found out that text, ntext, and image data types have been depracated for SQL 2005 and replaced by varchar(max), ntext(max), and varbinary(max). In fact, in future releases text, ntext, and image will no longer be supported. View the list at Deprecated Database Engine Features in SQL Server 2005.If I had only known. I would have designed all the fields to use nvarchar(max) instead of ntext. This would have solved a couple of problems for me. The first problem is that ntext data types can't be used in GROUP BY clauses and the second I would have been able to update the bad links a whole lot quicker by being able to use string functions. And if there was a need, I would have been able to use string functions in select statements to manipulate the text.</description>
			<pubDate>Fri, 27 Oct 2006 11:25: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>Names 1, IDs 0</title>
			<link>http://www.sitecrafting.com/blog/names-1-ids-0/</link>
			<description>  I never enjoy finding quirks in something so seemingly simple when I'm coding but it certainly happens. The following is a tale of how I ran into trouble with a couple attributes that should be worlds apart.    While working on a pretty spiffy site with all sorts of clutter saving JavaScript hiding/showing I ran up against a problem. On some pages these features were working just fine while on others they wouldn't do a thing -- not even throw up an error. I searched for a while without finding the culprit but eventually had a &quot;well, just try it&quot; moment that fixed things right up.The difference I found between pages was some anchor links. What was so special about these anchor links? See for yourself:...&amp;lt;a name=&quot;someSection&quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;table id=&quot;someSection&quot;&amp;gt;...IE6, your browser friend and mine, was trying to hide/show the anchor with the name &quot;someSection&quot; rather than the table with an ID of &quot;someSection&quot;. Since the anchor's pretty much invisible to begin with you can see how hard this would be to troubleshoot.A more common place you might run into this is when using forms. Since it's still common practice to give form elements names, this sort of hybrid old versus new DOM-compatibility fuzziness might pop up.Have a look at a quick example I whipped up in a newer browser then in IE6. May this save you billable time in the future when running into this yourself.</description>
			<pubDate>Mon, 11 Dec 2006 16:36: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>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>Cleaner forms through collapsible textareas</title>
			<link>http://www.sitecrafting.com/blog/cleaner-forms-collapsible-textareas/</link>
			<description>  Some really large forms can be a bit of an eyesore especially to the people filling them out. One thing that always bothered me was how bulbous most textareas had to be just to make enough room for a user to feel they could type what they needed. So I set out to figure a good way to clean up my forms a bit while still allowing the multi-line input of textareas.I'm not much for surprises so here's the final working example. The idea is to make any textarea on a page look just like a normal text input field. Once a user puts their cursor inside it expands to let them know they can type more than just a line.    First you should determine how tall you want the textarea when it's collapsed and when it's expanded. I recommend matching the collapsed height to any other text input fields in your form. Next add a class to the form(s) you'd like to convert to use collapsable textareas. With that, some CSS and a couple JS functions, we're there!You didn't think I'd leave you hanging, did you? Here's some code:/* first some CSS */.collapse_tareas input, .collapse_tareas textarea { font: 10pt arial, sans-serif; border: 1px solid #888; }.collapse_tareas textarea { height: 1.45em; }.collapse_tareas textarea.compact { height: 1.45em !important; }.collapse_tareas textarea.expanded { height: 5em !important; }Next comes the JavaScript:// find all the forms with textareas we want// to allow to collapsefunction setupTextareas() {&amp;nbsp; var pageForms = document.getElementsByTagName(&quot;form&quot;);&amp;nbsp; for( var j=0; j&amp;nbsp;&amp;nbsp;&amp;nbsp; var formArea = pageForms[j];&amp;nbsp;&amp;nbsp;&amp;nbsp; if( formArea.className.indexOf(&quot;collapse_tareas&quot;) &amp;gt; -1 ) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var txtAreas = formArea.getElementsByTagName(&quot;textarea&quot;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( var i=0; i&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var thisTxtArea = txtAreas[i];&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( thisTxtArea.addEventListener ) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thisTxtArea.addEventListener(&quot;focus&quot;, bigSmlTextarea, false);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thisTxtArea.addEventListener(&quot;blur&quot;, bigSmlTextarea, false);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else { // IE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thisTxtArea.attachEvent(&quot;onfocus&quot;, bigSmlTextarea);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thisTxtArea.attachEvent(&quot;onblur&quot;, bigSmlTextarea);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; }}// collapse or expand a textareafunction bigSmlTextarea(e){&amp;nbsp; var node = ( e.target ? e.target : e.srcElement );&amp;nbsp; if( node.className.indexOf(&quot;expanded&quot;) == -1 )&amp;nbsp;&amp;nbsp;&amp;nbsp; node.className += &quot; expanded&quot;;&amp;nbsp; else&amp;nbsp;&amp;nbsp;&amp;nbsp; node.className = node.className.replace(/expanded/gi, &quot;&quot;);&amp;nbsp; }// prep the the desired textareas to// collapse and expandwindow.onload = setupTextareas;By including the above CSS and JS on a page, any form with the &quot;collapse_tareas&quot; class will convert any textareas to collapsible ones. View the example and enjoy! It's an easy way to help clean up those unsightly forms.</description>
			<pubDate>Mon, 12 Mar 2007 10:27:00 PDT</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>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>ASP.NET 2.0 Tips - Shared Functions</title>
			<link>http://www.sitecrafting.com/blog/aspnet-20-tips-shared-functions/</link>
			<description>When developing a recent project for ASP.NET, there was a need to migrate a large number of generic functions that were created in PHP into the .net web project. For .net 1.0, you were able to add a code page that could be used for creating a bunch of functions. However, in .net 2.0, you still had the ability to add a code page, but it had to be a class. This meant placing all of our migrated functions as methods inside a class. To use a generic function, such as generateNewPassword(), you would have to first create a new object for the class and then call the method.Example:Dim objGenericFunctions as new GenericFunctions()blnPasswordSent = generateNewPassword(firstName, lastName, email)There are a couple of problems with this technique. First, since .net 2.0 encourages object-oriented programming, you could either create objGenericFunctions() once and pass the object as a parameter to other classes. But this requires extra code management, especially when there are classes that call other classes that might need to use some of those Generic Functions from objGenericFunctions. Or you could create a new objGenericfunctions whenever you need it, but this means creating a number of objects for the GenericFunctions class, which seems to be a waste of system resources. In developing classes for PHP 5.0, you could declare a class function as static. Which allowed you to use that method without having to create a new object. After some googling, I learned that VB.net also has a similar declaration, but they call it shared. So, by declaring a class function as shared, there's no need to create a new object each time.Example:blnPasswordSent = GenericFunctions.generateNewPassword(firstName, lastName, email)Here's a sample class with a shared function:Imports Microsoft.VisualBasicImports System.WebPublic Class GenericFunctions&amp;nbsp;&amp;nbsp; Public Shared Function isDateInRange(ByVal dateStart As DateTime, ByVal dateEnd As DateTime, ByVal dateCompare As DateTime) As Boolean&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim blnInRange As Boolean = False&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim intStartDiff As Integer = 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dim intEndDiff As Integer = 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intStartDiff = Date.Compare(dateStart, dateCompare)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intEndDiff = Date.Compare(dateCompare, dateEnd)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If intStartDiff &amp;lt;= 0 And intEndDiff &amp;lt;= 0 Then&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; blnInRange = True&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return blnInRange&amp;nbsp;&amp;nbsp;&amp;nbsp; End FunctionEnd ClassWe can take this one step for further by adding a namespace declaration to the class. By using a namespace, we can now add Imports GenericFunctions to the top of a code page and access those methods without having to type GenericFunctions first.Sample of Namespace declaration:Imports Microsoft.VisualBasicImports System.WebNamespace GenericFunctions&amp;nbsp;&amp;nbsp;&amp;nbsp; Public Class GenericFunctions&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' Place all the functions here...&amp;nbsp;&amp;nbsp;&amp;nbsp; End ClassEnd NamespaceExample of using the Imports statement:Default.aspx.vb - Code BehindImports GenericFunctionsPartial Class Default&amp;nbsp;&amp;nbsp;&amp;nbsp; Inherits System.Web.UI.Page&amp;nbsp;&amp;nbsp;&amp;nbsp; Protected Sub Page_Load(ByVal sender as Object, ByVal e As System.EventArgs) Handles Me.Load&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'No longer need to start with GenericFunctions&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; blnPasswordSent =generateNewPassword(firstName, lastName, email)&amp;nbsp;&amp;nbsp;&amp;nbsp; End SubEnd Class</description>
			<pubDate>Mon, 04 Jun 2007 11:31:00 PDT</pubDate>
		</item>
			
		<item>
			<title>ASP.net 2.0 Gridview vs. Custom Coding</title>
			<link>http://www.sitecrafting.com/blog/aspnet-20-gridview-vs-custom/</link>
			<description>I recently decided to try the Gridview control in asp.net 2.0. I read some documentation and decided that it would be very easy to implement. I started by following a step-by-step tutorial on creating a table using the Gridview control, which uses the SqlDataSource control. This step-by-step tutorial included details on how to add paging, column sorting, updating a record, and deleting a record. The tutorial can be found here. I was actually excited when I got this to work and how easy it was to do. It would only take a few minutes to create a simple, paged, sortable table where a user can delete and update records right on the page. Please note that simple is the operative word here.The next step was to start modifying the table's appearance to be similar to our standard table layout and colors and using images for the edit, delete, save, and cancel buttons. I first decided to tackle adding images to the&amp;nbsp; buttons. The default grid has a simple hyperlink button titled &quot;Edit&quot; and &quot;Delete&quot; and if you selected to &quot;Edit&quot; a record, those links were replaced by &quot;Update&quot; and &quot;Cancel.&quot; As I began looking into ways to change this, I soon learned it's not that simple. In order to use my images, I needed to add a new column to the Grid for a command field. This command field allowed me to select images for &quot;Edit&quot;, &quot;Delete&quot;, &quot;Update&quot;, and &quot;Cancel&quot; but it took me some time reading online tutorials and searching the Microsoft Visual Studio 2005 Documentation in order to figure out how to do it.I then updated the look and feel of the gridview to match our standard layout. That turned out to be pretty simple, since all I did was select a standard theme that's available to the gridview that was fairly close. I also wanted to hide the column that displayed the id number for each record, since a user has no need for it. Unfortunately, the Gridview needs that column in order to perform the delete and edit operations. I thought about updating the styling of cells under the id column to have a width of 0, but I didn't to want spend any more time on it. Next, I like how you could press the &quot;Edit&quot; icon or text and then that row would be converted to a simple form. So, I wanted to do the same thing for adding a new record. Ooops, that's not so easy either. It turns out that the Gridview does not have anything built in for adding a new record. After googling, there turned out to be a number of methods to simulate that behavior. Since I was in a hurry, I decided to go with the easiest one to implement, which is basically displaying a simple add form instead of the table. To see how this was done, please refer to this article. Unfortunately, this was not what I wanted.Now, the next thing I wanted to do was add a simple javascript to confirm that the user wants to delete the record. How hard could that be? Well, it's not exactly hard, I mean none of it is hard, just time consuming. In order to add javascript, I would need to convert the Gridview columns into templates in order to add the OnClientClick attribute to the delete icon button. Unfortunately, by converting to templates, that meant turning off the EnableSortingAndPagingCallbacks for the Gridview. Which meant I would have to do some more research on how to manually sort and page the Gridview. I decided that if a person clicked the delete, then the item will get deleted, no questions asked.What I learned was the more I features I wanted to add to the Gridview, the more research and coding that was required. In comparison, I decided to programatically write a table similar to Gridivew. I was able to add code for paging, column sorting, button to edit and delete a row, and a row for adding a new record. I was also able to add javascript to confirm a deletion. The edit button worked exactly the same as the Gridview, if you pressed edit, then that row would be converted to a simple form, with icon buttons for saving and cancelling. In addition, I was able to move the paging controls anywhere I wanted and to style it in any way. I also added a previous and next buttons, along with listing all the page numbers. At first glance, I couldn't find a way to this in the Gridview control.When comparing these two methods, Gridview vs Custom Coding, I spent twice as long creating the Gridview than I did using the custom coding method. However, this has more to do with the steep learning curve for the Gridview, especially when you need certain features, so I figure coding time could eventually be about the same, and would actually be a lot faster if the table is simple. The one advantage of Custom Coding, is that you can tailor your table to look and behave&amp;nbsp; exactly as you wish, especially if you wish to incorporate a lot of javascript. Hope this helps in determining when to use the Gridview or any other control.</description>
			<pubDate>Mon, 23 Jul 2007 17:29: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>
			
		<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>
			
	</channel>
</rss>
		
