<?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>Dave Rowe's Blog</title>
	<atom:link href="http://blog.roweware.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.roweware.com</link>
	<description>Ramblings about things I think I know...</description>
	<lastBuildDate>Wed, 03 Mar 2010 19:32:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SQL Server Export Encoding</title>
		<link>http://blog.roweware.com/2010/03/03/sql-server-export-encoding/</link>
		<comments>http://blog.roweware.com/2010/03/03/sql-server-export-encoding/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 19:32:29 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[dos2unix]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[utf-16]]></category>
		<category><![CDATA[utf-8]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=195</guid>
		<description><![CDATA[If you ask someone for an export of data, and you know the data is coming from SQL Server, be sure to clarify what encoding you&#8217;d like the export in (if they can configure it) &#8211; I spent a bit of time trying to figure out why I couldn&#8217;t reliably read a file, and by [...]]]></description>
			<content:encoded><![CDATA[<p>If you ask someone for an export of data, and you know the data is coming from <a href="http://www.microsoft.com/sqlserver/">SQL Server</a>, be sure to clarify what encoding you&#8217;d like the export in (if they can configure it) &#8211; I spent a bit of time trying to figure out why I couldn&#8217;t reliably read a file, and by using a hexeditor, I found the leading bytes were the culprit.  Comparing to a listing on <a href="http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding">Wikipedia</a>, I found the file was in UTF-16, when I&#8217;m expecting simple UTF-8 or ASCII.  Easy solution though if you&#8217;re on a *nix machine:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p195code2'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1952"><td class="code" id="p195code2"><pre class="bash" style="font-family:monospace;">iconv <span style="color: #660033;">-f</span> UTF-<span style="color: #000000;">16</span> <span style="color: #660033;">-t</span> UTF-<span style="color: #000000;">8</span> input_file <span style="color: #000000; font-weight: bold;">&gt;</span> output_file</pre></td></tr></table></div>

<p>And you&#8217;re done!  Easy as pie&#8230;when you know what the problem is.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/03/03/sql-server-export-encoding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ChartDirector with PHP</title>
		<link>http://blog.roweware.com/2010/03/02/chartdirector-with-php/</link>
		<comments>http://blog.roweware.com/2010/03/02/chartdirector-with-php/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 14:30:11 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[chartdirector]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[help]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=189</guid>
		<description><![CDATA[For a project, we have the need to create charts dynamically from data.  In another project, we&#8217;ve used ChartDirector for this.  It has worked great there, so we pulled it into this project as well.  Now, the type of charts I was working with in particular is a stacked percentage chart, which is kind of [...]]]></description>
			<content:encoded><![CDATA[<p>For a project, we have the need to create charts dynamically from data.  In another project, we&#8217;ve used <a href="http://www.advsofteng.com/">ChartDirector</a> for this.  It has worked great there, so we pulled it into this project as well.  Now, the type of charts I was working with in particular is a stacked percentage chart, which is kind of like a mash between a pie chart and a traditional bar chart.  An example:</p>
<p><a href="http://blog.roweware.com/wp-content/uploads/2010/03/percentbar.png"><img class="alignnone size-full wp-image-191" title="percentbar" src="http://blog.roweware.com/wp-content/uploads/2010/03/percentbar.png" alt="Percentage Bar" width="510" height="330" /></a></p>
<p>Now, with dynamic data, you can&#8217;t predict what your data will look like, and your code needs to be flexible enough to handle any situation without causing headaches for the user.  With ChartDirector, you pass in datasets via arrays across the chart, so for example the above datasets would be created by:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p189code5'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1895"><td class="code" id="p189code5"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$data0</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">125</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">245</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">147</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">67</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data1</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">85</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">156</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">179</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">211</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">123</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data2</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">87</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">56</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">267</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">157</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Such that, the numbers line up in the arrays (vertically) in how they correspond to the resulting chart.  In my situation and test data, I found I had a situation like the following:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p189code6'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1896"><td class="code" id="p189code6"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$data0</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">125</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">147</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">67</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data1</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">85</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">156</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">211</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">123</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data2</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">97</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">87</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">267</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">157</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>So, the bar for the 3rd item in the chart would be distributed equally as 33.33% when, in fact, there was no data.  I assumed the chart would display a blank spot for that bar.  After searching the less than optimal support forums (to no fault of the creators / maintainers), I found I needed to instead use a constant defined in the ChartDirector code &#8211; &#8216;NoValue&#8217;, where I had&#8230;wait for it&#8230;.no value.  Putting a small check in my code to replace zeros with &#8216;NoValue&#8217; proved to produce the results I was after.</p>
<p>Note to fellow developers: If you&#8217;re posting in a forum for assistance, please be more verbose in your subject line.  It <em>really</em> helps with searching if the subject can provide some bit of context around what the problem is.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/03/02/chartdirector-with-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery .submit() won&#8217;t fire!</title>
		<link>http://blog.roweware.com/2010/03/01/jquery-submit-wont-fire/</link>
		<comments>http://blog.roweware.com/2010/03/01/jquery-submit-wont-fire/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 19:51:24 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[basic]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/2010/03/01/jquery-submit-wont-fire/</guid>
		<description><![CDATA[FYI &#8211; If you&#8217;re using jQuery in your application, and you&#8217;re trying to submit a form programmatically (ie, $(&#8216;#myform&#8217;).submit(); ), you&#8217;ll want to make sure you don&#8217;t have a button with an ID/Name of &#8217;submit&#8217; &#8211; the code fails silently, with no indication of why.  This is something that caught me today, and was [...]]]></description>
			<content:encoded><![CDATA[<p>FYI &#8211; If you&#8217;re using jQuery in your application, and you&#8217;re trying to submit a form programmatically (ie, $(&#8216;#myform&#8217;).submit(); ), you&#8217;ll want to make sure you don&#8217;t have a button with an ID/Name of &#8217;submit&#8217; &#8211; the code fails silently, with no indication of why.  This is something that caught me today, and was somewhat frustrating since it was such a basic concept of getting a form to fire.</p>
<p>Reference: <a href="http://api.jquery.com/submit/#comment-30950448" target="_blank">http://api.jquery.com/submit/#comment-30950448</a> &#8211;  Thanks Scotty!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/03/01/jquery-submit-wont-fire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook Chat now supports XMPP (Jabber)!</title>
		<link>http://blog.roweware.com/2010/02/24/facebook-chat-now-supports-xmpp-jabber/</link>
		<comments>http://blog.roweware.com/2010/02/24/facebook-chat-now-supports-xmpp-jabber/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 17:21:44 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/2010/02/24/facebook-chat-now-supports-xmpp-jabber/</guid>
		<description><![CDATA[You can now sign-in to Facebook Chat using your favorite XMPP/Jabber client (Pidgin, Adium, Kopete, etc).  If you&#8217;re on Linux (Arch, specifically) you&#8217;ll need to install the cyrus-sasl package.
]]></description>
			<content:encoded><![CDATA[<p>You can now sign-in to Facebook Chat using your favorite XMPP/Jabber client (Pidgin, Adium, Kopete, etc).  If you&#8217;re on Linux (Arch, specifically) you&#8217;ll need to install the cyrus-sasl package.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/02/24/facebook-chat-now-supports-xmpp-jabber/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSH Tunnels</title>
		<link>http://blog.roweware.com/2010/02/10/ssh-tunnels/</link>
		<comments>http://blog.roweware.com/2010/02/10/ssh-tunnels/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 16:23:19 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=183</guid>
		<description><![CDATA[I love SSH tunnels.  I use them as a cheap VPN solution when traveling, and if I need to get access to an internal web server on the inside of a network (assuming the network isn&#8217;t separated).  As an example, I have 2 computers at home which I use daily for development, etc. [...]]]></description>
			<content:encoded><![CDATA[<p>I love SSH tunnels.  I use them as a cheap VPN solution when traveling, and if I need to get access to an internal web server on the inside of a network (assuming the network isn&#8217;t separated).  As an example, I have 2 computers at home which I use daily for development, etc.  When traveling, I have a laptop that I use.  Well, I use VirtualBox at home, since the computers there have plenty of RAM to support it, where my laptop isn&#8217;t as VM friendly (its old, but has served me well, and will continue to do so until it croaks.), so I needed a way to access my applications running on the VM while on the go.  Enter SSH tunnels.  SSH tunnels work by opening a port over which traffic can flow to the remote location.  Using &#8216;dynamic ports&#8217;, you get a SOCKS proxy.</p>
<p>You create SSH tunnels using:<br />
<code><br />
ssh -D 8080 username@remote_server<br />
</code><br />
Which opens port 8080 on the local machine.  Then, you can configure your browser of choice to use a SOCKS v5 Proxy at 127.0.0.1:8080.  Specifically in Firefox, make sure that none of your other proxy settings are set.</p>
<p>It should look like the following:<br />
<a style="clear: both;" href="http://blog.roweware.com/wp-content/uploads/2010/02/FirefoxProxy.png"><img class="size-full wp-image-184 alignnone" title="FirefoxProxy" src="http://blog.roweware.com/wp-content/uploads/2010/02/FirefoxProxy.png" alt="" width="502" height="543" /></a></p>
<p>Now, you can check the IP address for your connection by visiting a site like: <a href="http://www.whatsmyip.org/">http://www.whatsmyip.org/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/02/10/ssh-tunnels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Concrete5</title>
		<link>http://blog.roweware.com/2010/02/07/concrete5/</link>
		<comments>http://blog.roweware.com/2010/02/07/concrete5/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 03:18:19 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=181</guid>
		<description><![CDATA[A quick shout-out to a great product.  Concrete5 is an excellent CMS.  With easy theming, and even easier setup, it&#8217;s a snap solution for some of the most particular of tastes.
It&#8217;s open-source, which I really like, but the ease of getting it setup, and the polished look and feel just make me happy [...]]]></description>
			<content:encoded><![CDATA[<p>A quick shout-out to a <em>great</em> product.  <a href="http://www.concrete5.org/">Concrete5</a> is an excellent CMS.  With easy theming, and even easier setup, it&#8217;s a snap solution for some of the most particular of tastes.</p>
<p>It&#8217;s open-source, which I really like, but the ease of getting it setup, and the polished look and feel just make me happy to use it.</p>
<p>Great work guys!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/02/07/concrete5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenLDAP</title>
		<link>http://blog.roweware.com/2010/02/04/openldap/</link>
		<comments>http://blog.roweware.com/2010/02/04/openldap/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 22:48:27 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=174</guid>
		<description><![CDATA[At work, we&#8217;re developing an application that uses LDAP for authentication.  Specifically, we&#8217;re using OpenLDAP.  We use a VM for development, which allows each developer to have a copy of the &#8217;standard&#8217; environment, to ensure we&#8217;re on the same version of libraries, compilers, databases, etc.  As part of managing the VMs, we [...]]]></description>
			<content:encoded><![CDATA[<p>At work, we&#8217;re developing an application that uses <a href="http://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol">LDAP </a>for authentication.  Specifically, we&#8217;re using <a href="http://www.openldap.org/">OpenLDAP</a>.  We use a <a href="http://www.virtualbox.org/">VM</a> for development, which allows each developer to have a copy of the &#8217;standard&#8217; environment, to ensure we&#8217;re on the same version of libraries, compilers, databases, etc.  As part of managing the VMs, we write maintenance scripts to keep everyones VM in line with each other.  I wrote a script to install a baseline installation of OpenLDAP.  I thought  I&#8217;d covered my bases with <a href="http://en.wikipedia.org/wiki/File_system_permissions#Notation_of_traditional_Unix_permissions">permissions</a>, but upon startup OpenLDAP created a new file which was owned by root, and had 0600 permissions, which meant no one but root could read or write to that file.  I had configured OpenLDAP to run as &#8216;openldap&#8217;, so of course, it couldn&#8217;t read the file.  Unfortunately, the error message is less than helpful:<br />
<code><br />
'0x50 (Other (e.g., implementation specific) error): updating: &lt;my DN, etc etc&gt;'<br />
</code></p>
<p>So, checking to see the file permissions under /var/lib/ldap, I see a file objectClass.bdb owned by root.  Changed it to openldap:openldap, and all is well.</p>
<p>Moral of the story: Always check file permissions.  Especially after starting up the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/02/04/openldap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>External Login to phpBB</title>
		<link>http://blog.roweware.com/2010/01/26/external-login-to-phpbb/</link>
		<comments>http://blog.roweware.com/2010/01/26/external-login-to-phpbb/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 22:29:55 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpBB]]></category>
		<category><![CDATA[single-sign-on]]></category>
		<category><![CDATA[sso]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=172</guid>
		<description><![CDATA[Recently, I was tasked with creating a single-sign-on solution for phpBB, where the user would login to our application, and when clicking a link to take them to a support forum, they&#8217;d already be logged in.  phpBB isn&#8217;t known for having a great API with which to integrate, but the code works, and the [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I was tasked with creating a single-sign-on solution for phpBB, where the user would login to our application, and when clicking a link to take them to a support forum, they&#8217;d already be logged in.  phpBB isn&#8217;t known for having a great API with which to integrate, but the code works, and the product works.  The authentication works on the premise of providing credentials, logging in, which creates a session in the phpBB database.  A cookie value is set, which ties the user to the server-side session.  When you have the 2 disparate systems, the domains might be different, but on the same top-level domain.  This means if we could get the session ID and set a cookie on the next domain level up, we could be logged in.</p>
<p>The implementation is fairly simple, upon login, we use cURL or something similar and generate a POST request, using the username and password.  The remote script grabs the session ID and user ID and returns the values to the originating server.  We then, set the cookie values.</p>
<p>Now, the interesting bit.  phpBB has multiple layers by which it validates the session.  Since our remote server is originating the request, we don&#8217;t have the same IP as the user.  Second, it uses the User-Agent string of the browser to validate the session.  Using cURL, we don&#8217;t have a browser.  Now, with cURL, you can set various settings (User-Agent string, X-Forwarded-For header, etc) &#8211; but if you&#8217;d rather not depend on that, you can simply un-check those settings in phpBB.</p>
<p>Of course, I&#8217;d recommend using the cURL settings, but to get you started and ensure the connectivity is working.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2010/01/26/external-login-to-phpbb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZFDataGrid &#8211; Enabling Export</title>
		<link>http://blog.roweware.com/2009/12/29/zfdatagrid-enabling-export/</link>
		<comments>http://blog.roweware.com/2009/12/29/zfdatagrid-enabling-export/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 22:41:33 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[zfdatagrid]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=159</guid>
		<description><![CDATA[I&#8217;m evaluating a DataGrid for use in a project which is using the Zend Framework, and I came across the ZFDataGrid project.  Fantastic work, and the grid works wonderfully.  It enables you to filter your data and export it in various formats (PDF, Doc, Docx, OpenOffice, etc).  The sample on the site works exactly like [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m evaluating a DataGrid for use in a project which is using the <a href="http://framework.zend.com/">Zend Framework</a>, and I came across the <a href="http://code.google.com/p/zfdatagrid/">ZFDataGrid</a> project.  Fantastic work, and the grid works wonderfully.  It enables you to filter your data and export it in various formats (PDF, Doc, Docx, <a href="http://www.openoffice.org/">OpenOffice</a>, etc).  The <a href="http://www.petala-azul.com/grid/">sample</a> on the site works exactly like this.  The only issue is the manual doesn&#8217;t exactly explain how to enable the export functionality.  It doesn&#8217;t &#8216;just work&#8217;, but it was reasonably easy to find since the code for the sample site is in <a href="http://code.google.com/">Google Code</a>.  But, it isn&#8217;t in an intuitive place like the manual or on the site itself.  So, to hopefully save someone else some time, I&#8217;ll post the code here &#8211; it is from the sample <a href="http://code.google.com/p/zfdatagrid/source/browse/trunk/application/controllers/SiteController.php">SiteController</a>, and not originally written by me.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p159code8'); return false;">View Code</a> PHP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p1598"><td class="code" id="p159code8"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$export</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'export'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$export</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'odt'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Odt&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'ods'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Ods&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'xml'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Xml&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'csv'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Csv&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'excel'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Excel&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'word'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Word&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'wordx'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Wordx&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'pdf'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Pdf&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">case</span> <span style="color: #0000ff;">'print'</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Print&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">default</span> <span style="color: #339933;">:</span>
        <span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Bvb_Grid_Deploy_Table&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$grid</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000088;">$grid</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'DataGrid Example'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/tmp'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'download'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$grid</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setDataFromCsv</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/dirname"><span style="color: #990000;">dirname</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/Detail_Limited.csv'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$grid</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">imagesUrl</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/images/'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">grid</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$grid</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">deploy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>The code at the end is mine, which basically tells the DataGrid where to render/save the exported file, which is then immediately sent for download.  I also am not using the Zend_Db stuff for the data.  As a proof-of-concept, I&#8217;m using a simple dataset in CSV, which works amazingly well.  The filters, sorting, and pagination still work with CSV.</p>
<p>I&#8217;m thinking about writing an adapter for <a href="http://www.doctrine-project.org/">Doctrine</a>, such that one could construct a Doctrine query object, pass it into the DataGrid, and everything would work, as it does with the Zend_Db counterparts.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2009/12/29/zfdatagrid-enabling-export/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Surrogates</title>
		<link>http://blog.roweware.com/2009/12/23/surrogates/</link>
		<comments>http://blog.roweware.com/2009/12/23/surrogates/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 20:14:44 +0000</pubDate>
		<dc:creator>Dave Rowe</dc:creator>
				<category><![CDATA[Database Design]]></category>
		<category><![CDATA[keys]]></category>
		<category><![CDATA[linking table]]></category>
		<category><![CDATA[many to many]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://blog.roweware.com/?p=150</guid>
		<description><![CDATA[In my previous post, I used a key style that is open to debate and has been for many years amongst DB folks.  The idea of every table having a surrogate key, regardless of the purpose of the table.  This says, that for any record in the table I have a single column [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous post, I used a key style that is open to debate and has been for many years amongst DB folks.  The idea of every table having a surrogate key, regardless of the purpose of the table.  This says, that for any record in the table I have a single column that acts as the primary key.  Given a many-to-many relationship, using a surrogate key on the linking table allows me to describe the relationship in terms of objects and how they&#8217;re represented.  As shown in the below diagram &#8211; each user may have many user_role instances, which are tied to a single role instance.  This makes the lives of ORMs much easier since you can create objects for the linking table, which has a simple key to reference.</p>
<p style="text-align: center;"><a href="http://blog.roweware.com/wp-content/uploads/2009/12/Surrogate.png"><img class="size-full wp-image-152 aligncenter" title="Surrogate" src="http://blog.roweware.com/wp-content/uploads/2009/12/Surrogate.png" alt="" width="414" height="124" /></a></p>
<p>The ORM then has a User, UserRole, and Role object to use in accessing these tables and adding / removing relationships with ease, since it only needs to worry about the single surrogate &#8216;id&#8217; key on each table.  In the linking table (as a design concern), one should place a Unique Index on the user_id/role_id column combination.</p>
<p>The other option is using a composite candidate key.  I may have the specific terminology wrong, but the idea is that instead of the single surrogate key to identify a unique record in the linking table, you use a design like the diagram below, which combines the columns that are foreign keys to their respective tables to create the primary key.  The combination of the columns creates a unique identifying key.  The difficulty emerges with ORMs attempting to create objects out this design, and attempting to correctly generate the SQL required to make updates / deletes, etc, using each member of the composite key.</p>
<p style="text-align: center;"><a href="http://blog.roweware.com/wp-content/uploads/2009/12/NoSurrogate.png"><img class="size-full wp-image-151 aligncenter" title="NoSurrogate" src="http://blog.roweware.com/wp-content/uploads/2009/12/NoSurrogate.png" alt="" width="399" height="108" /></a></p>
<p>Personally speaking, I&#8217;m a fan of the surrogate key approach, but I&#8217;ve worked with both.  I won&#8217;t discuss the performance impacts of either design, since I don&#8217;t have nearly the research base to accurately describe it.  But, using simple integer based keys, the difference should be low.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roweware.com/2009/12/23/surrogates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
