<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dougv.com « Doug Vanderweide &#187; objects and classes</title>
	<atom:link href="http://www.dougv.com/tag/objects-and-classes/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.dougv.com</link>
	<description>ASP.NET, PHP, XML, JavaScript, Web geekery, Entrepreneurship</description>
	<lastBuildDate>Thu, 17 May 2012 22:33:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Killing Tynt&#8217;s &#8220;Read More&#8221; Clipboard Copy Hijacker With The Adblock Plus Plug-In For Firefox</title>
		<link>https://www.dougv.com/2010/07/19/killing-tynts-read-more-clipboard-copy-hijacker-with-the-adblock-plus-plug-in-for-firefox/</link>
		<comments>https://www.dougv.com/2010/07/19/killing-tynts-read-more-clipboard-copy-hijacker-with-the-adblock-plus-plug-in-for-firefox/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 23:07:12 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[ethics]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[marketing]]></category>
		<category><![CDATA[MySpace]]></category>
		<category><![CDATA[objects and classes]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[regular expression]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=3255</guid>
		<description><![CDATA[Update, 20 July 2011: I received an e-mail that notes the correct link to Tynt&#8217;s opt-out button is now http://www.tynt.com/tynt-users-opt-out. Its author adds that he believes their opt-out system now works. I love Firefox. It&#8217;s pretty much the only Web browser I use. I hate Tynt. If you&#8217;ve ever copied text from a Web page, [...]<div class="yarpp">
	<h5>Related Posts</h5>
		
No related posts.
	</div>
]]></description>
			<content:encoded><![CDATA[<div class="aside"><strong>Update, 20 July 2011:</strong> I received an e-mail that notes the correct link to Tynt&#8217;s opt-out button is now <a href="http://www.tynt.com/tynt-users-opt-out" target="_blank">http://www.tynt.com/tynt-users-opt-out</a>. Its author adds that he believes their opt-out system now works.</div>
<p></p>
<div id="attachment_3257" class="wp-caption alignnone" style="width: 510px"><a href="http://www.dougv.com/wp-content/uploads/2010/07/readmore.jpg"><img class="size-medium wp-image-3257" title="Tynt's annoying Read More clipboard jacking" src="http://www.dougv.com/wp-content/uploads/2010/07/readmore-500x236.jpg" alt="Tynt's annoying Read More clipboard jacking" width="500" height="236" /></a><p class="wp-caption-text">Tynt&#39;s annoying Read More clipboard jacking: You can kill it with AdBlock Plus for Firefox.</p></div>
<p>I love Firefox. It&#8217;s pretty much the only Web browser I use.</p>
<p>I hate <a href="http://www.tynt.com/" target="_blank">Tynt</a>. If you&#8217;ve ever copied text from a Web page, then pasted it, only to find a mysterious &#8220;Read More:&#8221; link inserted at the end of the text you copied, you just ran headfirst into Tynt.</p>
<blockquote><p>Each time a user pastes content from your website into an email, blog or website, we automatically add a URL link back to your site’s original content. When someone clicks that URL, they are directed back to your site and see the original content. This drives incremental traffic to your site when your content is shared without your knowledge while maintaining a consistent user experience.</p></blockquote>
<p>It may well be a &#8220;consistent user experience&#8221; for me to have to hit the backspace key to delete the &#8220;Read more&#8221; link Tynt adds every time I copy a small block of text, but it&#8217;s a consistently annoying experience.</p>
<p>I appreciate the importance of reciprocal links. I understand the challenge to content publishers of having content lifted from their Web sites without attribution.</p>
<p>So before I get into details about this fix, let me be clear: If you copy Web content, attribute it. It&#8217;s the right thing to do.</p>
<p>That said, there&#8217;s a wrong way of getting people to do the right thing, and Tynt is definitely the wrong way.</p>
<p>I find having my simple act of extracting a quote from a Web page turned into a link-spamming takeover of my local machine to be far more disturbing than a tracking cookie or layer ad.</p>
<p>Don&#8217;t be messing with my clipboard. It&#8217;s mine, not yours. I will put into it what I want there, not what you want.</p>
<p>Fortunately, I was able to put an immediate end to Tynt&#8217;s &#8220;Read More&#8221; clipboard copy highjacking in Firefox with <a href="https://addons.mozilla.org/en-US/firefox/addon/1865/" target="_blank">Adblock Plus</a>, a highly popular add-in that does what its name suggests: Blocks advertisements, and other content, from displaying on a page.</p>
<p><span id="more-3255"></span><br />
<h3>How To Block Tynt In Firefox Via Adblock Plus</h3>
<p>I don&#8217;t mind Web ads. In fact, on many sites, ads are quite useful. But I absolutely despise Tynt, so I went ahead and installed Adblock Plus specifically to deal with it:</p>
<ol>
<li>I installed AdBlock Plus from the link above.</li>
<li>After restarting Firefox, I was asked to choose a &#8220;filter subscription,&#8221; which is basically a series of user-contributed rules that block various ads, scripts, images, etc.
<ol>
<li>Because I don&#8217;t mind Web ads, I chose &#8220;Cancel.&#8221; Adblock Plus warned me that without a subscription, I would need to add any filters manually; I clicked OK.</li>
<li>You can go ahead and add a filter subscription. The &#8220;EasyList&#8221; subscription is supposed to block Tynt&#8217;s functionality; however, I found that was not always the case. For example, the EasyList (English) subscription available at this writing did not block Tynt on <a href="http://myspace.com/dougvdotcom" target="_blank">MySpace</a>.</li>
</ol>
</li>
<li>I selected Tools &#8211;&gt; Add-ons, then clicked the Options button under Adblock Plus.</li>
<li>I clicked &#8220;Add Filter&#8221; at the bottom of the window that came up.</li>
<li>A &#8220;New filter&#8221; line opened.
<ol>
<li>In the text box beneath, I entered *tynt* and hit the Enter key.</li>
<li>A red exclamation point resulted, which indicated that the filter was a regular expression / too short to be optimized. I accepted that; the reason why appears below.</li>
</ol>
</li>
<li>I clicked OK on the filter editing window and Close on the add-ons dialog box.</li>
</ol>
<div id="attachment_3264" class="wp-caption alignleft" style="width: 369px"><a href="http://www.dougv.com/wp-content/uploads/2010/07/abpscreens.jpg"><img class="size-medium wp-image-3264" title="Adblock Plus filter expression to turn off Tynt" src="http://www.dougv.com/wp-content/uploads/2010/07/abpscreens-359x500.jpg" alt="Adblock Plus filter expression to turn off Tynt" width="359" height="500" /></a><p class="wp-caption-text">The dialog boxes for Adblock Plus that accommodate my Tynt killing filter.</p></div>
<p>And just like that, I have not been bothered since by Tynt&#8217;s annoying &#8220;Read More&#8221; hijacking.</p>
<h3>The Alternatives Didn&#8217;t Work</h3>
<p>There are a number of suggestions out there to put an end to Tynt&#8217;s activities. I tried most but found them wanting compared to my solution.</p>
<p><strong>Block tcr.tynt.com via your computer&#8217;s HOSTS file:</strong> This was <a href="http://daringfireball.net/2010/05/tynt_copy_paste_jerks" target="_blank">a popular suggestion</a>. Many claimed it worked fine for them. But some Web sites &#8212; again, MySpace serves as an excellent example &#8212; aren&#8217;t stopped by blocking that one domain.</p>
<p>Tynt actually uses a number of subdomains to deliver its services; in some cases, the Tynt scripts run off the Web server you&#8217;re visiting. Since you can&#8217;t use wildcards in a HOSTS file, that means adding dozens of entries to the HOSTS file; and again, even that won&#8217;t stop Tynt if it is running off the local Web server.</p>
<p><strong>Use the NoScript add-on for Firefox:</strong> Another option is to employ <a href="https://addons.mozilla.org/en-US/firefox/addon/722/" target="_blank">NoScript</a>. But that is a nuclear solution; NoScript is pessimistic.</p>
<p>In other words, it blocks all Web sites from running JavaScript, and allows you to whitelist sites. That might have been an acceptable approach to annoying scripts five years ago, but in this age, your Web experience is going to be seriously curtailed if you start by blocking scripts.</p>
<p><strong>Use the YesScript add-on for Firefox:</strong> <a href="https://addons.mozilla.org/en-US/firefox/addon/4922/" target="_blank">YesScript</a> is a Firefox add-on that takes an optimistic approach to JavaScript. That is, you can blacklist sites, rather than having to whitelist them, as in NoScript.</p>
<p>Unfortunately, I did not see a way to use wildcards with YesScript, which pretty much made it the same as the HOSTS file option; and therefore, it did not work, for pretty much the same reasons.</p>
<p>And for the record, I looked for Greasemonkey scripts (couldn&#8217;t find one), add-ons specific to Tynt (couldn&#8217;t find one), and even tried using <a href="http://www.tynt.com/support/opt-inout/" target="_blank">Tynt&#8217;s purported global opt-out button</a> (surprise: it didn&#8217;t work).</p>
<h3>About That Exclamation Point In Adblock Plus</h3>
<p>Which brings us to the warning Adblock Plus shows about the filter rule.</p>
<p>As previously noted, our filter uses *tynt* as its expression. This is basically an instruction to Adblock Plus to block all objects that contain the letter sequence <em>tynt</em>: scripts, images, cookies, HTML, whatever.</p>
<p>Adblock Plus is smart enough to know that this is a very broad stroke; it&#8217;s four characters long, and generally speaking, that&#8217;s a wide net to cast &#8212; a net that could well catch a lot of fish we don&#8217;t want to fry.</p>
<p>For example, suppose we used the expression *ding*, instead. That would catch <a href="http://www.morewords.com/contains/ding/" target="_blank">over 900 different dictionary words</a> alone, most likely removing content from the page that we actually want to see.</p>
<p>On the other hand, *tynt* <a href="http://www.morewords.com/contains/tynt/" target="_blank">catches zero dictionary words</a>. Because that combination of letters is so rare &#8212; it almost exclusively applies to content we intend to block &#8212; the chances it blocks something we want to see is infinitesimal.</p>
<p>But Adblock Plus doesn&#8217;t know that, so it warns us.</p>
<p>Finally, I used *tynt* as the filter expression because I want to block not only scripts and content emanating from tynt.com, but to also catch local implementations of Tynt&#8217;s scripts and objects.</p>
<p>In other words, the entire Tynt clipboard hijacking solution could be installed on the Web host I am visiting. But the objects those scripts use are going to have to invoke the term <em>tynt</em> in calling objects or sending requests to Tynt&#8217;s servers in order to work; I am catching every time that happens with this expression, and putting an end to it before it begins.</p>
<p>All links in this post on delicious: <a href="http://delicious.com/dougvdotcom/killing-tynts-read-more-clipboard-copy-hijacker-with-the-adblock-plus-plug-in-for-firefox" target="_blank">http://delicious.com/dougvdotcom/killing-tynts-read-more-clipboard-copy-hijacker-with-the-adblock-plus-plug-in-for-firefox</a></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<p>No related posts.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/blogging/" title="blogging" rel="tag">blogging</a>, <a href="https://www.dougv.com/tag/ethics/" title="ethics" rel="tag">ethics</a>, <a href="https://www.dougv.com/tag/firefox/" title="Firefox" rel="tag">Firefox</a>, <a href="https://www.dougv.com/tag/marketing/" title="marketing" rel="tag">marketing</a>, <a href="https://www.dougv.com/tag/myspace/" title="MySpace" rel="tag">MySpace</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a>, <a href="https://www.dougv.com/tag/privacy/" title="privacy" rel="tag">privacy</a>, <a href="https://www.dougv.com/tag/regular-expression/" title="regular expression" rel="tag">regular expression</a>, <a href="https://www.dougv.com/tag/web-server/" title="web server" rel="tag">web server</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2010/07/19/killing-tynts-read-more-clipboard-copy-hijacker-with-the-adblock-plus-plug-in-for-firefox/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Good Coding Practices Should Replace Comments In Code</title>
		<link>https://www.dougv.com/2010/04/21/good-coding-practices-should-replace-comments-in-code/</link>
		<comments>https://www.dougv.com/2010/04/21/good-coding-practices-should-replace-comments-in-code/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 17:04:43 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[coding standards]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[metadata]]></category>
		<category><![CDATA[objects and classes]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2970</guid>
		<description><![CDATA[I recently came across a post on elegantcode.com that really struck a nerve. The premise: If you write good code, comments should not only be unnecessary, they could actually be counterproductive. Says author John Sonmez: &#8220;As my experience has increased, I have realized more and more that comments are actually bad. They indicate a failure.&#8221; [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2010/02/02/grouping-your-wordpress-blog-comments-by-type-comments-trackbacks-and-pingbacks/" rel="bookmark">Grouping Your WordPress Blog Comments By Type: Comments, Trackbacks And Pingbacks</a> (24)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (15.4)</li>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (14.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>I recently came across <a href="http://elegantcode.com/2010/04/18/eliminating-comments-the-road-to-clarity/" target="_blank">a post on elegantcode.com</a> that really struck a nerve. The premise: If you write good code, comments should not only be unnecessary, they could actually be counterproductive. Says author John Sonmez:</p>
<blockquote><p>&#8220;As my experience has increased, I have realized more and more that  comments are actually bad. They indicate a failure.&#8221;</p></blockquote>
<p>I know that this runs contrary to what most professors, instructors and textbooks say. They offer what seems a reasonable rule: Comment your code so that the next person who reads it doesn&#8217;t need to try to figure out what you&#8217;re doing.</p>
<p>And it&#8217;s also contrary to <a href="https://www.dougv.com/2009/06/25/how-i-code-on-this-blog-elegance-vs-transparency/" title="How I Code On This Blog: Elegance Vs. Transparency">most of the code I put out on this Web site</a>. I would certainly agree that I over-comment my code, but that&#8217;s a conscious decision, based in large part because I want my readers, who tend to be newer programmers, to completely understand what my code is doing at each step.</p>
<p>But as Sonmez notes, comments aren&#8217;t the best way to achieve that goal, especially in object-oriented code.</p>
<p>For example, if you change code, its related comment doesn&#8217;t change. Use proper constants &#8212; e.g., DEFAULT_LOOP_ITERATIONS &#8212; instead of a variable declarations. Name your methods, properties and function so they are self-documenting (do you really need to comment a method named OpenXMLFile?) and write more code so that self-documenting names can replace more abstract procedural code calls.</p>
<p>It&#8217;s this third suggestion that interests me. I&#8217;ve said, <a href="http://www.dougv.com/tag/elegance/">many times</a>, that less code is better. I maintain that view. But I&#8217;m inclined to agree more with Sonmez that, if it takes a few extra lines and a couple more dependencies to create self-documenting code, that complexity is probably the right trade-off, versus adding novella-sized comment blocks.</p>
<p>I&#8217;m almost certainly going to continue over-commenting code here, especially because I am trying to serve the needs of novice programmers.</p>
<p>But Sonmez&#8217;s brilliant post really hits hard, and reminds me that if I am trying to write simple code that&#8217;s easy to understand, I should rely more on best programming practices than double-slashes. Expect to see more of that in the future. And please do take the time to read his post in full.</p>
<p>All links in this post on delicious: <a href="http://delicious.com/dougvdotcom/good-coding-practices-should-replace-comments-in-code" target="_blank">http://delicious.com/dougvdotcom/good-coding-practices-should-replace-comments-in-code</a></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2010/02/02/grouping-your-wordpress-blog-comments-by-type-comments-trackbacks-and-pingbacks/" rel="bookmark">Grouping Your WordPress Blog Comments By Type: Comments, Trackbacks And Pingbacks</a> (24)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (15.4)</li>
				<li><a href="https://www.dougv.com/2006/12/13/a-request-of-yahoo-answers-code-questioners-please-post-your-code-on-geocities-or-another-web-site/" rel="bookmark">A Request Of Yahoo! Answers Code Questioners: Please Post Your Code On Geocities (Or Another Web Site)</a> (14.7)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/coding-standards/" title="coding standards" rel="tag">coding standards</a>, <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/metadata/" title="metadata" rel="tag">metadata</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a>, <a href="https://www.dougv.com/tag/productivity/" title="productivity" rel="tag">productivity</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2010/04/21/good-coding-practices-should-replace-comments-in-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MSDN Northeast Roadshow: Sept. 24 in Augusta, ME</title>
		<link>https://www.dougv.com/2009/08/14/msdn-northeast-roadshow-sept-24-in-augusta-me/</link>
		<comments>https://www.dougv.com/2009/08/14/msdn-northeast-roadshow-sept-24-in-augusta-me/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 22:48:31 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Help Desk]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Transact-SQL]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2607</guid>
		<description><![CDATA[The MSDN Roadshow returns to Augusta, ME and the Central Maine Commerce Center&#8217;s Florian Auditorium on Sept. 24, from 1 p.m. &#8211; 6 p.m. (That&#8217;s a later start than recent roadshows, because directly before it, there&#8217;s a TechNet event about Windows 7 and Remote Desktop.) MSDN Roadshows are a chance for Microsoft evangelists &#8212; namely, [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/03/05/msdn-roadshow-in-augusta-march-19-well-worth-the-time/" rel="bookmark">MSDN Roadshow In Augusta, March 19: Well Worth The Time</a> (58.1)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>The MSDN Roadshow returns to Augusta, ME and the Central Maine Commerce Center&#8217;s Florian Auditorium on Sept. 24, from 1 p.m. &#8211; 6 p.m. (That&#8217;s a later start than recent roadshows, because directly before it, there&#8217;s <a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032421462&#038;culture=en-US">a TechNet event about Windows 7 and Remote Desktop</a>.)</p>
<p>MSDN Roadshows are a chance for Microsoft evangelists &#8212; namely, <a href="http://blogs.msdn.com/cbowen/">Chris Bowen</a> and <a href="http://blogs.msdn.com/jimoneil/">Jim O&#8217;Neil</a> &#8212; to describe new technologies, demonstrate how to program in Microsoft languages and platforms, and generally share the word about what&#8217;s new and on Microsoft&#8217;s mind at the moment.</p>
<p>Among <a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032421463&#038;Culture=en-US">the issues to be discussed at this roadshow</a> is Windows 7. Without question, Chris and Jim know their stuff, and you&#8217;ll definitely walk away from this event with a better knowledge of Microsoft technologies &#8212; if not some of the loot they give out at every event (fully-functional copies of Windows Vista, Visual Developer 2008 Professional, Microsoft Press books and peripherals having been offered in the past as door prizes).</p>
<p>Florian Auditorium and the Central Maine Commerce Center are in the former SCI Systems / Digital Equipment plant off Civic Center Drive. <a href="http://maps.google.com/maps/ms?hl=en&#038;ie=UTF8&#038;msa=0&#038;msid=118213201074978555142.000471a0a11f1929ed01c&#038;ll=44.366186,-69.801292&#038;spn=0.010646,0.027874&#038;z=14">I have a public Google Map of the location</a>.</p>
<p>If Augusta or the date are not convenient for you, Chris and Jim are doing the same agenda in Manchester, NH; Rochester, NY; Troy, NY; Waltham, MA and Farmington, MA. <a href="http://blogs.msdn.com/cbowen/archive/2009/07/20/announcing-the-fall-2009-northeast-msdn-roadshow.aspx">Chris Bowen details it all on his blog</a>.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2009/03/05/msdn-roadshow-in-augusta-march-19-well-worth-the-time/" rel="bookmark">MSDN Roadshow In Augusta, March 19: Well Worth The Time</a> (58.1)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/08/14/msdn-northeast-roadshow-sept-24-in-augusta-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working With The Authorize.net Customer Information Manager (CIM), Part 1: Overview</title>
		<link>https://www.dougv.com/2009/07/06/working-with-the-authorize-net-customer-information-manager-cim-part-1-overview/</link>
		<comments>https://www.dougv.com/2009/07/06/working-with-the-authorize-net-customer-information-manager-cim-part-1-overview/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 04:59:31 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[XPath]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2424</guid>
		<description><![CDATA[I&#8217;m going to spend several posts discussing authorize.net&#8217;s Customer Information Manager, a Web service for storing and retrieving personally identifiable information about the people who place credit card orders on your Web site. Today, I&#8217;m focusing solely on an overview of CIM: What it is, how it works, why it works that way, and approaches [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/07/03/working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">Working With A Simple Structure Array In VB.NET</a> (15.2)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (13.9)</li>
				<li><a href="https://www.dougv.com/2006/11/26/a-simple-php-script-mysql-too-to-track-radio-station-song-requests/" rel="bookmark">A Simple PHP Script (MySQL, Too) To Track Radio Station Song Requests, Part 1</a> (10.9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to spend several posts discussing <a href="http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/">authorize.net&#8217;s Customer Information Manager</a>, a Web service for storing and retrieving personally identifiable information about the people who place credit card orders on your Web site.</p>
<p>Today, I&#8217;m focusing solely on an overview of CIM: What it is, how it works, why it works that way, and approaches to integrating CIM into your custom storefront / ordering systems. In future posts, I will discuss actual implementation via PHP and MySQL; my intent is to use 2-3 posts to cover the process, but it may take more or less. My intent is to post every day, but there may be a delay of a day or two between posts.</p>
<p>(I&#8217;m uncertain on the number and timing of posts on this topic because I&#8217;ll be blogging about implementation as I implement CIM for the first time. And lest that gives you pause, I&#8217;ve extensively reviewed the documentation, tested the basics of using the service, and have over 10 years&#8217; experience with PHP / XML / MySQL. And because I&#8217;m doing the actual implementation for pay, I will have extensively tested the solution for elegance, reliability and security.)</p>
<h3>What Is A Web Service?</h3>
<p>The Customer Information Manager is a Web service. In its most common implementation on the World Wide Web, you send a <a href="http://www.w3schools.com/webservices/default.asp">Web service</a> an XML document describing information you want, and the service responds with an XML document that contains the information you requested. (Not all Web services work this way; there are many kinds of Web services out there. But rather than bog down the point, let&#8217;s stick with this basic description.)</p>
<p>We can therefore think of a Web service as a remote database; the Customer Information Manager Web service is, in fact, a way to get data into and out of a remote database.</p>
<p>In the case of a Web service, rather than connecting to a local database, writing a SQL query and asking it to send us a result set (or Boolean false on failure), such as we would do in PHP / MySQL, we instead write an XML document that provides our authentication credentials and describes the data we want, send that to the CIM Web service via cUrl (or, if your server allows it, <a href="http://phpsec.org/projects/phpsecinfo/tests/allow_url_fopen.html">fopen</a>), and get back from the CIM an XML document that contains the records we want (or an error code describing any problems encountered).</p>
<p>In other words, for most intents and purposes, the CIM Web service works exactly like a database, only different. So why in the world does authorize.net bother with a Web service, rather than simply giving you access to their database directly?</p>
<p><span id="more-2424"></span></p>
<p>In a word, <em>security</em>. The primary benefit in providing the Customer Information Manager as a Web service is that it acts as an abstraction, and a fairly limited one at that.</p>
<p>What I mean is, if you had the ability to run any old UPDATE or DELETE query you wanted to run on the Customer Information Manager, you&#8217;d be able to do some serious damage, even if you only messed up your own records. (Everyone who has worked with SQL queries for more than a week has totally annihilated database tables with ill-considered UPDATE or DELETE queries.)</p>
<p>The <a href="http://developer.authorize.net/guides/">Customer Information Manager APIs</a> (application programming interfaces) allow authorize.net to restrict your activities to some basic tasks; namely, creating new customer database entries (&#8220;profiles&#8221;), deleting them one at a time; updating them one at a time; or getting a list of profile IDs.</p>
<p>The other benefit to the CIM Web service approach is, by only accepting XML requests and sending back XML in response, authorize.net can impose several levels of protection between the database and you. We don&#8217;t know, for example, what database holds our information; we can&#8217;t try to hack root; authorize.net is able to insert several layers of intrusion detection / firewall / load balancing between the XML we see and the database we can&#8217;t see.</p>
<h3>Why Bother With CIM?</h3>
<p>The primary reason to work with the Customer Information Manager is that it fully complies with the <a href="https://www.pcisecuritystandards.org/security_standards/pci_dss.shtml">Payment Card Industry (PCI) Data Security Standard (DSS)</a>. Having a secure payment gateway to process online credit cards is one thing; being able to protect the credit card numbers you collect, as well as personally identifiable information about cardholders, is another.</p>
<p>Generally speaking, accepting a payment isn&#8217;t of any use in and of itself; in exchange for the money you receive, you usually need to provide some good or service, and in order to do that, you usually need the name and / or address of the person sending you money, if not details about what the customer wants, too.</p>
<p>The DSS doesn&#8217;t have Draconian requirements, but you probably can&#8217;t ensure those requirements are met on a shared Web hosting account. Or, even if you aren&#8217;t on shared hosting, you might want to absolve yourself of the responsibility of complying with DSS. That&#8217;s the primary business reason for using CIM.</p>
<p>CIM can also help you work with returning customers or recurring payments. Thanks to its object model, you can associate multiple credit cards and addresses with a given customer (both billing and shipping). In my application, the client sells subscriptions; often, subscribers not only order for themselves, but also for others (e.g., gift subscriptions); some subscribers also want to be auto-rebilled at the end of every subscription term.</p>
<p>Using the Customer Information Manager will allow my client to not only quickly relate each customer to all the subscriptions he has purchased, it will make rebilling as simple as asking the server to round up all rebill clients set for a given date, get their billing information and credit card from CIM, and batch submit them. (I won&#8217;t cover this last bit immediately, as my client wants to hold off on the rebilling part until he sees how successful online sales prove.)</p>
<p>So what that boils down to is, I can completely ignore AIM &#8212; the API most authorize.net developers know, and which is most commonly used to process transactions through authorize.net &#8212; in favor of CIM.</p>
<h3>What CIM Is Not</h3>
<p>As I describe what the Customer Information Manager can do, I should take a moment to address the things CIM does not do.</p>
<p><em>The APIs for CIM and AIM are not integrated and do not use the same methodologies.</em> AIM &#8212; the authorize.net API that allows you to get money from credit cards &#8212; accepts POSTed form variables from your request and sends a delimited string back as a response. CIM is a Web service; it accepts and returns XML.</p>
<p>This isn&#8217;t a problem if you use CIM to handle all aspects of your online payments; you just cut out AIM altogether, as I plan to do.</p>
<p>However, some situations &#8212; such as sites using third-party e-commerce programs (e.g., <a href="http://www.zen-cart.com/">Zen Cart</a> or <a href="http://www.oscommerce.com/">osCommerce</a>), or custom software integrated with AIM that cannot be easily modified to use CIM &#8212; call for using CIM to only hold customer data. If you fall into the group that needs to use both CIM and AIM, most of what I discuss in upcoming posts will be of value, but keep in mind that CIM and AIM don&#8217;t work the same way.</p>
<p><em>While CIM stores lots of customer information, it isn&#8217;t extensible, nor is it very flexible.</em> Again, you can associate multiple credit cards and billing / shipping addresses with each customer profile. But if you want to store additional information about a customer, you&#8217;re out of luck. CIM gives you 20-character &#8220;refId&#8221; and &#8220;merchantCustomerId&#8221; fields, as well as a 255-character &#8220;description&#8221; field, for each customer.</p>
<p>We can store information about individual transactions made by each customer profile, too. In other words, not only can each customer profile have multiple credit cards and addresses associated with it, but we can also record basic information about items purchased by the customer &#8212; such as item IDs, quantities and descriptions &#8212; for each order the customer places.</p>
<p>Even so, this may not be enough flexibility for your application. Technically speaking, you can store some information about a customer on your local server, and so long as it is not personally identifiable, you&#8217;ll still comply with DSS requirements.</p>
<p>For example, if you keep a small memo field on your local server that uses no names, addresses, phone numbers, etc. that can be used to identify the customer, you can simply key that memo field to the CIM customer profile ID and still be in compliance with DSS (as there is no local correlation to the customer&#8217;s personal information and the memo you are keeping). To ensure compliance with DSS, you might want to consider using a hash / encryption scheme to obfuscate the CIM customer ID key.</p>
<h3>The Methodology I&#8217;ll Use</h3>
<p>I am going to take a fairly pragmatic and direct approach to the application I write. That is, I&#8217;m going to keep it simple and direct.</p>
<p>My initial intent was to create a series of classes that represent the objects in the Customer Information Manager API. I actually got as far as defining all the objects&#8217; properties and a significant number of the methods needed, before I decided it was consuming too much time and becoming a $1,000 solution to a 37-cent problem.</p>
<p>So, I&#8217;m simply going to use PHP 5, a little MySQL, and <a href="http://us3.php.net/manual/en/class.domdocument.php">DomDocument</a> to integrate the XML API for the Customer Information Manager. I&#8217;ll use <a href="http://us3.php.net/manual/en/book.curl.php">cUrl</a> to send requests.</p>
<p>I could have used the SOAP API. However, at least in the CIM API implementation, SOAP is fundamentally XML, only with the side aggravation of namespaces. Since that&#8217;s the case, and since I believe most readers of this blog will understand XML better than SOAP, that&#8217;s the way I will go.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/07/03/working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">Working With A Simple Structure Array In VB.NET</a> (15.2)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (13.9)</li>
				<li><a href="https://www.dougv.com/2006/11/26/a-simple-php-script-mysql-too-to-track-radio-station-song-requests/" rel="bookmark">A Simple PHP Script (MySQL, Too) To Track Radio Station Song Requests, Part 1</a> (10.9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a>, <a href="https://www.dougv.com/tag/web-services/" title="Web Services" rel="tag">Web Services</a>, <a href="https://www.dougv.com/tag/xpath/" title="XPath" rel="tag">XPath</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/07/06/working-with-the-authorize-net-customer-information-manager-cim-part-1-overview/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>JavaScript Function Arguments: They&#8217;re An Array And You Can Treat Them As Such</title>
		<link>https://www.dougv.com/2009/06/20/javascript-function-arguments-theyre-an-array-and-you-can-treat-them-as-such/</link>
		<comments>https://www.dougv.com/2009/06/20/javascript-function-arguments-theyre-an-array-and-you-can-treat-them-as-such/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 16:22:46 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[DOM images]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2342</guid>
		<description><![CDATA[One of the nicest features of JavaScript is the ability to treat function arguments as an array. We all know how to write a function that takes a known number of arguments: But sometimes, your script will require you to pass some unknown number of parameters to a function. So how do you deal with [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/07/03/working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">Working With A Simple Structure Array In VB.NET</a> (17.7)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (16.2)</li>
				<li><a href="https://www.dougv.com/2007/01/15/dynamically-populating-a-listbox-from-a-textbox-via-javascript-dom/" rel="bookmark">Dynamically Populating A Listbox From A Textbox Via JavaScript / DOM</a> (14.5)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>One of the nicest features of JavaScript is the ability to treat function arguments as an array. We all know how to write a function that takes a known number of arguments:</p>
<pre class="brush: jscript; title: ; notranslate">
function foo(bar) {
	alert(bar);
}

function getArea(shape, measure, unit) {
	var output = 'The area of a ' + measure + ' ' + unit + ' ' + shape + ' is ';
	switch(shape) {
		case 'square':
			output += (measure * measure);
			break;
		case 'circle':
			output += (3.14 * (measure * measure));
			break;
		default:
			output += 'unknown to this function.';
	}
	alert(output);
}
</pre>
<p>But sometimes, your script will require you to pass some unknown number of parameters to a function. So how do you deal with that?</p>
<p>Luckily, JavaScript functions treat all of their arguments as an array. So, if you&#8217;re not certain how many arguments your function will take, don&#8217;t declare them in your function code; simply use the reserved word arguments to iterate the array of arguments passed to the function.</p>
<p><span id="more-2342"></span></p>
<pre class="brush: jscript; title: ; notranslate">
function allTheAnimals() {
	var output = 'The animals you provided are: ';
	for(var i = 0; i &lt; arguments.length; i++) {
		output += arguments[i] + ', ';
	}
	output = output.substring(0, (output.length - 2)); //remove trailing comma and space
	alert(output);
}
</pre>
<p>Note that we can ask for specific indexes of the array, but should ensure there are at least that many elements in the array before asking:</p>
<pre class="brush: jscript; title: ; notranslate">
function threeIsAMagicNumber() {
	if(arguments.length &lt; 3) {
		alert('There is no third argument!');
	}
	else {
		alert('The value of the third argument passed to this function is ' + arguments[2].toString());
	}
}
</pre>
<p>We can even pass an unknown number of arguments from one function to another, via the <a href="http://www.webreference.com/js/column26/apply.html">apply method</a>:</p>
<pre class="brush: jscript; title: ; notranslate">
function parentFunction() {
	var output = 'Arguments received by parent function: ';
	for(var i = 0; i &lt; arguments.length; i++) {
		output += arguments[i] + ', ';
	}
	output = output.substring(0, (output.length - 2));
	output += &quot;\n\nDo you want to send these to the child function? OK to submit to child function, Cancel to abort.&quot;;
	if(confirm(output)) {
		childFunction.apply(this, arguments);
	}
}

function childFunction() {
	var output = 'Arguments received by the child function: ';
	for(var i = 0; i &lt; arguments.length; i++) {
		output += arguments[i] + ', ';
	}
	output = output.substring(0, (output.length - 2));
	alert(output);
}
</pre>
<p>You can see a demonstration of all these here: <a href="http://www.dougv.com/demo/js_function_arguments_array/">http://www.dougv.com/demo/js_function_arguments_array/</a></p>
<p>I distribute code under the GNU GPL version 3.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/07/03/working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">Working With A Simple Structure Array In VB.NET</a> (17.7)</li>
				<li><a href="https://www.dougv.com/2007/07/04/in-reply-to-comments-made-on-working-with-a-simple-structure-array-in-vbnet/" rel="bookmark">In Reply To Comments Made On &quot;Working With A Simple Structure Array In VB.NET&quot;</a> (16.2)</li>
				<li><a href="https://www.dougv.com/2007/01/15/dynamically-populating-a-listbox-from-a-textbox-via-javascript-dom/" rel="bookmark">Dynamically Populating A Listbox From A Textbox Via JavaScript / DOM</a> (14.5)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/dom-images/" title="DOM images" rel="tag">DOM images</a>, <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/06/20/javascript-function-arguments-theyre-an-array-and-you-can-treat-them-as-such/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Using JavaScript To Perform A Task Traditionally Solved With Server-Side Scripting</title>
		<link>https://www.dougv.com/2009/05/13/using-javascript-to-perform-a-task-traditionally-solved-with-server-side-scripting/</link>
		<comments>https://www.dougv.com/2009/05/13/using-javascript-to-perform-a-task-traditionally-solved-with-server-side-scripting/#comments</comments>
		<pubDate>Wed, 13 May 2009 23:29:25 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=2045</guid>
		<description><![CDATA[Asked recently on Yahoo! Answers: Does anyone know how to automatically update a birthday list on a web page? Our web page has a section that displays all staff birthdays for the week. This section is updated manually every Monday morning. Is there a way to have this update done automatically everyday. Must display all [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/10/17/printing-sections-of-a-web-page-using-divs-and-javascript-remote-scripting/" rel="bookmark">Printing Sections Of A Web Page Using DIVs And JavaScript Remote Scripting</a> (21.7)</li>
				<li><a href="https://www.dougv.com/2008/11/08/cleaning-up-some-php-and-incorporating-a-javascript-based-image-preview/" rel="bookmark">Cleaning Up Some PHP And Incorporating A JavaScript-Based Image Preview</a> (12.8)</li>
				<li><a href="https://www.dougv.com/2007/01/01/using-php-mysql-to-store-a-form-value-calculated-via-javascript-dom/" rel="bookmark">Using PHP / MySQL To Store A Form Value Calculated Via JavaScript / DOM</a> (10.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Asked recently on Yahoo! Answers:</p>
<blockquote><p><strong><a href="http://answers.yahoo.com/question/index?qid=20090513065556AAFSpZD">Does anyone know how to automatically update a birthday list on a web page?</a></strong><br />
Our web page has a section that displays all staff birthdays for the week. This section is updated manually every Monday morning. Is there a way to have this update done automatically everyday. Must display all birthdays for that day and all birthdays for the next 6 days. The format required is:<br />
Date (eg: 13 May)<br />
Name Surname, Department (a new line entry for each employee with a birthday on that day)<br />
Above repeated for each of the other 6 days.</p></blockquote>
<p>This question presents me with an excellent opportunity to discuss a topic I&#8217;ve not really had a chance to broach before: namely, the decision process on whether to use JavaScript or a server-side scripting language, such as PHP or ASP.NET, to accomplish a given task.</p>
<p>Using JavaScript to accomplish a traditional server-side scripted, data-driven task is becoming increasingly popular, especially as <a href="http://www.ecma-international.org/memento/TC39.htm">ECMAScript standards</a> are more widely adopted, libraries such as <a href="http://jquery.com/">jQuery</a> gain prevalence and supporting technologies, such as <a href="http://code.google.com/apis/gears/">Google Gears</a>, remove many of the traditional roadblocks in writing client-side scripts for stateless Web applications.</p>
<p>In this case, we have a problem that can be solved either client-side (JavaScript) or server-side (in this case, PHP / MySQL). Which to choose is largely a function of scale: If we&#8217;re dealing with hundreds or thousands of employee birthdays we want to display, we&#8217;re probably best off using a server-side technology; but if we have fewer employees, it might make sense to simply use JavaScript, and push the workload from the server and onto our visitors.</p>
<p>I&#8217;ll demonstrate both the traditional PHP / MySQL approach, as well as a JavaScript approach.</p>
<p><span id="more-2045"></span></p>
<p><strong>The Old-School Approach: PHP And MySQL</strong></p>
<p>Let&#8217;s start with the traditional way of selecting and sorting a subset of data from a master data store: PHP and MySQL.</p>
<p>In this case, we simply create a table in MySQL that holds a listing of employee names, birthdays and departments (depending on the size and complexity of the organization, we&#8217;d likely use multiple tables to store this data, with foreign keys relating each; for the purposes of this demo, we&#8217;ll use one table). Here&#8217;s the SQL to create such a table, with 11 demo records:</p>
<pre class="brush: sql; title: ; notranslate">
CREATE TABLE IF NOT EXISTS `php_birthday_list` (
  `person_id` int(10) unsigned NOT NULL auto_increment,
  `person_name` varchar(50) NOT NULL,
  `person_surname` varchar(50) NOT NULL,
  `person_birthdate` date NOT NULL,
  `person_department` varchar(50) NOT NULL,
  PRIMARY KEY  (`person_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;

INSERT INTO `php_birthday_list` (`person_id`, `person_name`, `person_surname`, `person_birthdate`, `person_department`) VALUES
(1, 'Tom', 'Jones', '1984-05-10', 'Maintenance'),
(2, 'Richard', 'Gingras', '1946-05-11', 'Administration'),
(3, 'Joan', 'Walsh', '1973-05-11', 'Administration'),
(4, 'Norman', 'Blashka', '1953-05-12', 'Maintenance'),
(5, 'Kerry', 'Lauerman', '1967-05-13', 'Administration'),
(6, 'Jeanne', 'Carstensen', '1990-05-15', 'Accounts Payable'),
(7, 'Ruth', 'Henrich', '1981-05-16', 'Maintenance'),
(8, 'Joy', 'Press', '1969-05-14', 'Accounts Payable'),
(9, 'Page', 'Rockwell', '1951-05-10', 'Warehouse'),
(10, 'Laura', 'Miller', '1982-03-21', 'Accounts Payable'),
(11, 'Wendy', 'Williams', '1992-05-17', 'Accounts Payable');
</pre>
<p>With data now on hand, we can create a PHP script to query the database for all birthdays this week. We do that in several steps:</p>
<p>First, we determine the timestamp for the Sunday of the current week. The easiest way to do that is via <a href="http://us3.php.net/getdate">the getdate() function</a>, which will return the day of the week represented by the current date, indexed from 0 (Sunday) to 6 (Saturday). Since we&#8217;re interested in Sunday, we take the current timestamp, then subtract from it the number of seconds in a day (86,400) times the day of the week returned by getdate().</p>
<p>So, for example, suppose $today['wday'] is 2 (i.e., today is Tuesday). If I multiply 86,400 by 2 (172,800), and subtract that from the current timestamp, I&#8217;ll have a timestamp that falls on the previous Sunday.</p>
<p>We next need to find when Saturday falls on the same week. The math this time is to subtract the current weekday value from 6 (which is Saturday), multiply that by the number of seconds in a day, and add that to the current timestamp. So, if today is Tuesday, (6 &#8211; 2) * 86,400 = 4 * 86,400 = 345,600 seconds, which when added to the current timestamp will give me a timestamp that falls on Saturday.</p>
<p>Now that we have timestamps for the Sunday and Saturday of the week, we need to get the month and day values from each. We&#8217;ll then find all the birthdays in the table that have a month equal to or greater than the Sunday month, <em>and</em> a month equal to or less than the Saturday month, <em>and</em> a day equal to or greater than the Sunday day, <em>and</em> a day equal to or less than the Saturday day.</p>
<p>If we find no matches, we have no birthdays. Otherwise, we will loop through the results set, outputting every person whose birthday falls within this week.</p>
<pre class="brush: php; title: ; notranslate">
if(!$link = mysql_connect('server', 'host', 'password')) {
	echo &quot;&lt;p&gt;&lt;strong&gt;Could not connect to database server.&lt;/strong&gt;&lt;/p&gt;n&quot;;
}
//select database
elseif(!mysql_select_db('database')) {
	echo &quot;&lt;p&gt;&lt;strong&gt;Could not select database.&lt;/strong&gt;&lt;/p&gt;n&quot;;
}
else {
	//get today's date info
	$today = getdate(time());

	/*
	OPTION 1: This week only. Birthdays falling between Sunday and Saturday of this week are shown.
	*/

	//find the sunday of this week
	$sun = time() - (86400 * $today['wday']);
	//find the saturday of this week
	$sat = time() + ((6 - $today['wday']) * 86400);

	//get month and day for each
	$sun_mon = date('m', $sun);
	$sun_day = date('d', $sun);
	$sat_mon = date('m', $sat);
	$sat_day = date('d', $sat);

	//get records
	if(!$rs = mysql_query(&quot;SELECT person_name, person_surname, person_birthdate, person_department FROM php_birthday_list WHERE MONTH(person_birthdate) &gt;= $sun_mon AND MONTH(person_birthdate) &lt;= $sat_mon AND DAYOFMONTH(person_birthdate) &gt;= $sun_day AND DAYOFMONTH(person_birthdate) &lt;= $sat_day ORDER BY MONTH(person_birthdate), DAYOFMONTH(person_birthdate), person_surname, person_name, person_department&quot;)) {
		echo &quot;&lt;p&gt;&lt;strong&gt;There was an error parsing the query.&lt;/strong&gt;&lt;/p&gt;n&quot;;
	}
	//no records found
	elseif(mysql_num_rows($rs) == 0) {
		echo &quot;&lt;p&gt;&lt;strong&gt;No staff birthdays this week.&lt;/strong&gt;&lt;/p&gt;n&quot;;
	}
	else {
		echo &quot;&lt;p&gt;Option 1: This week's birthdays&lt;/p&gt;n&quot;;
		//output birthdays
		echo &quot;&lt;table class=&quot;bordered&quot; cellspacing=&quot;0&quot;&gt;n&quot;;
		echo &quot;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Birthday&lt;/th&gt;&lt;th&gt;Age&lt;/th&gt;&lt;th&gt;Department&lt;/th&gt;&lt;/tr&gt;n&quot;;
		while($row = mysql_fetch_array($rs)) {
			$age = time() - strtotime($row['person_birthdate']);
			$age = floor($age / 31536000);

			echo &quot;&lt;tr&gt;&quot;;
			echo &quot;&lt;td&gt;$row[person_name] $row[person_surname]&lt;/td&gt;&quot;;
			echo &quot;&lt;td&gt;&quot; . date('F j, Y', strtotime($row['person_birthdate'])) . &quot;&lt;/td&gt;&quot;;
			echo &quot;&lt;td&gt;$age&lt;/td&gt;&quot;;
			echo &quot;&lt;td&gt;$row[person_department]&lt;/td&gt;&quot;;
			echo &quot;&lt;/tr&gt;n&quot;;
		}
		echo &quot;&lt;/table&gt;&lt;br /&gt;n&quot;;
	}
}
</pre>
<p>The question above wasn&#8217;t crystal-clear about what constitutes a week. It may be that the questioner actually means a week to be today, plus the next six days. If so, a little tweaking of our code above accomplishes that task.</p>
<p>Instead of calculating the Sunday and Saturday of the current week, we can simply take the current timestamp, add 518,400 seconds (the number of seconds in six days) and get a end timestamp that&#8217;s six days from now.</p>
<p>Otherwise, the script is unchanged.</p>
<pre class="brush: php; title: ; notranslate">
/*
OPTION 2: Today and six days hence.
*/

//get starting and ending months and days
$end = time() + 518400;
$start_month = date('m', time());
$start_day = date('d', time());
$end_month = date('m', $end);
$end_day = date('d', $end);

//get records
if(!$rs = mysql_query(&quot;SELECT person_name, person_surname, person_birthdate, person_department FROM php_birthday_list WHERE MONTH(person_birthdate) &gt;= $start_month AND MONTH(person_birthdate) &lt;= $end_month AND DAYOFMONTH(person_birthdate) &gt;= $start_day AND DAYOFMONTH(person_birthdate) &lt;= $end_day ORDER BY MONTH(person_birthdate), DAYOFMONTH(person_birthdate), person_surname, person_name, person_department&quot;)) {
	echo &quot;&lt;p&gt;&lt;strong&gt;There was an error parsing the query.&lt;/strong&gt;&lt;/p&gt;n&quot;;
}
//no records found
elseif(mysql_num_rows($rs) == 0) {
	echo &quot;&lt;p&gt;&lt;strong&gt;No staff birthdays this week.&lt;/strong&gt;&lt;/p&gt;n&quot;;
}
else {
	echo &quot;&lt;p&gt;Option 2: Today and six days hence; also shows only birth month and day&lt;/p&gt;n&quot;;
	//output birthdays
	echo &quot;&lt;table class=&quot;bordered&quot; cellspacing=&quot;0&quot;&gt;n&quot;;
	echo &quot;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Birthday&lt;/th&gt;&lt;th&gt;Department&lt;/th&gt;&lt;/tr&gt;n&quot;;
	while($row = mysql_fetch_array($rs)) {
		echo &quot;&lt;tr&gt;&quot;;
		echo &quot;&lt;td&gt;$row[person_name] $row[person_surname]&lt;/td&gt;&quot;;
		echo &quot;&lt;td&gt;&quot; . date('F j', strtotime($row['person_birthdate'])) . &quot;&lt;/td&gt;&quot;;
		echo &quot;&lt;td&gt;$row[person_department]&lt;/td&gt;&quot;;
		echo &quot;&lt;/tr&gt;n&quot;;
	}
	echo &quot;&lt;/table&gt;&lt;br /&gt;n&quot;;
}
</pre>
<p>And that&#8217;s all there is to the traditional, server-side approach to this problem. You can see a working demo here:</p>
<p><a href="http://www.dougv.com/demo/php_birthday_list/index.php">http://www.dougv.com/demo/php_birthday_list/index.php</a></p>
<p><strong>The JavaScript Approach</strong></p>
<p>You might ask yourself, &#8220;Why should I waste valuable server CPU cycles and memory to output something so simple? Why not make the client&#8217;s Web browser do the work?&#8221; So long as you don&#8217;t need to make frequent changes to your employee list, and your employee list isn&#8217;t hundreds or thousands of entries long (making it a management nightmare), you can &#8212; and, probably, should &#8212; make the client&#8217;s Web browser do the heavy lifting.</p>
<p>Via DOM scripting, we can add rows and cells to an otherwise empty table, for each and every employee with a birthday this week. Not only that, we can even default the table to say there are no birthdays, and remove that default message if we do, indeed, have birthdays to display.</p>
<p>Let&#8217;s start with the HTML for the table, which will take the unique ID &#8220;birthdays&#8221;:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;table id=&quot;birthdays&quot; class=&quot;bordered&quot; cellspacing=&quot;0&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Birthday&lt;/th&gt;&lt;th&gt;Age&lt;/th&gt;&lt;th&gt;Department&lt;/th&gt;
        &lt;tr&gt;&lt;td colspan=&quot;4&quot;&gt;No birthdays this week!&lt;/td&gt;&lt;/tr&gt;
    &lt;/tr&gt;
&lt;/table&gt;
</pre>
<p>Nothing all that special there. But there&#8217;s some heavy lifting to be done in JavaScript.</p>
<p><strong>The Person Class</strong></p>
<p>First, we need to create a simple Person object which can accept a name, surname, birthdate and department.</p>
<p>Why an object? We could use a two-dimensional array; first dimension being employee number, second dimension being each of those attributes.</p>
<p>An object, however, makes things neater and easier to address. Each named property is easy to call; there&#8217;s conformity to the way each Person is created, as well. This is going to make it easier for us to code, and the code more easy to understand for people who are looking at it.</p>
<p>In JavaScript, classes (aka objects) are declared by creating a function with the name of the class you want to create, and by using the reserved word this to assign properties and methods to the class. (Our Person class will only have properties.)</p>
<pre class="brush: jscript; title: ; notranslate">
function Person(name, surname, birthday, department) {
	//object representing an employee
	this.name = name;
	this.surname = surname;
	this.birthday = birthday;
	this.department = department;
}
</pre>
<p><strong>The employee Array</strong></p>
<p>Now that we have a class which will make every employee record we work with nice and neat, we need to add all our employees to a global array. We&#8217;re using a global array of employees because it&#8217;s convenient, and since the entire script relies on this array to work, it&#8217;s appropriate to scope the array globally. (For more of an understanding about variable scope, see my blog entry titled, &#8220;<a href="http://www.dougv.com/2006/12/18/variable-scope-made-simple/">Variable Scope Made Simple</a>.&#8221;</p>
<p>The way we&#8217;ll add employees to that global array is via a function called createEmployeeList(). All it does is push onto the end of the employees array a new Person object, one for each employee on the payroll.</p>
<pre class="brush: jscript; title: ; notranslate">
//declare global array of employees
var employees = new Array();

function createEmployeeList() {
	//add employees to global employees array
	employees.push(new Person('Laura', 'Miller', new Date('March 21, 1982'), 'Accounts Payable'));
	employees.push(new Person('Page', 'Rockwell', new Date('May 10, 1951'), 'Warehouse'));
	employees.push(new Person('Tom', 'Jones', new Date('May 10, 1984'), 'Mainenance'));
	employees.push(new Person('Richard', 'Gingras', new Date('May 11, 1946'), 'Administration'));
	employees.push(new Person('Joan', 'Walsh', new Date('May 11, 1973'), 'Administration'));
	employees.push(new Person('Norman', 'Blashka', new Date('May 12, 1953'), 'Mainenance'));
	employees.push(new Person('Kerry', 'Lauerman', new Date('May 13, 1967'), 'Mainenance'));
	employees.push(new Person('Joy', 'Press', new Date('May 14, 1969'), 'Accounts Payable'));
	employees.push(new Person('Jeanne', 'Carstensen', new Date('May 15, 1990'), 'Accounts Payable'));
	employees.push(new Person('Ruth', 'Henrich', new Date('May 16, 1981'), 'Mainenance'));
	employees.push(new Person('Wendy', 'Williams', new Date('May 17, 1992'), 'Accounts Payable'));
}
</pre>
<p>Note that one compromise we have to make in JavaScript, versus the traditional PHP / MySQL approach, is that records must be listed in the order of birth date; specifically, by month, day and year. In other words, all the Jan. 1 birthdays must be listed first; of all the Jan. 1 birthdays, the one in 1931 must be listed before the one in 1978.</p>
<p>That&#8217;s assuming you want to order your results by date; in other words, you want birthdays appearing today to come first, birthdays tomorrow second, birthdays two days from now third, etc.; and you want older people listed before younger people. If you want your list ordered some other way &#8212; say, by last name, department, etc. &#8212; that&#8217;s the order they should appear in the list.</p>
<p>If we were using a supporting technology such as <a href="http://code.google.com/apis/gears/api_database.html">Google Gears Database</a>, we wouldn&#8217;t face this problem; we&#8217;d simply offload the employee list to the client and sort it as we would with a traditional SQL query (or, more specifically, a SQLite query).</p>
<p>I don&#8217;t want to delve into Google Gears too deeply in this entry, but assuming I ever get around to working on the <a href="http://www.gulfofmainewrecks.com">Gulf Of Maine Wrecks</a> Web site again, Gears will feature prominently, and there is where I will blog about using it.</p>
<p><strong>The listBirthdays() Function</strong></p>
<p>With an array of employees at our disposal, we can now get down to the nitty-gritty: Showing employees with a current birthday in our table.</p>
<p>The approach is the same as the one used in our PHP script. We get today&#8217;s date; from that, figure out the Sunday and Saturday of the current week; then iterate through the entire array of employees, looking for those who have a birthday with a month and day that fall between Sunday and Saturday.</p>
<p>For each employee that has a birthday this week, we add a new row to the table, then a cell for the name, birth month / day, age and department of that employee. We keep track of which row we&#8217;re adding via a counter, named x, which begins at index 2 (that is, row 3).</p>
<p>We start at row 3 because our table has two rows: A header row (1) and a row that says there aren&#8217;t any current birthdays (2). If we encounter at least one birthday this week, we set the value of a Boolean named ok to true (its initial value is false).</p>
<p>After we&#8217;re all done iterating the records, if the value of ok is true, we tell the table to remove row 2 &#8212; that is, the row that says there are no current birthdays.</p>
<pre class="brush: jscript; title: ; notranslate">
function listBirthdays() {
	//get birthday list table
	var table = document.getElementById('birthdays');

	//set today's date
	//comment out declaration below and use this for production runs
	//var today = new Date();

	//for demo purposes, I'm using May 12 as the date
	//use the code above instead of this line
	var today = new Date('May 12, 2009');

	//set Sunday
	var sun = new Date();
	sun.setTime(today.getTime() - (86400000 * today.getDay()));

	//set Saturday
	var sat = new Date();
	sat.setTime(today.getTime() + (86400000 * (6 - today.getDay())));

	//declare table row counter; index begins at 2 to accommodate header row and no birthdays message
	var x = 2;

	//boolean to check if any birthdays found for this week
	var ok = false;

	//iterate employee array
	for(var i = 0; i &lt; employees.length; i++) {
		//if birthday exists this week ...
		if(employees[i].birthday.getMonth() &gt;= sun.getMonth() &amp;&amp; employees[i].birthday.getMonth() &lt;= sat.getMonth() &amp;&amp; employees[i].birthday.getDate() &gt;= sun.getDate() &amp;&amp; employees[i].birthday.getDate() &lt;= sat.getDate()) {
			//change birthday found boolean to true if it is false
			if(!ok) {
				ok = true;
			}
			//add row to table for employee
			var row = table.insertRow(x);
			//name column
			var name = row.insertCell(0);
			name.innerHTML = employees[i].name + ' ' + employees[i].surname;
			//birthday column
			var birthday = row.insertCell(1);
			birthday.innerHTML = monthName(employees[i].birthday.getMonth()) + ' ' + employees[i].birthday.getDate();
			//age column
			var age = row.insertCell(2);
			age.innerHTML = Math.floor((today.getTime() - employees[i].birthday.getTime()) / 31536000000);
			//department column
			var dept = row.insertCell(3);
			dept.innerHTML = employees[i].department;
			//iterate row counter
			x++;
		}
	}
	//remove no birthdays message if birthdays found
	if(ok) {
		table.deleteRow(1);
	}
}
</pre>
<p><strong>Final JavaScript Functions</strong></p>
<p>To complete the JavaScript version, we need two more functions. The first is monthName(), which takes an integer argument and returns a text value corresponding to the numeric value of the month indicated. (In JavaScript, the <a href="http://www.w3schools.com/jsref/jsref_getMonth.asp">getMonth() method</a> of <a href="http://www.w3schools.com/jsref/jsref_obj_date.asp">the Date object</a> returns an integer from 0-11, where January is 0 and December, 11.)</p>
<pre class="brush: jscript; title: ; notranslate">
function monthName(month) {
	//return text name for month numeric value
	switch(month) {
		case 0:
			return 'Jan.';
			break;
		case 1:
			return 'Feb.';
			break;
		case 2:
			return 'March';
			break;
		case 3:
			return 'April';
			break;
		case 4:
			return 'May';
			break;
		case 5:
			return 'June';
			break;
		case 6:
			return 'July';
			break;
		case 7:
			return 'Aug.';
			break;
		case 8:
			return 'Sept.';
			break;
		case 9:
			return 'Oct.';
			break;
		case 10:
			return 'Nov.';
			break;
		case 11:
			return 'Dec.';
			break;
		default:
			return 'Undefined';
	}
}
</pre>
<p>Finally, we need to create a function we can call with the onload event, because we need to trigger two functions: createEmployeeList() and listBirthdays(). (I could have combined these functions into one, or called createEmployeeList() from listBirthdays(), but the two functions really do two different things, and I believe elegance dictates keeping them separate.)</p>
<pre class="brush: jscript; title: ; notranslate">
function pageLoad() {
	//on page load, bind employee list, show birthdays
	createEmployeeList();
	listBirthdays();
}
</pre>
<p><strong>Invoking The JavaScript</strong></p>
<p>To get the whole thing to work, we simply make pageLoad() the onload event for the body tag:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;body onload=&quot;pageLoad()&quot;&gt;
</pre>
<p>(Technically, we could simply use the window.onload event handler in JavaScript, but I find that doesn&#8217;t always work well in every browser; I prefer to call onload events via the body tag.)</p>
<p>And that&#8217;s all there is to it. You can see a working demo here:</p>
<p><a href="http://www.dougv.com/demo/php_birthday_list/javascript.html">http://www.dougv.com/demo/php_birthday_list/javascript.html</a></p>
<p>You can download both scripts here: <a href='http://www.dougv.com/wp-content/uploads/2009/05/php_birthday_list.zip'>Using JavaScript To Perform A Task Traditionally Solved With Server-Side Scripting Demo Code</a>. I distribute code under the GNU GPL version 3.</p>
<p>All links in this post on delicious: <a href="http://delicious.com/dhvrm/using-javascript-to-perform-a-task-traditionally-solved-with-server-side-scripting">http://delicious.com/dhvrm/using-javascript-to-perform-a-task-traditionally-solved-with-server-side-scripting</a></p>
<p><em>Special thanks to <a href="http://www.salon.com/about/staff/">Salon.com for the staff list</a>, which provided most of the names used in this demo.</em></p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2007/10/17/printing-sections-of-a-web-page-using-divs-and-javascript-remote-scripting/" rel="bookmark">Printing Sections Of A Web Page Using DIVs And JavaScript Remote Scripting</a> (21.7)</li>
				<li><a href="https://www.dougv.com/2008/11/08/cleaning-up-some-php-and-incorporating-a-javascript-based-image-preview/" rel="bookmark">Cleaning Up Some PHP And Incorporating A JavaScript-Based Image Preview</a> (12.8)</li>
				<li><a href="https://www.dougv.com/2007/01/01/using-php-mysql-to-store-a-form-value-calculated-via-javascript-dom/" rel="bookmark">Using PHP / MySQL To Store A Form Value Calculated Via JavaScript / DOM</a> (10.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2009/05/13/using-javascript-to-perform-a-task-traditionally-solved-with-server-side-scripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Trouble With PHP&#8217;s Weak Data Types: An Example Examined And Explained</title>
		<link>https://www.dougv.com/2008/11/02/the-trouble-with-phps-weak-data-types-an-example-examined-and-explained/</link>
		<comments>https://www.dougv.com/2008/11/02/the-trouble-with-phps-weak-data-types-an-example-examined-and-explained/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 05:23:40 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[data types]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=1162</guid>
		<description><![CDATA[Asked recently on Yahoo! Answers: Multiple nested MySQL functions in PHP? I was going through code today, trying to make some things more compact. The application worked without problems, so I knew that mysql error statements were superfluous. This is the type of statement I was changing, I figured that I&#8217;d remove the seemingly unnecessary [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/22/objects-classes-explained-in-very-simple-terms/" rel="bookmark">Objects (Classes) Explained In Very Simple Terms</a> (18.5)</li>
				<li><a href="https://www.dougv.com/2006/12/01/the-difference-between-data-adapters-data-sets-and-data-readers-in-plain-english/" rel="bookmark">The Difference Between Data Adapters, Data Sets And Data Readers, In Plain English</a> (16.9)</li>
				<li><a href="https://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/" rel="bookmark">The Difference Between Null, Empty And Zero-Length Data / Strings</a> (14.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>Asked recently on Yahoo! Answers:</p>
<blockquote><p>
<strong><a href="http://answers.yahoo.com/question/index?qid=20081101190128AAxSL6f">Multiple nested MySQL functions in PHP?</a></strong></p>
<p>I was going through code today, trying to make some things more compact. The application worked without problems, so I knew that mysql error statements were superfluous.</p>
<p>This is the type of statement I was changing, I figured that I&#8217;d remove the seemingly unnecessary $result2 variable</p>
<pre class="brush: php; title: ; notranslate">
$result2 = mysql_query($carts) or die(mysql_error());&lt;br /&gt;
while ($row2 = mysql_fetch_array($result2)) {&lt;br /&gt;
	echo &quot;&lt;option&gt;$row2[0]&lt;/option&gt;&quot;;&lt;br /&gt;
}
</pre>
<p>so this is what I changed it into (I basically replaced where it said $result2, to what $result2 had contained, and removed the error check)</p>
<pre class="brush: php; title: ; notranslate">
while ($row2 = mysql_fetch_array(mysql_query($carts))) {&lt;br /&gt;
	echo &quot;&lt;option&gt;$row2[0]&lt;/option&gt;&quot;;&lt;br /&gt;
}
</pre>
<p>but this code returned infinite loops, much to my surprise. Why is it doing this? is there a way around it?
</p></blockquote>
<p>Recently, I wrote about how PHP&#8217;s weak data types often can lead to problems for new programmers who don&#8217;t understand <a href="http://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/">the difference between null, empty and zero-length variables</a>. Here&#8217;s another opportunity to expose why strong data typing is essential for best programming practices, and to show how PHP&#8217;s weak data types &#8212; normally, a source of comfort for beginning programmers &#8212; can be the source of extensive frustration.</p>
<p><span id="more-1162"></span></p>
<p>Let&#8217;s look at the first block of code, which was to be &#8220;cleaned up&#8221; by this questioner:</p>
<pre class="brush: php; title: ; notranslate">
$result2 = mysql_query($carts) or die(mysql_error());
while ($row2 = mysql_fetch_array($result2)) {
	echo &quot;&lt;option&gt;$row2[0]&lt;/option&gt;&quot;;
}
</pre>
<p>The code here is straightforward. Somewhere prior to this block, the questioner connected to a database server and selected a database. Now, he wants to populate a select with the results set from a SELECT query (stored in a variable named $carts).</p>
<p>Let&#8217;s examine each line:</p>
<ol>
<li><a href="http://us3.php.net/manual/en/function.mysql-query.php">mysql_query(</a>) instructs a connected MySQL database server to execute the specified query and return a <a href="http://us3.php.net/manual/en/language.types.resource.php">resource</a> or boolean, depending on the type of query run and any errors encountered by the function. In this case, assuming the database server does not encounter an error, a result resource will be returned.</li>
<li><a href="http://us3.php.net/manual/en/function.mysql-fetch-array.php">mysql_fetch_array()</a> takes the result returned by the query, instructs the database server to populate the noted array variable with the contents of the current row, and to advance the internal pointer in the result to the next row. while() instructs this process to continue until the internal row pointer of the resource reaches the end of the result.</li>
<li>The echo statement outputs a new option element to the page, setting as its value the value of the first cell of the $row2 array.</li>
</ol>
<p>Grab some data, use it as the value(s) for some element(s) on the page. This is known as <em>data binding</em>, and it&#8217;s as routine a task as Web programming allows.</p>
<p>But in the process of data binding with PHP&#8217;s built-in functions, we actually work with several unmentioned objects and data types, which would have been a lot more transparent had we used a more structured programming language.</p>
<h4>How Data Binding Works In Strongly Typed Languages</h4>
<p>Bear with me for a moment while I show how the code block above would be different if we used a more strongly typed, more object-oriented programming language to accomplish the same task.</p>
<p>For example, if I want to populate a select list in ASP.NET from a database, I might declare a DropDownList control on my page, and use a SQLDataSource control to populate it:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;asp:DropDownList runat=&quot;server&quot; ID=&quot;MyDropDown&quot; DataSourceID=&quot;MyDataSource&quot; DataTextField=&quot;some_column&quot; DataValueField=&quot;some_other_column&quot; /&gt;
&lt;asp:SqlDataSource runat=&quot;server&quot; ID=&quot;MyDataSource&quot; SelectCommand=&quot;SELECT * FROM some_table&quot; ConnectionString=&quot;&lt;%$ ConnectionStrings:MyNorthwind%&gt;&quot; /&gt;
</pre>
<p>This level of abstraction hides from me all the objects and data types I might otherwise need to explicitly declare in order to add option elements to a select in ASP.NET. (In other words, it works like PHP in terms of writing it, because I don&#8217;t need to concern myself with data types or other pesky technical details; ASP.NET, like PHP, takes care of that for me.)</p>
<p>Actually, it&#8217;s better than PHP, because I am not writing control loops or working with things like result resources; I simply plug in some parameters and ASP.NET does the grunt work for me. This is <em>abstraction</em> at the height of its power.</p>
<p>An alternative approach in ASP.NET would be to use a subroutine to bind data from the query to a DropDownList control. If I wanted to do that, I would first declare a DropDownList control:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;asp:DropDownList runat=&quot;server&quot; ID=&quot;MyDropDown&quot;  /&gt;
</pre>
<p>Then, in my code behind / server script block, I would declare all the data types and variables needed to actually connect to, and extract from, a database server the records I want:</p>
<pre class="brush: vb; title: ; notranslate">
Imports System.Data
Imports System.Data.SqlClient

Sub Page_Load(Sender As Object, E As EventArgs) Handles Me.Load
	If Not Page.IsPostBack Then
		MyDropDown_dataBind()
	End If
End Sub

Sub MyDropDown_dataBind()
	Dim objConn As New SqlConnection(&quot;My Connection String&quot;)
	Dim objCmd As New SqlCommand(&quot;SELECT * FROM table&quot;, objConn)

	Try
		objConn.Open()
		Dim objReader As SqlDataReader = objCmd.ExecuteReader()

		If objReader.HasRows Then
			MyDropDown.DataSource = objReader
			MyDropDown.DataTextField = &quot;some_column&quot;
			MyDropDown.DataValueField = &quot;some_other_column&quot;
			MyDropDown.DataBind()
		Else
			MyDropDown.Items.Insert(0, New ListItem(&quot;No records returned!&quot;))
		End If

		objConn.Close()
	Catch Ex As Exception
		MyDropDown.Items.Insert(0, New ListItem(&quot;There was a database error getting the records: &quot; &amp; Ex.Message))
	Finally
		objCmd.Dispose()
		objConn.Dispose()
	End Try
End Sub
</pre>
<p>Notice that the code above is far more explicit and complex than the previous code blocks. It employs several classes: SqlConnection, SqlCommand, SqlDataReader, DropDownList (referenced by calling MyDropDown), ListItem and Exception, to name several. Each of these classes are their own data types, and each employs primitive types, such as integers and strings, or even each other, as properties and / or arguments for methods they employ.</p>
<p>Strong typing means knowing exactly what you&#8217;re working with as you program. Abstraction, when done to the extent ASP.NET provides, means not having to worry one bit about what you&#8217;re working with.</p>
<p>PHP&#8217;s approach fits somewhere in the middle: You don&#8217;t really need to know what you&#8217;re working with, but not knowing can cause lots of trouble.</p>
<h4>What&#8217;s Wrong With The Second Code Block</h4>
<p>Let&#8217;s look now at the second code block and sort out its troubles.</p>
<pre class="brush: php; title: ; notranslate">
while ($row2 = mysql_fetch_array(mysql_query($carts))) {
	echo &quot;&lt;option&gt;$row2[0]&lt;/option&gt;&quot;;&lt;br /&gt;
}
</pre>
<p>Line 1 accomplishes several tasks, which we will evaluate from the right to the left, since that&#8217;s the order PHP will use:</p>
<ul>
<li>We query the database; again, a mysql result resource is returned on success.</li>
<li>We read the first line of that result into an array named $row2 The internal record pointer of the result resource is advanced to the next record.</li>
<li>We repeat the process due to the while loop.</li>
</ul>
<p>In other words, so long as the query always returns at least one record, the while condition is always satisfied, so the loop never stops executing. It just keeps spitting out the first record of the results set, over and over again.</p>
<p>The while condition always evaluates to true because the structure of the code does not consider how a result resource works. And that, in large part, is the fault of PHP&#8217;s weak data types.</p>
<p>When mysql_query() returns a result resource, what it&#8217;s really doing is telling the database server to hold, in the database server&#8217;s memory, the records requested.</p>
<p>The resource returned by the MySQL server isn&#8217;t itself an PHP variable, the way a string or integer is; it&#8217;s a reference PHP uses to tell the database server, &#8220;Remember the records I asked for with that query? The ones you bookmarked with the value stored in this reference? I want you to work with those records.&#8221;</p>
<p>Looking again at the questioner&#8217;s first code block:</p>
<pre class="brush: php; title: ; notranslate">
$result2 = mysql_query($carts) or die(mysql_error());
while ($row2 = mysql_fetch_array($result2)) {
	echo &quot;&lt;option&gt;$row2[0]&lt;/option&gt;&quot;;
}
</pre>
<ul>
<li>In Line 1, $carts is the string we will pass as a query; e.g., &#8220;SELECT * FROM table&#8221;. $carts is an internal variable &#8212; that is, a variable that exists within PHP itself, which PHP can manipulate directly.</li>
<li>In Line 1, $result2 is a resource. In this case, it will be a result, which is a reference (or a kind of bookmark) that MySQL gives to PHP after MySQL sets aside, in its memory, the records we requested. PHP doesn&#8217;t have these records; they remain on the database server. Whenever PHP wants to work with those records, it sends the reference (bookmark) held in $result2 back to MySQL, and MySQL gets, from its memory, the records referenced (bookmarked) by that PHP variable. That makes $result2 an external variable; PHP does not directly work with the information contained in $result2, but uses it to tell MySQL to perform tasks on its behalf.</li>
<li>Line 2 instructs MySQL to send, to PHP, the current record referenced by $result2&#8242;s row poiner (more on that in a moment). Once MySQL sends that record, PHP assigns that record&#8217;s columns to an associative array named $row2. In this case, PHP uses the external variable $result2 to remind MySQL which set of records PHP wants, and to tell MySQL to send to PHP information it can assign to an internal variable, $row2.</li>
<li>When PHP asks MySQL to send the information it assigned to $row2, it also tells MySQL to advance the row pointer to the next record in the result resource. The row pointer, which is part of the result resource, is how MySQL knows where PHP left off when it last worked with the records in the result resource. Because advancing the row pointer happens silently &#8212; that is, MySQL does this implicitly, as part of its mysql_fetch_array() tasks; you don&#8217;t explicitly command MySQL to advance the row pointer &#8212; it&#8217;s easy to forget about the row pointer altogether.</li>
</ul>
<h4>Inefficient, Inelegant, But By Design</h4>
<p>So, how do we achieve the efficiency desired by this questioner?</p>
<p>In short, we don&#8217;t. By design, PHP requires a fairly verbose process to bind data to a page or HTML element; there&#8217;s really no more efficient manner of going about it. In fact, the block below is about as compact as it gets when binding option elements to a select, using only PHP&#8217;s built-in functions:</p>
<pre class="brush: php; title: ; notranslate">
&lt;select id=&quot;myselect&quot; name=&quot;myselect&quot;&gt;
&lt;?php
	$link = mysql_connect(&quot;host&quot;, &quot;user&quot;, &quot;pass&quot;) or die(&quot;cannot connect to db server&quot;);
	mysql_select_db(&quot;dbname&quot;) or die(&quot;cannot select database&quot;);
	$rs = mysql_query(&quot;SELECT * FROM table&quot;) or die(&quot;cannot parse query&quot;);
	while($row = mysql_fetch_array($rs)) {
		echo &quot;&lt;option&gt;$row[0]&lt;/option&gt;&quot;;
	}
?&gt;
&lt;/select&gt;
</pre>
<p>If you have lots and lots of controls to bind in the same way, you might consider using a class. Among the benefits of a class, as we have seen in the past, is that we can reuse code for similar tasks.</p>
<p>Below is a class, named optionMaker, that takes as its constructor arguments a database query and link resource, respectively; its public method, makeOptions(), spits out option elements from the resulting record set.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class optionMaker {
	public $link, $query;
	private $rs, $row;

	function __construct($q, $l) {
		$this-&gt;query = $q;
		$this-&gt;link = $l;
		$this-&gt;getResults();
	}

	private function getResults() {
		if(!$this-&gt;rs = mysql_query($this-&gt;query, $this-&gt;link)) {
			unset($this-&gt;rs);
		}
		elseif(mysql_num_rows($this-&gt;rs) == 0) {
			unset($this-&gt;rs);
		}
	}

	public function makeOptions() {
		if(!is_null($this-&gt;rs)) {
			while($this-&gt;row = mysql_fetch_array($this-&gt;rs)) [
				echo &quot;&lt;option&gt;&quot; . $this-&gt;row[0] . &quot;&lt;/option&gt;n&quot;;
			}
		}
		else {
			echo &quot;&lt;option&gt;No matching records or database error getting records&lt;/option&gt;n&quot;;
		}
	}
}
?&gt;
</pre>
<p>Note that this class isn&#8217;t very secure; it doesn&#8217;t check if the $link resource is valid, for example; it doesn&#8217;t sanitize the SQL it is sent; it will pass UPDATE, DELETE, DROP or other possibly harmful queries along. While these security holes shouldn&#8217;t be of major concern &#8212; presumably, you wouldn&#8217;t poison your own well by sending bad parameters to this class &#8212; it&#8217;s always best to secure your applications against unintended uses and attacks. <em>Use this at your own risk.</em></p>
<p>(Herein lies another benefit of object-oriented languages: In ASP.NET, there are a number of ways to prevent controls from sending potentially harmful queries to a database, sanitize input, etc. with little or no extra coding, compared to PHP.)</p>
<p>The easiest way to use the class above is to save it to a php file; call it optionMaker.php. Then, include that PHP file wherever you want to use it. Your use of the class to populate three select elements might look like this:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
&lt;?php
require_once(&quot;optionMaker.php&quot;);
$link = mysql_connect(&quot;server&quot;, &quot;user&quot;, &quot;pass&quot;) or die(&quot;cannot connect to db server&quot;);
mysql_select_db(&quot;dbname&quot;) or die(&quot;cannot select database&quot;);
?&gt;

&lt;select id=&quot;select1&quot; name=&quot;select1&quot;&gt;
&lt;?php
$options1 = new optionMaker(&quot;SELECT column1 FROM table1&quot;, $link);
$options1-&gt;makeOptions();
?&gt;
&lt;/select&gt;

&lt;select id=&quot;select2&quot; name=&quot;select2&quot;&gt;
&lt;?php
$options2 = new optionMaker(&quot;SELECT column1 FROM table2 WHERE column2 = 'foo'&quot;, $link);
$options2-&gt;makeOptions();
?&gt;
&lt;/select&gt;

&lt;select id=&quot;select3&quot; name=&quot;select3&quot;&gt;
&lt;?php
$options3 = new optionMaker(&quot;SELECT a.column1 FROM table3 AS a LEFT JOIN table4 AS b ON a.id = b.foreign_key WHERE b.column1 = 'foo' AND b.foreign_key IS NOT NULL&quot;, $link);
$options3-&gt;makeOptions();
?&gt;
&lt;/select&gt;
</pre>
<p>If the database server can&#8217;t parse the query you supply, or if the query returns no records, the class simply nulls out the result resource returned by the database server; the makeOptions() method, in turn, returns a single option, noting the problem, if the result resource is null. (Strong typing, once again, solves a problem: What happens if the class has errors or no results? By using null, we escape such situations gracefully, and provide useful feedback to the user.)</p>
<p>Note also that this class will always use only one column &#8212; the first column in a successful result resource &#8212; as the value of the option elements it outputs.</p>
<p>I distribute all code under the GNU GPL version 3.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/22/objects-classes-explained-in-very-simple-terms/" rel="bookmark">Objects (Classes) Explained In Very Simple Terms</a> (18.5)</li>
				<li><a href="https://www.dougv.com/2006/12/01/the-difference-between-data-adapters-data-sets-and-data-readers-in-plain-english/" rel="bookmark">The Difference Between Data Adapters, Data Sets And Data Readers, In Plain English</a> (16.9)</li>
				<li><a href="https://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/" rel="bookmark">The Difference Between Null, Empty And Zero-Length Data / Strings</a> (14.4)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/data-types/" title="data types" rel="tag">data types</a>, <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2008/11/02/the-trouble-with-phps-weak-data-types-an-example-examined-and-explained/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The Difference Between Null, Empty And Zero-Length Data / Strings</title>
		<link>https://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/</link>
		<comments>https://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 20:13:43 +0000</pubDate>
		<dc:creator>Doug Vanderweide</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[elegance]]></category>
		<category><![CDATA[objects and classes]]></category>

		<guid isPermaLink="false">http://www.dougv.com/blog/?p=1109</guid>
		<description><![CDATA[A common problem faced by new programmers is understanding the difference between null, empty and zero-length variables, especially when working with database records. While, for most intents and purposes, the three things have the same effect &#8212; either you have some data you can work with, or you don&#8217;t &#8212; they arise from different circumstances. [...]<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/01/the-difference-between-data-adapters-data-sets-and-data-readers-in-plain-english/" rel="bookmark">The Difference Between Data Adapters, Data Sets And Data Readers, In Plain English</a> (27.2)</li>
				<li><a href="https://www.dougv.com/2006/12/08/a-simple-calendar-page-to-display-date-specific-data-in-php/" rel="bookmark">A Simple Calendar Page To Display Date-Specific Data In PHP</a> (10.5)</li>
				<li><a href="https://www.dougv.com/2007/07/13/getting-plain-text-from-an-aspnet-20-page-for-use-as-an-ajax-data-source/" rel="bookmark">Getting Plain Text From An ASP.NET 2.0 Page For Use As An AJAX Data Source</a> (9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.
	</div>
]]></description>
			<content:encoded><![CDATA[<p>A common problem faced by new programmers is understanding the difference between null, empty and zero-length variables, especially when working with database records.</p>
<p>While, for most intents and purposes, the three things have the same effect &#8212; either you have some data you can work with, or you don&#8217;t &#8212; they arise from different circumstances. Understanding how null, empty and zero-length are different can help you avoid data errors in your programs.</p>
<p>The short version is this: If a variable simply doesn&#8217;t exist &#8212; usually because it hasn&#8217;t been declared, but sometimes because it hasn&#8217;t been assigned a value &#8212; it&#8217;s null. If the variable exists but contains no data, it&#8217;s empty. And if a structured data variable, such as an array, exists but doesn&#8217;t contain any items, it&#8217;s zero-length.</p>
<p>An analogy is in order.</p>
<p>Think of a database as a house. A house has rooms, and in each of these rooms are furniture and accessories that are appropriate to that room.</p>
<p>For example, the kitchen has a stove, refrigerator and sink. The bedroom has a dresser, bed and armoire. The living room has a couch, television and coffee table.</p>
<p><span id="more-1109"></span></p>
<h4>Where&#8217;s The Fridge?</h4>
<p>Let&#8217;s refocus the analogy. We&#8217;ll liken a database table to your kitchen, and the refrigerator as a column in that table.</p>
<p>As a general rule, refrigerators hold food. What specific food is in there doesn&#8217;t really matter, so long as it&#8217;s food. (I know the fridge doesn&#8217;t hold every kind of food and often contains non-food items. Bear with me, please, and just accept for the purpose of the analogy that a fridge holds food.)</p>
<p>That&#8217;s much like the way a database column works. For example, a column might be a VARCHAR(50). The column doesn&#8217;t care what you are storing in it; it only cares that you are storing text that is not longer than 50 characters.</p>
<p>But let&#8217;s suppose you just bought a house (i.e., you are creating a new database table). There is a kitchen, but the old owners took the refrigerator and left the stove.</p>
<p>There&#8217;s a space where the refrigerator used to be. But there&#8217;s no refrigerator there. That&#8217;s null.</p>
<p>In other words, just because you&#8217;ve set aside some space where the refrigerator ought to be, and just because you say to visitors, &#8220;the fridge is going to be right over there,&#8221; that doesn&#8217;t make one magically appear.</p>
<p>It&#8217;s the same thing with database columns (and, for what that&#8217;s worth, all scalars [i.e., variables]). Declaring that you intend to have data at some point doesn&#8217;t mean there is data. And when there&#8217;s no data, you get a null.</p>
<p>Let&#8217;s bring the analogy back around. You have a database table called <em>kitchen.</em> In <em>kitchen</em> is a column named <em>refrigerator</em>, and refrigerator will hold <em>food</em> data.</p>
<p>When you first create the <em>refrigerator</em> column in your database, you&#8217;ve basically said, &#8220;I will eventually have some food, and I will need to put it someplace, and that place will be a fridge, which will go right there.&#8221; But until you actually get around to all that, there is no fridge.</p>
<p>Basically, the database says, &#8220;I know that&#8217;s where you want to put the fridge. But until you get one, that&#8217;s just a void space.&#8221;</p>
<p>So there is no fridge. Or, in programming parlance, it&#8217;s null.</p>
<h4>Nothing From Nothing Means Nothing; You Gotta Have Something &#8230;</h4>
<p>You can&#8217;t get blood from a turnip, especially when you don&#8217;t even have a turnip. The same is true of nulls. Null isn&#8217;t zero; it&#8217;s nonexistence.</p>
<p>If you ask me, &#8220;How big is your swimming pool?,&#8221; I can&#8217;t answer that question; I don&#8217;t have a swimming pool. Never have, probably never will.</p>
<p>I can&#8217;t say a nonexistent swimming pool has zero size. I can&#8217;t say it&#8217;s infinite or infinitesimal, either. The largest and smallest possible measures are still measures, and you can&#8217;t quantify things that don&#8217;t exist.</p>
<p>That&#8217;s why nulls cause so much trouble for new programmers. They write their programs with the presumption that the data they are referencing actually exists.</p>
<p>Consider our house database again, with its kitchen table (no pun intended). Let&#8217;s suppose I&#8217;m baking cookies in the stove and washing dishes in the sink, but I don&#8217;t have a fridge. The one record in the table might look like this:</p>
<table style="border: 1px solid #000;" border="0" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<th style="font-size: 12px; background-color: #ff0; font-weight: bold; text-align: center; border: 1px solid #000;">Column</th>
<th style="font-size: 12px; background-color: #ff0; font-weight: bold; text-align: center; border: 1px solid #000;">Value</th>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">stove</td>
<td style="font-size: 12px; border: 1px solid #000;">cookies</td>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">sink</td>
<td style="font-size: 12px; border: 1px solid #000;">dishes</td>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">fridge</td>
<td style="font-size: 12px; border: 1px solid #000; background-color: #ccc;"></td>
</tr>
</tbody>
</table>
<p>Let&#8217;s then suppose I want to serve milk with my cookies. I might use this code in VB.NET to tell me if I have milk:</p>
<pre class="brush: vb; title: ; notranslate">
Dim objConn As New SqlConnection(&quot;connection string&quot;)
Dim objCmd As New SqlCommand(&quot;SELECT * FROM kitchen&quot;, objConn)

objConn.Open()
Dim objReader As SqlDataReader = objCmd.ExecuteReader()
If objReader.HasRows() Then
	objReader.Read()
	If objReader(&quot;fridge&quot;) = &quot;milk&quot; Then
		Console.WriteLine(&quot;Cookies and milk! Yummy!&quot;)
	Else
		Console.WriteLine(&quot;There's no milk in the fridge. <img src='https://www.dougv.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> &quot;)
	End If
Else
	Console.WriteLine(&quot;There are no matching records.&quot;)
End If

objConn.Close()
objCmd.Dispose()
objConn.Dispose()
</pre>
<p>Notice this line:</p>
<pre class="brush: vb; title: ; notranslate">If objReader(&quot;fridge&quot;) = &quot;milk&quot; Then</pre>
<p>We are using the equality operator to determine if the value of objReader(&#8220;fridge&#8221;) is an empty string. But remember: there is no fridge.</p>
<p>Asking about what is inside a fridge that doesn&#8217;t exist is far more straightforward to a computer than it is to a person: The database basically says back to you, &#8220;What is this <em>fridge</em> of which you speak?&#8221;</p>
<p>Yet in the average person&#8217;s mind, not having any milk because you don&#8217;t have a fridge is the same thing as not having any milk in a fridge you do have. Either way, no milk.</p>
<p>This touches on the idea of <em>identity</em>, and it&#8217;s a good place to begin describing emptiness.</p>
<h4>I Spit Out Like A Sewer Hole, Yet Still Receive Your Kiss</h4>
<p>Let&#8217;s go back to our house database analogy.</p>
<p>Suppose, even though I don&#8217;t have any food, I decide to go ahead and buy a refrigerator. I put it in the place where I said I was going to put it, but there&#8217;s no food in it.</p>
<p>That&#8217;s emptiness. I have a fridge, but it is empty.</p>
<table style="border: 1px solid #000;" border="0" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<th style="font-size: 12px; background-color: #ff0; font-weight: bold; text-align: center; border: 1px solid #000;">Column</th>
<th style="font-size: 12px; background-color: #ff0; font-weight: bold; text-align: center; border: 1px solid #000;">Value</th>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">stove</td>
<td style="font-size: 12px; border: 1px solid #000;">cookies</td>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">sink</td>
<td style="font-size: 12px; border: 1px solid #000;">dishes</td>
</tr>
<tr>
<td style="font-size: 12px; border: 1px solid #000;">fridge</td>
<td style="font-size: 12px; border: 1px solid #000;"></td>
</tr>
</tbody>
</table>
<p>So, if I go back to line 8 of the example above:</p>
<pre class="brush: vb; title: ; notranslate">If objReader(&quot;fridge&quot;) = &quot;milk&quot; Then</pre>
<p>Visual Basic now knows there is, indeed, a fridge in the kitchen. So if I ask it whether there&#8217;s milk in the fridge, it can go look inside the fridge and see no, there isn&#8217;t.</p>
<p>The difference between null and empty is especially problematic with weakly typed programming languages, such as PHP.</p>
<p>PHP will implicitly assign a null variable an empty value if you use a <a href="http://us2.php.net/manual/en/language.operators.comparison.php">comparison operator</a>, such as == or !=. (In other words, if PHP doesn&#8217;t have a refrigerator, it will automatically conjure one up in order to tell you the fridge is empty, since it figures that&#8217;s what you really want to know.)</p>
<p>That reinforces the idea in some programmers&#8217; minds that null is the same thing as empty. To get around this, one uses PHP&#8217;s identity operators, === and !==.</p>
<p>The identity operator attempts to bring strong typing to the weakly typed data used by PHP. Identity means, in a nutshell, &#8220;are these two variables both equal, and of the same data type?&#8221;</p>
<p>Generally speaking, we can trust PHP to handle automatically converting our data types &#8212; such as changing nulls into empty strings &#8212; so that the comparison operator works 99 percent of the time. But once in a while, we run into a situation where PHP&#8217;s implicit comparisons aren&#8217;t enough, and that&#8217;s when we need to use identity.</p>
<p>This can easily be demonstrated with the <a href="http://us2.php.net/manual/en/function.strpos.php">strpos()</a> function. Ideally, when strpos() does not find the needle in the haystack, it returns the boolean false; when it finds the needle, it returns the position of the needle as an integer.</p>
<p>But sometimes, the value returned by strpos() if the needle isn&#8217;t found will be a value other than false, such as zero (if the needle is found at the beginning of the haystack) or an empty string.</p>
<p>So, we shouldn&#8217;t use the comparison operator ==, because PHP won&#8217;t implicitly cast zero or an empty string as boolean false. Instead, we use the identity operator ===, which basically says, &#8220;are these values equal, and the same type?&#8221; And that, in turn, instructs PHP to explicitly cast each of the variables as a mutual type &#8212; in our case, booleans &#8212; in order to make its comparison.</p>
<p>Consider the example below, which you can <a href="http://www.dougv.com/demo/nullemptyzero/index.php">run for yourself here</a>:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$foo = &quot;Valerie&quot;;
$bar = &quot;V&quot;;

echo &quot;strpos() position of $bar in $foo is: &quot;;
echo strpos($foo, $bar);
echo &quot;&lt;br /&gt;&quot;;

echo &quot;strpos() return value of $bar in $foo is of type: &quot;;
echo gettype(strpos($foo, $bar));
echo &quot;&lt;br /&gt;&quot;;

if(strpos($foo, $bar) == false) {
	echo &quot;strpos() comparison operator says $bar is &lt;strong&gt;not&lt;/strong&gt; in $foo&quot;;
}
else {
	echo &quot;strpos() comparison operator says $bar is in $foo&quot;;
}
echo &quot;&lt;br /&gt;&quot;;

if(false === strpos($foo, $bar)) {
	echo &quot;strpos() identity operator says $bar is &lt;strong&gt;not&lt;/strong&gt; in $foo&quot;;
}
else {
	echo &quot;strpos() identity operator says $bar is in $foo&quot;;
}
echo &quot;&lt;br /&gt;&quot;;
?&gt;
</pre>
<p>(Many thanks to <a href="http://www.programmerskit.com/the-difference-between-and/">Valerie at theprogrammerskit.com</a> for the variables.)</p>
<p>In the example above, strpos() finds &#8220;V&#8221; at the very start of &#8220;Valerie.&#8221; It does this, essentially, by converting &#8220;Valerie&#8221; into an array of characters, then iterating through each until it finds &#8220;V&#8221;. Since all PHP arrays are indexed from 0, strpos() returns 0.</p>
<p>When PHP&#8217;s comparison operator makes an implicit typecast from an integer to a boolean, it considers zero to be false and all other integer values to be be true. So because 0 is false, but it is also the index position of &#8220;V&#8221;, PHP erroneously reports the letter was not found.</p>
<p>However, when we use the identity operator, we are telling PHP, &#8220;First, find the type of the first operand. Next, convert the type of the second operand to be the same as the first. Finally, compare the values.&#8221;</p>
<p>While the implicit casting with the comparison operator makes the integer 0 equal to boolean false, the identity operator equates 0 with true, because it converts data using a different algorithm. (As to the why and how of that, I am not sure, except that PHP developers must have figured out that they needed a way to convert the integer 0 to boolean false, and decided the identity operator would take on that job.)</p>
<p>So, when strpos() returns a zero, PHP knows that it must first explicitly convert zero into a boolean. In this case, it understands zero to be the same as boolean true. And so, the identity operator properly states that the letter was found.</p>
<p>In strongly typed languages such as .NET, however, there&#8217;s an inherently huge difference between the ethereal and temporal.</p>
<p>In PHP, for the most part null and empty are apples and oranges; they&#8217;re not the same thing, but they&#8217;re at least both fruits. In .NET, null and empty are your marriage to <a href="http://www.marisamiller.com/">Marisa Miller</a> and oranges. There&#8217;s literally no comparison to be made.</p>
<p>However, because humans equate nothing with zero, thanks to our <a href="http://www.dougv.com/2008/09/03/describing-red-to-a-blind-man-the-dilemma-of-ontology/">ontological capacities</a>, almost all programming languages have some construct that allows us to equate null and empty. In .NET, for example, the <a href="http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.aspx">IsNullOrEmpty()</a> method of the String class:</p>
<pre class="brush: vb; title: ; notranslate">
Dim MyString As String

If MyString.IsNullOrEmpty() Then
	Console.WriteLine(&quot;MyString is null or empty, says IsNullOrEmpty&quot;)
End If
</pre>
<p>In PHP, again, the comparison operators will implicitly convert your nulls into empty strings. However, there is also the built-in <a href="http://us2.php.net/manual/en/function.is-null.php">is_null()</a> function, which will also return a boolean if your variable is explicitly cast as null; you can couple that with an empty-string comparison to equate null and emptiness:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$foo = NULL;

if(is_null($foo) || $foo == &quot;&quot;) {
echo '$foo is null or empty';
}
?&gt;
</pre>
<h4>Emptiness Is Loneliness, And Loneliness Is Cleanliness</h4>
<p>Which brings us to zero-length, which is basically the condition of existing, and being something, but not anything useful.</p>
<p>This is most common with arrays and similar structured data (e.g., object properties). An array has zero length if it has been instantiated but contains no data. A zero-length data structure, such as an array, itself isn&#8217;t null, and it has type; but it contains nothing.</p>
<p>It&#8217;s like having a refrigerator with its door chained shut; it&#8217;s there, but you can&#8217;t look inside it or take anything out. Of course, you can always unchain the door, and then put things in or out, or just look at what&#8217;s there.</p>
<p>Consider this PHP code, the output of which <a href="http://www.dougv.com/demo/nullemptyzero/zero.php">you can see here</a>:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
$foobar = array();
echo 'the length of $foobar is: ' . count($foobar);
echo &quot;&lt;br /&gt;&quot;;

foreach($foobar as $foo) {
	echo &quot;$foo&lt;br /&gt;&quot;;
}

$foobar[] = &quot;Hello&quot;;
$foobar[] = 46;
echo 'the new length of $foobar is: ' . count($foobar);
echo &quot;&lt;br /&gt;&quot;;

foreach($foobar as $foo) {
	echo &quot;$foo&lt;br /&gt;&quot;;
}
?&gt;
</pre>
<ul>
<li>Line 3 prints 0; $foobar has zero length because we didn&#8217;t add anything to it.</li>
<li>Lines 6-8 are ignored, because $foobar has zero length; there is no <em>each</em>.</li>
<li>Line 12 prints 2, because there are now two items in the array.</li>
<li>Lines 15-17 print &#8220;Hello&#8221; and 46, because <em>foreach</em> now has items to iterate.</li>
</ul>
<h4>Null vs. Empty vs. Zero Length Recap</h4>
<p>So, in review: <strong>Null </strong>means the variable does not exist. <strong>Empty </strong>means it exists, but it contains no value. <strong>Zero length </strong>means an array or similar structure has been declared &#8212; and, if the language is strongly typed, has type &#8212; but contains no values.</p>
<div class="yarpp">
	<h5>Related Posts</h5>
		<ol>
				<li><a href="https://www.dougv.com/2006/12/01/the-difference-between-data-adapters-data-sets-and-data-readers-in-plain-english/" rel="bookmark">The Difference Between Data Adapters, Data Sets And Data Readers, In Plain English</a> (27.2)</li>
				<li><a href="https://www.dougv.com/2006/12/08/a-simple-calendar-page-to-display-date-specific-data-in-php/" rel="bookmark">A Simple Calendar Page To Display Date-Specific Data In PHP</a> (10.5)</li>
				<li><a href="https://www.dougv.com/2007/07/13/getting-plain-text-from-an-aspnet-20-page-for-use-as-an-ajax-data-source/" rel="bookmark">Getting Plain Text From An ASP.NET 2.0 Page For Use As An AJAX Data Source</a> (9)</li>
			</ol>
	<p class="note">The numbers inside parentheses are relevance scores. Scoring is based, in order of priority, on title, category, content and tags. The higher the score, the more likely that post relates to this post.</p>
	</div>

	Tags: <a href="https://www.dougv.com/tag/elegance/" title="elegance" rel="tag">elegance</a>, <a href="https://www.dougv.com/tag/objects-and-classes/" title="objects and classes" rel="tag">objects and classes</a><br />
]]></content:encoded>
			<wfw:commentRss>https://www.dougv.com/2008/10/22/the-difference-between-null-empty-and-zero-length-data-strings/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

