<?xml version="1.0" ?> 
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<!-- _l: atom -->
<channel>
    <title>Graham Christensen</title>
    <description>Symfony development, hardware, and everything else, too.</description>
    <link>http://grahamc.com/</link>
    <atom:link href="http://grahamc.com/feed/" rel="self" type="application/rss+xml" /> 
    <lastBuildDate>Mon, 21 Nov 2011 15:27:35 -0800</lastBuildDate> 
    
    
	
    <item>
        <guid>http://grahamc.com//blog/multiple-git-repositories-one-directory-dotfiles</guid>
        <title>How to have two git repositories in the same directory</title>
        <pubDate>Tue, 13 Sep 2011 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>If you were to <a href='https://github.com/search?q=dotfiles'>search GitHub for dotfile repositories</a>, you would find <em>thousands</em> of them. Just perusing the top few will give you a wonderful treasure-trove of useful tips and tricks for becoming a true power user. This resource has truly opened my eyes to things I could be doing better, faster.</p>

<p>When I struck gold and didn&#8217;t want to cobble together my files yet again (IE: every time I reinstall) I decided to begin versioning my dotfiles. I began in the most obvious of ways: I made my home directory a git repository, ignored all my files, and only explicitly added all the files I really wanted in there. This worked for a while, but the files that I truly wish WERE versioned were not - my SSH and GPG keys, and my SSH configuration. Additionally, I had a few bash variables which contained private information that I didn&#8217;t want to make public.</p>

<p>The obvious solution was to put these into another repository <a href='http://grahamc.com/blog/create-secure-git-repository/'>hosted on my own server</a> but integrating that repository into my home directory is what infuriated me.</p>

<h3 id='symlinks'>Symlinks</h3>

<p>The first and common method people seem to be doing is using tools like <a href='https://github.com/trym/dotty'>dotty</a> or <a href='https://github.com/technicalpickles/homesick'>homesick</a> to manage the multiple repositories and setup symlinks automatically.</p>

<p>These tools worked fine for a little while, but they had a severe downside: <strong>neither of them are designed to be easy to add files back in</strong>. This made it very difficult to maintain or find files I had forgotten to import; it was mostly a guess-and-check kind of situation.</p>

<p>They created a reasonable interface to working with themselves, but when it came down to using <strong>git</strong> like it is supposed to be, it was just an enormous headache.</p>

<p>Unfortunately the problem with using symlinks in this situation is inherent: git doesn&#8217;t know what you&#8217;re doing, and does its best. I cannot blame git.</p>

<h3 id='a_proposed_solution'>A Proposed Solution</h3>

<p>My biggest frustration with these tools were they didn&#8217;t let git do what it is good at: <strong>manage my dammed files</strong>. They tried to be smarter than git, and really quite poorly. It pissed me off a good deal.</p>

<p>My ideal solution was letting git manage itself like I know it can, but I just needed it to support multiple repositories in one directory.</p>

<h4 id='if_only'>If only&#8230;</h4>

<p>If only I could have my git repository files located in, say, <code>~/.git-repos/private</code>, but tell it to check my files out into <code>~/</code> that would do it, right?</p>

<h4 id='oh_wait'>OH WAIT!</h4>

<p>Git already provides the tools to do <em>exactly</em> to this!</p>

<ul>
<li><strong>$GIT_DIR</strong> - This tells Git where to look for the .git directory. In this way you could be in <code>/tmp/whatever</code> and manage your git repository located in <code>/home/grahamc/my-awesome-files</code>.</li>

<li><strong>GIT_WORK_TREE</strong> - This tells Git where the files are that it is tracking. Using this your .git directory could be in <code>/tmp/whatever</code> and actually have all your checked out files be put in to <code>/home/grahamc/my-awesome-files</code>.</li>
</ul>

<p>Now we&#8217;re getting somewhere!</p>

<h3 id='the_sexy_solution_'>The Sexy Solution: <code>git multi</code></h3>

<p>That&#8217;s right, I built it out. Using those two shell variables it was pretty trivial, didn&#8217;t require crazy dependencies, or any nasty symlinks.</p>

<p>Go ahead and get <a href='https://github.com/grahamc/git-multi'>these shell scripts</a>, drop them in to your ~/bin (or path, I suppose) and be enlightened.</p>

<h4 id='adding_a_repository'>Adding a Repository</h4>

<p><code>git multi add public git@github.com:youruser/dotfiles.git</code></p>

<p>Blammo. Done. That&#8217;s it. That even checks out the repository and everything.</p>

<h4 id='working_on_a_repository'>Working on a Repository</h4>

<p><code>git multi work public</code></p>

<p>This command opens up a bash terminal with <strong>$GIT_DIR</strong> and <strong>$GIT_WORK_TREE</strong> already set and everything. Your git commands work like they were native. <strong>Wait. Mmmm&#8230; it&#8217;s because they are.</strong></p>

<p>When you&#8217;re done and want to commit or push? Just do that. <code>git commit; git push origin master</code>.</p>

<p>For bonus points, add <a href='https://github.com/grahamc/git-multi'><code>grahamc/git-multi</code></a> (or your own fork) as an additional repository to your home directory.</p>

<p>Hit me up with a pull request or comments if you have issues.</p>]]></description>
        <link>http://grahamc.com/blog/multiple-git-repositories-one-directory-dotfiles</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/create-secure-git-repository</guid>
        <title>How to Create a Secure Git Repository on a Shared Server</title>
        <pubDate>Mon, 12 Sep 2011 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>If you&#8217;re like me, you might like hosting your private repositories yourself Something about <a href='http://news.cnet.com/8301-31921_3-20072755-281/dropbox-confirms-security-glitch-no-password-required/'>trusting other people</a> with my secure files gives me the willies. I also prefer keeping these files under version control, so I began exploring setting up a git repository on my server.</p>

<p>It was pretty easy, <code>git init --bare secure.git</code> to initialize a repository at <code>./secure.git</code>. The problem with this, is even if you set the umask to 0077, the files will become readable by all users after you push. You could re-mask them to be 0700, but next time you push it&#8217;ll store new files too permissively.</p>

<p>The solution is fairly easy, but it took a little bit of googling:</p>

<p><code>git init --bare --shared=0700 secure.git</code></p>

<p>This causes all files in this repository to only be readable by the user who owns the directory. If you want your files to be secure, make sure you initialize your repository with this command, otherwise everyone will be able to read your PGP keys.</p>

<p>Now, pretending your server is your-ssh-server.com, and the username is user, you would add it as a remote to your repository as such: <code>git remote add origin user@your-ssh-server.com:path/to/secure.git</code></p>]]></description>
        <link>http://grahamc.com/blog/create-secure-git-repository</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/Ships-Bell-Build-Notifier</guid>
        <title>How I Use a Ship's Bell Clock to Know My Software is Broken</title>
        <pubDate>Sun, 27 Mar 2011 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>My father is a horologist, and as such I grew up with clocks ticking and chiming at all hours - their great strikes cooing me to sleep at night. I remember laying on the floor as a boy studying a clock in the dining room, practicing reading the roman numerals on its octagonal dial.</p>

<p>This early exposure to these beautiful, precision instruments has always inspired me to work with them - I just never knew how, or what I would use them for.</p>

<p>About a year ago I saw the <a href='http://urbanhonking.com/ideasfordozens/2010/05/19/the_github_stoplight/'>GitHub stoplight</a> pass along my feed reader, and I was hooked. I began researching stoplights and how to incorporate them, but it was too easy; no challenge after my <a href='http://www.youtube.com/itrebal#p/a/u/1/desD5os8iuE'>Price is Right, Cliff Hanger clone</a>.</p>

<p>I wanted a similar system to inform me of my mistake on my software, but I also wanted a challenge, and I wanted it to be unique. Ultimately, I decided on using an Arduino with a motor control shield to control the chiming of a Ship&#8217;s bell: One strike meant success, a second strike meant a failure.</p>

<h3 id='controlling_the_strike'>Controlling the Strike</h3>

<p><img src='/resources/2011-03-27-clock-tugs.png' alt='2011 03 27 Clock Tugs' /> As it turns out, a clock&#8217;s chime isn&#8217;t rocket science. Something mechanical triggers the chime, and it runs autonomously. In this case, every half hour a trip rotating pin pushes the strike trigger out, allowing the process to begin.</p>

<p>Brilliantly enough, in order for the strike to do one chime (instead of two), the second strike lever falls and prevents the hammer from hitting the bell a second time.</p>

<p>By mechanically pulling the strike trigger, and lifting (or dropping) the second strike lever, I could reliably and fairly easily trigger the clock to strike once or twice.</p>

<h3 id='controlling_the_strike_electronically'>Controlling the Strike&#8230; Electronically</h3>

<p><img src='/resources/2011-03-27-clock-sensors.png' alt='2011 03 27 Clock Sensors' /> Setting up a couple of motors to tug on the strike trigger and the second strike lever was fairly easy. I used a <a href='http://www.sparkfun.com/products/9457'>SparkFun Dual Motor Driver</a> along with a couple of <a href='http://www.sparkfun.com/products/8911'>geared motors</a> and the hub from a <a href='http://www.sparkfun.com/products/8899'>wheel</a>. Using a bent paper clip and some dental floss, I was able to trigger both actions without much motor movement.</p>

<p>I knew from the get-go I needed a way to know if I had moved the levers far enough, but I wasn&#8217;t sure how to go about it.</p>

<h4 id='sensing_the_levers'>Sensing the Levers</h4>

<p><img src='/resources/2011-03-27-clock-sensors2.png' alt='2011 03 27 Clock Sensors2' /> I discovered by mistake that I could ground both levers from the same point, and that placing a wire at the right point would allow me to know for certain when I had pulled a lever far enough. By waiting for these circuits to be completed, I could stop pulling the lever at the precise moment.</p>

<p><img src='/resources/2011-03-27-clock-chimebar.png' alt='2011 03 27 Clock Chimebar' /></p>

<blockquote>
<p>I used copper desoldering braid wrapped around an insulated peg to sense when the second strike lever was all the way up.</p>
</blockquote>

<h3 id='all_together_now'>All Together Now</h3>

<p><img src='/resources/2011-03-27-clock-attachedtop.png' alt='2011 03 27 Clock Attachedtop' /></p>

<p>Possibly the hardest part of this project was figuring out a way to know when to stop pulling on the levers. This took by far the longest, but looking back, was the most pivotal in having it be successful. In fact, additional value would be gained by adding feedback systems to know exactly when they are in their &#8220;off&#8221; position too, as these are still done via a timer.</p>

<p>All in all, I&#8217;m fairly pleased with the results - all that is functionally left now is having my testing server push notifications to the chime. Eventually, I would like to clean it up; put the electronics away, mount it on wood and possibly put a quartz movement in there as if it were a real clock.</p>]]></description>
        <link>http://grahamc.com/blog/Ships-Bell-Build-Notifier</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/how-to-create-a-super-nerdy-superbowl-that-everyone-will-love</guid>
        <title>How to Create a Super Nerdy Super Bowl Party That Everyone Will Love or: RFID + 1,000 Chicken Wings (Wait... What?)</title>
        <pubDate>Fri, 11 Feb 2011 00:00:00 -0800</pubDate>
        <description><![CDATA[<p>To be quite frank, I don&#8217;t care about football. I didn&#8217;t even know who was playing in the Super Bowl until the day before when two people simultaneously expressed their excitement for <em>insert team here</em> to kick <em>the other team</em>&#8217;s ass. Unfortunately I was being dragged into a party, but it wasn&#8217;t without cause - we were going to eat 1,000 chicken wings before the night was out, and only 25 people were there to do it. We called it <a href='http://keepwinging.com'>KeepWinging</a>.</p>

<p>Now this was pretty close to enough for me to enjoy it, but since <a href='http://nationalfield.org'>NationalField</a> is a data and analytics driven company, we needed to step it up.</p>

<h3 id='thursday_night'>Thursday Night</h3>

<p>Three days before the big day we decided that in order to really know for certain how many wings we&#8217;ve eaten, we needed an accurate count. We needed a great, fun, real-time dashboard of how many wings we&#8217;ve snarfed down, and an easy, BBQ-sauce friendly way to report that data. A solution that means no sticky fingers or beer on my laptop.</p>

<p>I had a lot to do in just 48 hours:</p>

<ul>
<li>build an easy reporting system that didn&#8217;t involve a sticky mess.</li>

<li>get anything that was necessary to build and implement this system.</li>

<li>build a website to display this information in real time.</li>
</ul>

<h3 id='the_dashboard'>The Dashboard</h3>

<p><img src='/resources/2011-02-11-dashboard.png' alt='The KeepWinging Dashboard' /></p>

<blockquote>
<p>Note, this was taken after KeepWinging ended; otherwise the WPH would show a real number.</p>
</blockquote>

<p>We wanted a very simple dashboard which would display only the most important stats in our venture to eat 250 chickens worth of buffalo wings. We also wanted it to be live-updating, and give some level of competition between users.</p>

<p>This was done with a simple jQuery <code>$.get()</code> call plus a <code>setTimeout</code> at the end. The polling was simple and quick, and for a guy who doesn&#8217;t know Javascript very well - it was just perfect. I looked at Node.JS, however with only three days to go I didn&#8217;t have the time to learn it.</p>

<h4 id='what_we_came_up_with'>What We Came Up With</h4>

<ul>
<li><strong>Leaderboard</strong>: The top nine users, showing their total wing consumption and how they compared to the people behind them. This seemed to encourage people who were five below a spot to eat more, and had people fighting to stay on the board.</li>

<li><strong>Total Wings Consumed</strong>: We actually had this in two places, in graph form (which for some reason didn&#8217;t display accurately, but the trend was correct) and as a big number along the top. It was so exciting seeing it roll over to 900, we knew it had to be possible to finish. Below this we also displayed the total number of wings remaining.</li>

<li><strong>Wings Per Hour (WPH)</strong>: We thought it was very neat to know just how many wings we were eating per hour, and we also displayed the number of wings per hour which were necessary to complete the 1,000 wings by the end of the game. At one point we were up to 300 WPH.</li>
</ul>

<p>Each of these items would automatically refresh every second or two, so feedback was almost instant. We knew exactly when consumption was falling off, as well as when fresh &#8220;meat&#8221; joined. This was displayed on a gigantic television screen next to the wings.</p>

<h3 id='the_feed'>The Feed</h3>

<p><img src='/resources/2011-02-11-feed.png' alt='The KeepWinging Feed' /></p>

<blockquote>
<p>The feed would update every second.</p>
</blockquote>

<p>Let&#8217;s face it, the internet loves a good live-updating feed of what is going on. We love that instant feedback of change in our lives, so we couldn&#8217;t resist building one.</p>

<p>The feed was extremely simple, and only updated when a user registered or ate more wings. This view however, was exciting to have and be able to see how quickly people were allocating themselves more wings.</p>

<h2 id='how_it_all_worked'>How It All Worked</h2>

<p>The solution to mess-free reporting was pretty obvious: RFID (<code>Radio Frequency IDentification</code>, like what you might scan to open a keyless door.) Each participant would register an RFID tag with the system, and every time they threw out 5 wings they would be allowed to scan their tag. Since I already had a reader, this was feasible.</p>

<h3 id='keepwingingcom'>KeepWinging.com</h3>

<p><a href='http://keepwinging.com'>KeepWinging</a> was written entirely in <a href='http://symfony-project.org'>Symfony</a> using <a href='http://www.propelorm.org'>Propel</a>; it had a very simple <code>JSON RPC API</code> for providing the data we needed for the content pages - and a single reporting endpoint.</p>

<p>I started writing the code on Friday evening and finally pulled it all together at 2:50 PM, Sunday afternoon, with the party starting at 3:00PM. Perfect timing.</p>

<h3 id='the_rfid_reader'>The RFID Reader</h3>

<p><img src='/resources/2011-02-11-rfid-reader.png' alt='The RFID Process' /> Thursday night was spent building the RFID reader: an <a href='http://www.sparkfun.com/products/9950'>arduino</a> with a <a href='http://www.radioshack.com/product/index.jsp?productId=2906723'>Parallax RFID reader</a> which I got from RadioShack, a couple of LEDS, all mushed into a used Korean <a href='http://en.wikipedia.org/wiki/Bibimbap'>Bibimbop</a> take-out dish. It was perfect. All we needed were the RFID tags.</p>

<p>I also incorporated some simple human feedback: users are used to visual <em>and</em> audio feedback when reading a tag like this. I incorporated a visual cue by having a red and blue LED. When the tag was scanned, the blue light would switch to red. Unfortunately I didn&#8217;t have a buzzer loud enough to stand a chance at a party, so I removed this part of the feedback. (Yes, I did get complaints that it didn&#8217;t beep or buzz.)</p>

<p>One note about RFID readers which I learned during this project:</p>

<blockquote>
<p>Since RFID readers use radio frequencies, the number of devices and signals we have going through the airways can cause false-positive matches. These codes would look like <code>F0000F0000</code> and were almost always obviously fake.</p>

<p>In order to reduce the number of false positives received, it is recommended to try reading the tag twice within a few seconds (I used 2) before it considers it a successful read. This will prevent almost all false positive reads.</p>
</blockquote>

<h3 id='the_rfid_tags'>The RFID Tags</h3>

<p>The tags were a little bit tricky. I only had the two which came with the kit, and we were expecting around 30 people. Now that wouldn&#8217;t be fun, we&#8217;d only have two teams; we had to order more.</p>

<p>It was 10:00 PM on Thursday, the party was on Sunday, and I had to order 50 RFID tags. This meant overnight shipping. This meant Saturday delivery. This meant an AM delivery so I would have some time to make sure they worked. This meant that the cost of shipping was 2x the cost of the actual tags themselves. Boy, when I ordered these tags I committed myself to a lot; namely that they would work.</p>

<h3 id='the_glue_arduino__laptop__keepwingingcom'>The Glue (Arduino -&gt; Laptop -&gt; KeepWinging.com)</h3>

<p>In order to get the tag data from the Arduino to the laptop, I had my brother and a friend help hack out a Perl based script to read from the serial port and execute a command when it received one. This would just execute a local Symfony task: <code>./symfony tag:reportRemote --env=prod $tag</code></p>

<p>The code was simple enough: read 10 bytes from the reader, send it along through the USB serial port to my laptop using the Arduino&#8217;s handy reader.</p>

<p><img src='/resources/2011-02-11-rfid-process.png' alt='The RFID Process' /></p>

<blockquote>
<p>By having the registered check, setting up a new RFID tag was a snap and nearly problem-free.</p>
</blockquote>

<p>That task would perform the registration or the reporting through a very simple RPC API I built. This was no attempt at being RESTful; I just needed to get the thing done.</p>

<h3 id='nearing_the_end'>Nearing the End</h3>

<p>At the end of the night, we were about 20 away from finishing off a thousand - but the simple fact was that nobody could stand to eat five more. Solution: Reduce the report number down to 1, and everyone only has to eat one more wing to push us over. After a little bit of cheering and motivational speaking, we polished off an entire thousand buffalo wings right as the Super Bowl&#8217;s clock ran out of time.</p>

<p>Success.</p>

<p><em>This was also posted on NationalField&#8217;s blog, at <a href='http://nationalfield.org/2011/02/keepwinging/'>http://nationalfield.org/2011/02/keepwinging/</a></em></p>]]></description>
        <link>http://grahamc.com/blog/how-to-create-a-super-nerdy-superbowl-that-everyone-will-love</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/using-make-to-manage-jekyll</guid>
        <title>Using `make' to Manage Jekyll</title>
        <pubDate>Sat, 25 Dec 2010 00:00:00 -0800</pubDate>
        <description><![CDATA[<p>Recently I switched from using Wordpress to Jekyll. I noticed a general trend of using <code>rake</code> for managing the generation and deployment of the website. Lately I&#8217;ve become quite fond of straight Makefiles, and ported their concepts and utilities.</p>

<p>The resulting Makefile is fairly basic, but performs essential operations:</p>

<ul>
<li><code>clean</code>: Delete the locally built files</li>

<li><code>build</code>: Generate the website files locally (automatically runs <code>clean</code>)</li>

<li><code>push</code>: Push the generated files to the remote server. This uses <code>scp</code> by default.</li>

<li><code>new</code>: Generate a new Markdown document in <code>_posts</code>. Pass <code>TOPIC=&quot;foo&quot;</code> to change the name of the generated post (<code>new article</code> by default).</li>
</ul>

<p>To use this Makefile with Jekyll, just reconfigure the <code>REMOTEHOST</code> and <code>REMOTEDIR</code> parameters at the bottom of the file with your own settings.</p>
<div class='highlight'><pre><code class='makefile'><span class='nf'>deploy</span><span class='o'>:</span> <span class='m'>build push</span>

<span class='nf'>help</span><span class='o'>:</span>
	@echo <span class='s2'>&quot;You may provide several parameters, like:&quot;</span>
	@echo <span class='s2'>&quot;make [target] KEY=\&quot;value\&quot;&quot;</span>
	@echo <span class='s2'>&quot;&quot;</span>
	@echo <span class='s2'>&quot;The following parameters are available (with the defaults): &quot;</span>
	@echo <span class='s2'>&quot;REMOTEHOST=$(REMOTEHOST)&quot;</span>
	@echo <span class='s2'>&quot;REMOTEDIR=$(REMOTEDIR)&quot;</span>
	@echo <span class='s2'>&quot;&quot;</span>
	@echo <span class='s2'>&quot;You may provide the TOPIC variable to the &#39;new&#39; target.&quot;</span>
	@echo <span class='s2'>&quot;&quot;</span>

<span class='nf'>.PHONY</span><span class='o'>:</span> <span class='m'>clean</span>
<span class='nf'>clean</span><span class='o'>:</span>
	rm -rf _site/*

<span class='nf'>push</span><span class='o'>:</span>
	scp -r _site/* <span class='k'>$(</span>REMOTE<span class='k'>)</span>
	growlnotify -m <span class='s2'>&quot;BLOG: Uploaded.&quot;</span>

<span class='nf'>build</span><span class='o'>:</span> <span class='m'>clean</span>
	jekyll
	chmod -R 755 _site/*
	growlnotify -m <span class='s2'>&quot;BLOG: Built.&quot;</span>

<span class='nf'>serve</span><span class='o'>:</span> <span class='m'>clean</span>
	jekyll --server

<span class='nf'>new</span><span class='o'>:</span>
	<span class='nb'>echo</span> <span class='s2'>&quot;---&quot;</span> &gt;&gt; <span class='k'>$(</span>FILE<span class='k'>)</span>
	<span class='nb'>echo</span> <span class='s2'>&quot;title: $(TOPIC)&quot;</span> &gt;&gt; <span class='k'>$(</span>FILE<span class='k'>)</span>
	<span class='nb'>echo</span> <span class='s2'>&quot;layout: post&quot;</span> &gt;&gt; <span class='k'>$(</span>FILE<span class='k'>)</span>
	<span class='nb'>echo</span> <span class='s2'>&quot;published: false&quot;</span> &gt;&gt; <span class='k'>$(</span>FILE<span class='k'>)</span>
	<span class='nb'>echo</span> <span class='s2'>&quot;---&quot;</span> &gt;&gt; <span class='k'>$(</span>FILE<span class='k'>)</span>
	open <span class='k'>$(</span>FILE<span class='k'>)</span>

<span class='c'># Change these settings for your own use, for example:</span>
<span class='c'># REMOTEHOST ?= yourwebsite.com</span>
<span class='c'># REMOTEDIR ?= /path/to/your/webroot</span>
<span class='c'># Note the lack of a / on webroot</span>
<span class='nv'>REMOTEHOST</span> <span class='o'>?=</span> yakko
REMOTEDIR ?<span class='o'>=</span> ~/grahamc.com/main/public
<span class='nv'>REMOTE</span> <span class='o'>=</span> <span class='k'>$(</span>REMOTEHOST<span class='k'>)</span>:<span class='k'>$(</span>REMOTEDIR<span class='k'>)</span>

TOPIC ?<span class='o'>=</span> new article
<span class='nv'>FILE</span> <span class='o'>=</span> <span class='k'>$(</span>shell date <span class='s2'>&quot;+./_posts/%Y-%m-%d-$(TOPIC).markdown&quot;</span> | sed -e y/<span class='se'>\ </span>/-/<span class='k'>)</span>
</code></pre>
</div>
<blockquote>
<p>This Makefile also utilizes the Mac program Growl. If you don&#8217;t use a Mac (or don&#8217;t have Growl, remove the <code>growlnotify</code> lines.)</p>
</blockquote>]]></description>
        <link>http://grahamc.com/blog/using-make-to-manage-jekyll</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/testing-symfony-propel-phpunit</guid>
        <title>Testing Symfony and Propel With PHPUnit</title>
        <pubDate>Tue, 30 Nov 2010 00:00:00 -0800</pubDate>
        <description><![CDATA[<p>Running PHPUnit alongside of symfony is a fairly easy matter. Including the ProjectConfiguration file initializes the autoloader, your libraries get set up, everything is gravy&#8230; Except when its not.</p>

<p>When you get into contexts, configurations, applications, database integration, or nearly anything else that touches even the basic symfony bits, you drag in the whole symfony stack. <em>Something</em> in the stack caused every test to throw an <a href='/resources/2010-11-30.txt'>unintelligible RuntimeException</a>, with thousands of literal question marks (read: not an encoding error.)</p>

<p>Even through modifying symfony and PHPUnit&#8217;s sourcecode, running XDebug, not running XDebug, etc. nothing could convert those question marks into real-life, intelligible errors. Imagine how silly I felt searching Google for &#8221;<strong>phpunit symfony question marks</strong>&#8221; - nothing, as you could imagine, came up.</p>

<p>I had worked through both of the existing Symfony plugins, <a href='http://www.symfony-project.org/plugins/sfPhpunitPlugin'>sfPHPUnitPlugin</a> and <a href='http://www.symfony-project.org/plugins/sfPHPUnit2Plugin'>sfPHPUnit2Plugin</a>. One of the is very over-arching and depends on an old version of PHPUnit (however it did work) and the newer one gave me the same issue.</p>

<p>After a long time of organized debugging, I devolved (as one usually does) to a series of <a href='http://en.wikipedia.org/wiki/Shotgun_debugging'>shotgun debugging</a>.</p>

<h3 id='how_i_solved_it'>How I Solved It</h3>

<p>Firstly, you&#8217;re going to need to use a bootstrap file to initialize the context. Basic, cut and dry:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='nv'>$path</span> <span class='o'>=</span> <span class='nb'>realpath</span><span class='p'>(</span><span class='nb'>dirname</span><span class='p'>(</span><span class='k'>__FILE__</span><span class='p'>)</span> <span class='o'>.</span> <span class='s1'>&#39;/../config/&#39;</span><span class='p'>);</span>
<span class='k'>require_once</span> <span class='nv'>$path</span> <span class='o'>.</span> <span class='s1'>&#39;/ProjectConfiguration.class.php&#39;</span><span class='p'>;</span>

<span class='c1'>// Initialize the application</span>
<span class='nv'>$m</span> <span class='o'>=</span> <span class='nx'>ProjectConfiguration</span><span class='o'>::</span><span class='na'>getApplicationConfiguration</span><span class='p'>(</span><span class='s1'>&#39;frontend&#39;</span><span class='p'>,</span>
                                                       <span class='s1'>&#39;testing&#39;</span><span class='p'>,</span> <span class='k'>true</span><span class='p'>);</span>

<span class='c1'>// Now initialize the database bits</span>
<span class='nx'>sfContext</span><span class='o'>::</span><span class='na'>createInstance</span><span class='p'>(</span><span class='nv'>$m</span><span class='p'>);</span>
<span class='k'>new</span> <span class='nx'>sfDatabaseManager</span><span class='p'>(</span><span class='nv'>$m</span><span class='p'>);</span>

<span class='nb'>error_reporting</span><span class='p'>(</span><span class='k'>E_ALL</span> <span class='o'>|</span> <span class='nx'>E_STRICT</span><span class='p'>);</span>
<span class='nb'>ini_set</span><span class='p'>(</span><span class='s1'>&#39;display_errors&#39;</span><span class='p'>,</span> <span class='k'>true</span><span class='p'>);</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>Drop this into <code>test/bootstrap.php</code>. Every time you run phpunit from here, you pass the <code>--bootstrap test/bootstrap.php</code></p>
</blockquote>
<div class='highlight'><pre><code class='xml'><span class='nt'>&lt;phpunit</span>
    <span class='na'>colors=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>verbose=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>convertErrorsToExceptions=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>convertNoticesToExceptions=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>convertWarningsToExceptions=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>stopOnFailure=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>processIsolation=</span><span class='s'>&quot;false&quot;</span>
    <span class='na'>syntaxCheck=</span><span class='s'>&quot;true&quot;</span>
    <span class='na'>bootstrap=</span><span class='s'>&quot;test/bootstrap.php&quot;</span><span class='nt'>&gt;</span>

    <span class='nt'>&lt;testsuites&gt;</span>
        <span class='nt'>&lt;testsuite</span> <span class='na'>name=</span><span class='s'>&quot;Unit Tests&quot;</span><span class='nt'>&gt;</span>
            <span class='nt'>&lt;directory&gt;</span>test/unit/<span class='nt'>&lt;/directory&gt;</span>
        <span class='nt'>&lt;/testsuite&gt;</span>
    <span class='nt'>&lt;/testsuites&gt;</span>

    <span class='nt'>&lt;filter&gt;</span>
        <span class='nt'>&lt;blacklist&gt;</span>
            <span class='nt'>&lt;directory</span> <span class='na'>suffix=</span><span class='s'>&quot;.php&quot;</span><span class='nt'>&gt;</span>lib/vendor<span class='nt'>&lt;/directory&gt;</span>
            <span class='nt'>&lt;directory</span> <span class='na'>suffix=</span><span class='s'>&quot;.php&quot;</span><span class='nt'>&gt;</span>cache<span class='nt'>&lt;/directory&gt;</span>
            <span class='nt'>&lt;exclude&gt;</span>
                <span class='nt'>&lt;directory</span> <span class='na'>suffix=</span><span class='s'>&quot;.php&quot;</span><span class='nt'>&gt;</span>lib/vendor<span class='nt'>&lt;/directory&gt;</span>
            <span class='nt'>&lt;/exclude&gt;</span>
        <span class='nt'>&lt;/blacklist&gt;</span>
    <span class='nt'>&lt;/filter&gt;</span>
<span class='nt'>&lt;/phpunit&gt;</span>
</code></pre>
</div>
<blockquote>
<p>Typing in <code>phpunit --bootstrap test/bootstrap.php</code> is pretty ridiculous, so drop this XML into <code>phpunit.xml</code>.</p>
</blockquote>

<p>That <code>phpunit.xml</code> will make it pretty and ensure to exclude the extraneous files which you don&#8217;t want included in any coverage data. It will also specify the bootstrap.php which you just created. At this stage you just execute <code>phpunit</code> and all should be well.</p>

<p><em>For the record, I never did discover the cause of the question marks. I did, discover, however, that the trick is to enable process isolation.</em></p>]]></description>
        <link>http://grahamc.com/blog/testing-symfony-propel-phpunit</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/making-objects-linkable-in-symfony</guid>
        <title>Making Objects Linkable in symfony</title>
        <pubDate>Fri, 10 Sep 2010 00:00:00 -0700</pubDate>
        <description><![CDATA[<p><strong>Note:</strong> This code isn&#8217;t really workable on a complex application. Don&#8217;t use it unless your system is basic CRUD.</p>

<p>While working on a new project, I was exhausted by all the <code>link_to</code> writing I had been doing. It was repetitive, and even though I was using proper object-based routes - it was still ugly. All of them were formatted the exact same way, it was just silly. Definitely not DRY.</p>

<p>I started refactoring this by making a helper to link to an object. It was specific - <code>link_to_group(NFGroup $group)</code>, <code>link_to_user(sfGuardUser $user)</code> and about the third time I wrote a nearly identical helper, I wrote another helper - <code>link_to_object(BaseObject $object, $route)</code>. This wasn&#8217;t pretty, and I wanted a simpler solution.</p>

<p>What I ended up with was an interface for objects that I wanted to be linkable. The interface provided a way to get the route, parameters for the route, and then used the <code>__toString()</code> method on the object for the link text.</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='sd'>/**</span>
<span class='sd'> * Makes an object easy to link to by passing it to the</span>
<span class='sd'> * linkableLink helper</span>
<span class='sd'> *</span>
<span class='sd'> * @author Graham Christensen &lt;graham@grahamc.com&gt;</span>
<span class='sd'> */</span>
<span class='k'>interface</span> <span class='nx'>NF_Linkable</span> <span class='p'>{</span>
	<span class='sd'>/**</span>
<span class='sd'>	 * Get the route</span>
<span class='sd'>	 * @return string The route</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>getRoute</span><span class='p'>();</span>

	<span class='sd'>/**</span>
<span class='sd'>	 * Get route parameters</span>
<span class='sd'>	 * @return array of route parameters</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>getParameters</span><span class='p'>();</span>

	<span class='sd'>/**</span>
<span class='sd'>	 * Get the text to use as link-text</span>
<span class='sd'>	 * @return string</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>__toString</span><span class='p'>();</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>The NF_Linkable interface, allowing it to be easily linked to in a symfony view. To use this, place it in lib/NF_Linkable.php</p>
</blockquote>

<p>My new helper is named <code>linkableLink(NF_Linkable $object)</code> and it will output a link, nice and simply. The helper is fairly straightforward too:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='sd'>/**</span>
<span class='sd'> * Link to any object extending NF_Linkable</span>
<span class='sd'> * @param NF_Linkable $object</span>
<span class='sd'> * @return string</span>
<span class='sd'> * @author Graham Christensen &lt;graham@grahamc.com&gt;</span>
<span class='sd'> */</span>
<span class='k'>function</span> <span class='nf'>linkableLink</span><span class='p'>(</span><span class='nx'>NF_Linkable</span> <span class='nv'>$object</span><span class='p'>)</span> <span class='p'>{</span>
	<span class='nv'>$url</span> <span class='o'>=</span> <span class='nv'>$object</span><span class='o'>-&gt;</span><span class='na'>getRoute</span><span class='p'>()</span> <span class='o'>.</span> <span class='s1'>&#39;?&#39;</span><span class='p'>;</span>
	<span class='nv'>$url</span> <span class='o'>.=</span> <span class='nb'>http_build_query</span><span class='p'>(</span><span class='nv'>$object</span><span class='o'>-&gt;</span><span class='na'>getParameters</span><span class='p'>());</span>

	<span class='k'>return</span> <span class='nx'>link_to</span><span class='p'>(</span><span class='nv'>$object</span><span class='p'>,</span> <span class='nv'>$url</span><span class='p'>);</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>This is pretty straightforward. It takes the object&#8217;s route, builds the query string from the parameters, and passes it along to symfony&#8217;s link_to helper. For those following along, place this in <code>lib/helpers/LinkableHelper.php</code></p>
</blockquote>

<p>To use this is simple enough, using the example of a group&#8217;s Propel object - we simply implement the interface&#8217;s methods:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>

<span class='sd'>/**</span>
<span class='sd'> * A group object which is linkable using linkableLink</span>
<span class='sd'> *</span>
<span class='sd'> * @author Graham Christensen &lt;graham@grahamc.com&gt;</span>
<span class='sd'> */</span>
<span class='k'>class</span> <span class='nc'>FieldGroup</span> <span class='k'>extends</span> <span class='nx'>BaseFieldGroup</span>
						<span class='k'>implements</span> <span class='nx'>NF_Linkable</span> <span class='p'>{</span>
	<span class='sd'>/**</span>
<span class='sd'>	 * Get the route to show a group</span>
<span class='sd'>	 * @return string</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>getRoute</span><span class='p'>()</span> <span class='p'>{</span>
		<span class='k'>return</span> <span class='s1'>&#39;@group_show&#39;</span><span class='p'>;</span>
	<span class='p'>}</span>

	<span class='sd'>/**</span>
<span class='sd'>	 * Get the route&#39;s parameters for building the final URL</span>
<span class='sd'>	 * @return array</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>getParameters</span><span class='p'>()</span> <span class='p'>{</span>
		<span class='k'>return</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;id&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getId</span><span class='p'>());</span>
	<span class='p'>}</span>

	<span class='sd'>/**</span>
<span class='sd'>	 * Get the text to appear between in &lt;a&gt;text&lt;/a&gt; tags</span>
<span class='sd'>	 * @return string</span>
<span class='sd'>	 */</span>
	<span class='k'>public</span> <span class='k'>function</span> <span class='nf'>__toString</span><span class='p'>()</span> <span class='p'>{</span>
		<span class='k'>return</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getName</span><span class='p'>();</span>
	<span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>This is an example of how I use the NF_Linkable interface. This would create a link to this particular group using the name as the link text. The URL generated would be something like <code>@group_show?id=1</code>, which</p>
</blockquote>

<p>symfony translates into <code>group/view/1</code></p>

<p>To then use this in your codebase, write a simple view:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='c1'>// Get a FieldGroup just for the example</span>
<span class='nv'>$group</span> <span class='o'>=</span> <span class='nx'>FieldGroupPeer</span><span class='o'>::</span><span class='na'>doSelectOne</span><span class='p'>(</span><span class='k'>new</span> <span class='nx'>Criteria</span><span class='p'>());</span>

<span class='nx'>use_helper</span><span class='p'>(</span><span class='s1'>&#39;Linkable&#39;</span><span class='p'>);</span>
<span class='k'>echo</span> <span class='nx'>linkableLink</span><span class='p'>(</span><span class='nv'>$group</span><span class='p'>);</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>]]></description>
        <link>http://grahamc.com/blog/making-objects-linkable-in-symfony</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/managing-remote-svn-branches-in-git-svn</guid>
        <title>Managing Remote SVN Branches in Git-SVN</title>
        <pubDate>Wed, 25 Aug 2010 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>This was a major problem I&#8217;ve been having with git-svn is how to handle remote branches. There is lots of documentation on SVN, switching to Git, using git-svn, but very little seemed to be related to creating remote branches and then switching to them.</p>

<p>Turns out it was pretty obvious:</p>

<p>To create the branch:</p>
<div class='highlight'><pre><code class='bash'>git svn branch foo
</code></pre>
</div>
<p>To switch to the branch:</p>
<div class='highlight'><pre><code class='bash'>git branch foo remotes/foo
</code></pre>
</div>
<p>To delete a remote branch you have to do it with SVN&#8217;s command line tool:</p>
<div class='highlight'><pre><code class='bash'>svn rm http://svn.foobar.org/branches/foo
</code></pre>
</div>]]></description>
        <link>http://grahamc.com/blog/managing-remote-svn-branches-in-git-svn</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/how-to-setup-sfpdosessionstorage</guid>
        <title>How to Setup sfPDOSessionStorage</title>
        <pubDate>Wed, 16 Jun 2010 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>Setting up sfPDOSessionStorage is a fairly simple matter to make sure that sessions exist on a setup with multiple web-heads.</p>

<p>Add the following code to your <code>app/app_name/config/factories.yml</code> file:</p>
<div class='highlight'><pre><code class='yaml'><span class='l-Scalar-Plain'>all</span><span class='p-Indicator'>:</span>
    <span class='l-Scalar-Plain'>storage</span><span class='p-Indicator'>:</span>
    <span class='l-Scalar-Plain'>class</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>sfPDOSessionStorage</span>
    <span class='l-Scalar-Plain'>param</span><span class='p-Indicator'>:</span>
      <span class='l-Scalar-Plain'>db_table</span><span class='p-Indicator'>:</span>    <span class='l-Scalar-Plain'>session</span>
      <span class='l-Scalar-Plain'>database</span><span class='p-Indicator'>:</span>    <span class='l-Scalar-Plain'>propel</span>
      <span class='c1'># Optional parameters</span>
      <span class='l-Scalar-Plain'>db_id_col</span><span class='p-Indicator'>:</span>   <span class='l-Scalar-Plain'>sess_id</span>
      <span class='l-Scalar-Plain'>db_data_col</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>sess_data</span>
      <span class='l-Scalar-Plain'>db_time_col</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>sess_time</span>
</code></pre>
</div>
<p>Make sure your remove all unnecessary references to setting a different storage mechanism</p>

<p>Now add the following YAML to your config/schema.yml file. This creates the table structure.</p>
<div class='highlight'><pre><code class='yaml'><span class='c1'># Session</span>
  <span class='l-Scalar-Plain'>session</span><span class='p-Indicator'>:</span>
    <span class='l-Scalar-Plain'>_attributes</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>{</span> <span class='nv'>phpName</span><span class='p-Indicator'>:</span> <span class='nv'>Session</span> <span class='p-Indicator'>}</span>
    <span class='l-Scalar-Plain'>sess_id</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>{</span> <span class='nv'>type</span><span class='p-Indicator'>:</span> <span class='nv'>varchar</span><span class='p-Indicator'>,</span> <span class='nv'>size</span><span class='p-Indicator'>:</span> <span class='nv'>64</span><span class='p-Indicator'>,</span>
               <span class='nv'>required</span><span class='p-Indicator'>:</span> <span class='nv'>true</span><span class='p-Indicator'>,</span> <span class='nv'>primaryKey</span><span class='p-Indicator'>:</span> <span class='nv'>true</span> <span class='p-Indicator'>}</span>
    <span class='l-Scalar-Plain'>sess_data</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>{</span> <span class='nv'>type</span><span class='p-Indicator'>:</span> <span class='nv'>longvarchar</span> <span class='p-Indicator'>}</span>
    <span class='l-Scalar-Plain'>sess_time</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>{</span> <span class='nv'>type</span><span class='p-Indicator'>:</span> <span class='nv'>INTEGER</span><span class='p-Indicator'>,</span> <span class='nv'>size</span><span class='p-Indicator'>:</span> <span class='s'>&#39;11&#39;</span><span class='p-Indicator'>}</span>
    <span class='l-Scalar-Plain'>_indexes</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>{</span> <span class='nv'>SESSIONTIME</span><span class='p-Indicator'>:</span> <span class='p-Indicator'>[</span><span class='nv'>sess_time</span><span class='p-Indicator'>]</span> <span class='p-Indicator'>}</span>
</code></pre>
</div>
<p>I try to keep the generated SQL as up to date as possible, so do that now.</p>
<div class='highlight'><pre><code class='bash'>./symfony cc
./symfony propel:build-sql
</code></pre>
</div>
<p>If you need to make this change to an existing dataaset, here is the raw SQL to create the table:</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>CREATE</span> <span class='k'>TABLE</span> <span class='ss'>`sessions`</span>
<span class='p'>(</span>
        <span class='ss'>`sess_id`</span> <span class='kt'>VARCHAR</span><span class='p'>(</span><span class='mi'>64</span><span class='p'>)</span>  <span class='k'>NOT</span> <span class='no'>NULL</span><span class='p'>,</span>
        <span class='ss'>`sess_data`</span> <span class='kt'>TEXT</span><span class='p'>,</span>
        <span class='ss'>`sess_time`</span> <span class='kt'>INTEGER</span><span class='p'>(</span><span class='mi'>11</span><span class='p'>),</span>
        <span class='k'>PRIMARY</span> <span class='k'>KEY</span> <span class='p'>(</span><span class='ss'>`sess_id`</span><span class='p'>),</span>
        <span class='k'>KEY</span> <span class='ss'>`SESSIONTIME`</span><span class='p'>(</span><span class='ss'>`sess_time`</span><span class='p'>)</span>
<span class='p'>)</span><span class='n'>Type</span><span class='o'>=</span><span class='n'>InnoDB</span><span class='p'>;</span>
</code></pre>
</div>
<blockquote>
<p>Note: If the session table is MyISAM, you&#8217;re going to hurt yourself with table-level locking. Making it InnoDB means row-level locking, and much better performance. Also, this only scales so far - eventually memcache is the solution.</p>
</blockquote>]]></description>
        <link>http://grahamc.com/blog/how-to-setup-sfpdosessionstorage</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/sending-mail-from-a-task-symfony-1-4</guid>
        <title>Sending Mail from a Task, Symfony 1.4; Fatal error: Class 'Swift_Message' not found</title>
        <pubDate>Mon, 22 Feb 2010 00:00:00 -0800</pubDate>
        <description><![CDATA[<p>While trying to build and send a fairly complicated e-mail using a template from within a task. Unfortunately that resulted in a fairly nasty (and annoying) bug with Symfony&#8217;s autoloader:</p>

<blockquote>
<p><code>Fatal error: Class &#39;Swift_Message&#39; not found in apps/lib/email/DomainReportMessage.class.php on line 3</code></p>
</blockquote>

<p>And then the task:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='k'>class</span> <span class='nc'>emailTestTask</span> <span class='k'>extends</span> <span class='nx'>sfBaseTask</span> <span class='p'>{</span>

    <span class='cm'>/* ... configure() - nothing special */</span>

    <span class='k'>protected</span> <span class='k'>function</span> <span class='nf'>execute</span><span class='p'>(</span><span class='nv'>$arguments</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>(),</span>
                                   <span class='nv'>$options</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>())</span> <span class='p'>{</span>

        <span class='c1'>// initialize the database connection</span>
        <span class='nv'>$databaseManager</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>sfDatabaseManager</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>configuration</span><span class='p'>);</span>
        <span class='nv'>$db</span> <span class='o'>=</span> <span class='nv'>$databaseManager</span><span class='o'>-&gt;</span><span class='na'>getDatabase</span><span class='p'>(</span><span class='nv'>$options</span><span class='p'>[</span><span class='s1'>&#39;connection&#39;</span><span class='p'>]);</span>
        <span class='nv'>$connection</span> <span class='o'>=</span> <span class='nv'>$db</span><span class='o'>-&gt;</span><span class='na'>getConnection</span><span class='p'>();</span>


        <span class='nv'>$c</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>DomainReportMessage</span><span class='p'>();</span>
        <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getMailer</span><span class='p'>()</span><span class='o'>-&gt;</span><span class='na'>send</span><span class='p'>(</span><span class='nv'>$c</span><span class='p'>);</span>
    <span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<p>The simple fix for this is to add a call to <code>$this-&gt;getMailer()</code> before you use the <code>Swift_Message</code> class, which seems like a fairly basic issue with symfony&#8217;s autoloader.</p>

<p>Here is the working code:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='k'>class</span> <span class='nc'>emailTestTask</span> <span class='k'>extends</span> <span class='nx'>sfBaseTask</span> <span class='p'>{</span>

    <span class='cm'>/* ... configure() - nothing special */</span>

    <span class='k'>protected</span> <span class='k'>function</span> <span class='nf'>execute</span><span class='p'>(</span><span class='nv'>$arguments</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>(),</span>
                                   <span class='nv'>$options</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>())</span> <span class='p'>{</span>

        <span class='c1'>// initialize the database connection</span>
        <span class='nv'>$databaseManager</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>sfDatabaseManager</span><span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>configuration</span><span class='p'>);</span>
        <span class='nv'>$db</span> <span class='o'>=</span> <span class='nv'>$databaseManager</span><span class='o'>-&gt;</span><span class='na'>getDatabase</span><span class='p'>(</span><span class='nv'>$options</span><span class='p'>[</span><span class='s1'>&#39;connection&#39;</span><span class='p'>]);</span>
        <span class='nv'>$connection</span> <span class='o'>=</span> <span class='nv'>$db</span><span class='o'>-&gt;</span><span class='na'>getConnection</span><span class='p'>();</span>

        <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getMailer</span><span class='p'>();</span> <span class='c1'>// These are the magic words</span>
        <span class='nv'>$c</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>DomainReportMessage</span><span class='p'>();</span>
        <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getMailer</span><span class='p'>()</span><span class='o'>-&gt;</span><span class='na'>send</span><span class='p'>(</span><span class='nv'>$c</span><span class='p'>);</span>
    <span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>]]></description>
        <link>http://grahamc.com/blog/sending-mail-from-a-task-symfony-1-4</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/validate-domains-pages-in-symfony-and-sfvalidator</guid>
        <title>Validate a Domain is Valid and Exists, Symfony 1.2</title>
        <pubDate>Tue, 27 Oct 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>After spending good portion of my day validating, parsing, and analyzing URLs - I find that I&#8217;ve written a small set of tools to ensure consistency, clean, and sane URLs. After an overhaul on a settings page - I had to integrate much of this into a simple (to the viewer, anyway) form. To ensure that user-entered URLs are valid, I&#8217;ve written a custom validator in <strong>Symfony 1.2</strong> to accomplish this validation.</p>

<h3 id='writing_a_custom_sfvalidator'>Writing a Custom sfValidator</h3>

<p>Writing a custom validator really isn&#8217;t as difficult as you would imagine. Open up one of the existing ones, and you&#8217;ll see that. Primarily, you only need to worry about two methods.</p>

<h4 id='configure'>configure()</h4>

<p>The configure method is where you can specify customization options, making some required or optional. This method is used to build flexibility into the validator.</p>

<h4 id='doclean'>doClean()</h4>

<p>The doClean method may seem confusing at first, however it&#8217;s very simple. Upon failure, throw an exception.</p>

<h5 id='how_to_signal_a_failure'>How to Signal a Failure</h5>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='k'>throw</span> <span class='k'>new</span> <span class='nx'>sfValidatorError</span><span class='p'>(</span><span class='nv'>$this</span><span class='p'>,</span> <span class='s1'>&#39;invalid&#39;</span><span class='p'>,</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;value&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$value</span><span class='p'>));</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p><code>invalid</code> is the name of the message you want to error with, and the options array at in the third parameter allow you to replace variables in the message.</p>
</blockquote>

<h5 id='how_to_handle_a_success'>How to Handle a Success</h5>

<p>If the validator is successful - you have two options:</p>

<ul>
<li>Your validator can act as a filter, and return something different from the input value</li>

<li>Your validator can return exactly what it was passed in.</li>
</ul>

<h3 id='implementing_the_new_sfvalidator_into_an_sfform'>Implementing the new sfValidator into an sfForm</h3>

<p>This validator is used just like any other:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='nv'>$form</span><span class='o'>-&gt;</span><span class='na'>setValidator</span><span class='p'>(</span><span class='s1'>&#39;domain&#39;</span><span class='p'>,</span> <span class='k'>new</span> <span class='nx'>sfValidatorDomain</span><span class='p'>());</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div><div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='sd'>/**</span>
<span class='sd'> * @author Graham Christensen &lt;graham@grahamc.com&gt;</span>
<span class='sd'>*/</span>
<span class='k'>class</span> <span class='nc'>sfValidatorDomain</span> <span class='k'>extends</span> <span class='nx'>sfValidatorBase</span>
<span class='p'>{</span>
  <span class='sd'>/**</span>
<span class='sd'>   * Configures the current validator.</span>
<span class='sd'>   *</span>
<span class='sd'>   *</span>
<span class='sd'>   * @param array $options    An array of options</span>
<span class='sd'>   * @param array $messages   An array of error messages</span>
<span class='sd'>   *</span>
<span class='sd'>   * @see sfValidatorBase</span>
<span class='sd'>   */</span>
  <span class='k'>protected</span> <span class='k'>function</span> <span class='nf'>configure</span><span class='p'>(</span><span class='nv'>$options</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>(),</span>
                                <span class='nv'>$messages</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>())</span> <span class='p'>{</span>
      <span class='c1'>// The type of method to use to validate it.</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addOption</span><span class='p'>(</span><span class='s1'>&#39;clean_type&#39;</span><span class='p'>,</span> <span class='s1'>&#39;url&#39;</span><span class='p'>);</span>

      <span class='c1'>// List of valid protocol schemes to allow in URLs</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addOption</span><span class='p'>(</span><span class='s1'>&#39;schemes&#39;</span><span class='p'>,</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;http&#39;</span><span class='p'>,</span> <span class='s1'>&#39;https&#39;</span><span class='p'>));</span>

      <span class='c1'>// The default scheme</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addOption</span><span class='p'>(</span><span class='s1'>&#39;default_scheme&#39;</span><span class='p'>,</span> <span class='s1'>&#39;http&#39;</span><span class='p'>);</span>

	  <span class='c1'>// Setup some basic error messages</span>
	  <span class='nv'>$msg</span> <span class='o'>=</span> <span class='s1'>&#39;The provided domain does not appear to be valid.&#39;</span><span class='p'>;</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addMessage</span><span class='p'>(</span><span class='s1'>&#39;badform&#39;</span><span class='p'>,</span> <span class='nv'>$msg</span><span class='p'>);</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addMessage</span><span class='p'>(</span><span class='s1'>&#39;badscheme&#39;</span><span class='p'>,</span> <span class='nv'>$msg</span><span class='p'>);</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addMessage</span><span class='p'>(</span><span class='s1'>&#39;nohost&#39;</span><span class='p'>,</span> <span class='nv'>$msg</span><span class='p'>);</span>
      <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>addMessage</span><span class='p'>(</span><span class='s1'>&#39;invalid&#39;</span><span class='p'>,</span> <span class='nv'>$msg</span><span class='p'>);</span>
  <span class='p'>}</span>

  <span class='sd'>/**</span>
<span class='sd'>   * @see sfValidatorBase</span>
<span class='sd'>   */</span>
  <span class='k'>protected</span> <span class='k'>function</span> <span class='nf'>doClean</span><span class='p'>(</span><span class='nv'>$value</span><span class='p'>)</span> <span class='p'>{</span>
      <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getOption</span><span class='p'>(</span><span class='s1'>&#39;clean_type&#39;</span><span class='p'>)</span> <span class='o'>==</span> <span class='s1'>&#39;domain&#39;</span><span class='p'>)</span> <span class='p'>{</span>
          <span class='c1'>// If it&#39;s a domain, then it&#39;s simple to check it.</span>
          <span class='nv'>$domain</span> <span class='o'>=</span> <span class='nv'>$value</span><span class='p'>;</span>
      <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
          <span class='c1'>// It&#39;s probably a complete URL, so check it in</span>
          <span class='c1'>// more depth.</span>

          <span class='c1'>// Verify that it can be parsed as a URL.</span>
          <span class='c1'>// Note: @&#39;s are bad practice, however if a method is</span>
          <span class='c1'>// being checked and we can&#39;t stop the error, then</span>
          <span class='c1'>// we want to hide it.</span>

          <span class='nv'>$parts</span> <span class='o'>=</span> <span class='o'>@</span><span class='nb'>parse_url</span><span class='p'>(</span><span class='nv'>$value</span><span class='p'>);</span> <span class='c1'>// May throw a warning</span>

          <span class='c1'>// If there is no scheme (http, https, etc.) then it&#39;s</span>
          <span class='c1'>// likely that parse_url parsed it incorrectly, so</span>
          <span class='c1'>// prepend a scheme and try again. if we don&#39;t do this,</span>
          <span class='c1'>// we may get &quot;example.com/foobar&quot; as our path.</span>
          <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>isset</span><span class='p'>(</span><span class='nv'>$parts</span><span class='p'>[</span><span class='s1'>&#39;scheme&#39;</span><span class='p'>]))</span> <span class='p'>{</span>
              <span class='nv'>$value</span> <span class='o'>=</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getOption</span><span class='p'>(</span><span class='s1'>&#39;default_scheme&#39;</span><span class='p'>)</span>
                       <span class='o'>.</span> <span class='s1'>&#39;://&#39;</span> <span class='o'>.</span> <span class='nv'>$value</span><span class='p'>;</span>
              <span class='nv'>$parts</span> <span class='o'>=</span> <span class='o'>@</span><span class='nb'>parse_url</span><span class='p'>(</span><span class='nv'>$value</span><span class='p'>);</span>
          <span class='p'>}</span>

          <span class='c1'>// If it wasn&#39;t parsed, then something was wrong.</span>
          <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nv'>$parts</span><span class='p'>)</span> <span class='p'>{</span>
              <span class='k'>throw</span> <span class='k'>new</span> <span class='nx'>sfValidatorError</span><span class='p'>(</span><span class='nv'>$this</span><span class='p'>,</span> <span class='s1'>&#39;badform&#39;</span><span class='p'>,</span>
                            <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;value&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$value</span><span class='p'>));</span>
          <span class='p'>}</span>

          <span class='c1'>// Validate that the scheme provided is valid</span>
          <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>in_array</span><span class='p'>(</span><span class='nv'>$parts</span><span class='p'>[</span><span class='s1'>&#39;scheme&#39;</span><span class='p'>],</span>
                        <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getOption</span><span class='p'>(</span><span class='s1'>&#39;schemes&#39;</span><span class='p'>)))</span> <span class='p'>{</span>
              <span class='k'>throw</span> <span class='k'>new</span> <span class='nx'>sfValidatorError</span><span class='p'>(</span><span class='nv'>$this</span><span class='p'>,</span> <span class='s1'>&#39;badscheme&#39;</span><span class='p'>,</span>
                            <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;value&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$value</span><span class='p'>));</span>
          <span class='p'>}</span>

          <span class='c1'>// Ensure that the host was found</span>
          <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>isset</span><span class='p'>(</span><span class='nv'>$parts</span><span class='p'>[</span><span class='s1'>&#39;host&#39;</span><span class='p'>]))</span> <span class='p'>{</span>
              <span class='k'>throw</span> <span class='k'>new</span> <span class='nx'>sfValidatorError</span><span class='p'>(</span><span class='nv'>$this</span><span class='p'>,</span> <span class='s1'>&#39;nohost&#39;</span><span class='p'>,</span>
                            <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;value&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$value</span><span class='p'>));</span>
          <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
              <span class='c1'>// Finally set the domain for the final, unified</span>
              <span class='c1'>// verification.</span>
              <span class='nv'>$domain</span> <span class='o'>=</span> <span class='nv'>$parts</span><span class='p'>[</span><span class='s1'>&#39;host&#39;</span><span class='p'>];</span>
          <span class='p'>}</span>
      <span class='p'>}</span>

      <span class='c1'>// Convert the domain to an IP address</span>
      <span class='nv'>$ip_address</span> <span class='o'>=</span> <span class='nb'>gethostbyname</span><span class='p'>(</span><span class='nv'>$domain</span><span class='p'>);</span>

      <span class='c1'>// Unfortunately, gethostbyname&#39;s only response if it</span>
      <span class='c1'>// fails, is returns the input $domain. Try to convert it</span>
      <span class='c1'>// to a packed IP address. If that fails, then it isn&#39;t a</span>
      <span class='c1'>// valid domain name.</span>
      <span class='k'>if</span> <span class='p'>(</span><span class='o'>@</span><span class='nb'>inet_pton</span><span class='p'>(</span><span class='nv'>$ip_address</span><span class='p'>))</span> <span class='p'>{</span>
          <span class='k'>return</span> <span class='nv'>$value</span><span class='p'>;</span>
      <span class='p'>}</span>

      <span class='c1'>// Didn&#39;t validate...</span>
    <span class='k'>throw</span> <span class='k'>new</span> <span class='nx'>sfValidatorError</span><span class='p'>(</span><span class='nv'>$this</span><span class='p'>,</span> <span class='s1'>&#39;invalid&#39;</span><span class='p'>,</span>
                    <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;value&#39;</span> <span class='o'>=&gt;</span> <span class='nv'>$value</span><span class='p'>));</span>
  <span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>Install this into lib/validator/sfValidatorDomain.class.php</p>
</blockquote>]]></description>
        <link>http://grahamc.com/blog/validate-domains-pages-in-symfony-and-sfvalidator</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/modifying-form-elements-in-symfony-1-2</guid>
        <title>Modifying Form Elements in Symfony 1.2</title>
        <pubDate>Thu, 15 Oct 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>As I found in recent development of an app, I needed to change one of Symfony&#8217;s form on the fly (more specifically, I needed to change a drop-down, <code>sfWidgetFormSelect</code>). After some looking, there wasn&#8217;t much documentation on this that I could find. My final solution was easy enough:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='nv'>$form</span> <span class='o'>=</span> <span class='k'>new</span> <span class='nx'>SomeFancyForm</span><span class='p'>();</span>
<span class='nv'>$new_choices</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;Selection 1&#39;</span><span class='p'>,</span> <span class='s1'>&#39;Selection 2&#39;</span><span class='p'>,</span> <span class='s1'>&#39;Selection 3&#39;</span><span class='p'>);</span>
<span class='nv'>$widget</span> <span class='o'>=</span> <span class='nv'>$form</span><span class='o'>-&gt;</span><span class='na'>getWidget</span><span class='p'>(</span><span class='s1'>&#39;select_widget_name&#39;</span><span class='p'>);</span>
<span class='nv'>$widget</span><span class='o'>-&gt;</span><span class='na'>setOption</span><span class='p'>(</span><span class='s1'>&#39;choices&#39;</span><span class='p'>,</span> <span class='nv'>$new_choices</span><span class='p'>);</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<p>Of course, that can easily be adapted to modify any option on any form - just find the appropriate option you want to adjust. Additionally, you may need to adjust the validator as well.</p>

<p>Relevant Documentation:</p>

<ul>
<li><a href='http://www.symfony-project.org/api/1_2/sfForm#method_getwidget'>sfForm API Documentation</a></li>

<li><a href='http://www.symfony-project.org/api/1_2/sfWidgetFormSelect'>sfWidgetFormSelect API Documentation</a></li>
</ul>]]></description>
        <link>http://grahamc.com/blog/modifying-form-elements-in-symfony-1-2</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/forcing-login-success-page-symfony-1-2-sfguard</guid>
        <title>Forcing Login Success Page, Symfony 1.2 + sfGuard</title>
        <pubDate>Mon, 28 Sep 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>Working on my latest project, we needed to force a specific page to be sent to after login. After quite a bit of searching, I went to the most logical location for this information: The README. Duh. <a href='http://www.symfony-project.org/plugins/sfGuardPlugin/3_1_3?tab=plugin_readme'>sfGuardPlugin v3.1.3 Readme</a></p>

<p>Unfortunately, Symfony&#8217;s documentation is notoriously sketchy, however this is verifiably functional.</p>

<p>Add the following to your <code>app.yml</code>:</p>
<div class='highlight'><pre><code class='yaml'><span class='l-Scalar-Plain'>all</span><span class='p-Indicator'>:</span>
  <span class='l-Scalar-Plain'>sf_guard_plugin</span><span class='p-Indicator'>:</span>
    <span class='l-Scalar-Plain'>success_signin_url</span><span class='p-Indicator'>:</span>      <span class='s'>&#39;@my_route?param=value&#39;</span>
    <span class='l-Scalar-Plain'>success_signout_url</span><span class='p-Indicator'>:</span>     <span class='l-Scalar-Plain'>module/action</span>
</code></pre>
</div>]]></description>
        <link>http://grahamc.com/blog/forcing-login-success-page-symfony-1-2-sfguard</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/ranking-items-in-a-database</guid>
        <title>Ranking Items in a Database</title>
        <pubDate>Sat, 05 Sep 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>At work recently, I was tasked to create a system that ranked items in a database, from least to greatest based on a time measurement. Originally I was quite blinded by the original code, which had used three nested queries, and a dozen variables of impenetrable names, a set of code I won&#8217;t be posting. Now, this isn&#8217;t a very hard task - but let me document the path through with I got to the simple solution. This idea wasn&#8217;t immediately obvious to me, or someone else who had quite a bit more experience on the topic - but here we are.</p>

<h3 id='the_dataset'>The Dataset</h3>

<p>The dataset that I&#8217;m ranking is much more complex, however the concept is still the same.</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>CREATE</span> <span class='k'>TABLE</span> <span class='ss'>`response`</span> <span class='p'>(</span>
	<span class='n'>id</span> <span class='kt'>INT</span><span class='p'>(</span><span class='mi'>11</span><span class='p'>)</span> <span class='kp'>AUTO_INCREMENT</span> <span class='k'>NOT</span> <span class='no'>NULL</span><span class='p'>,</span>
	<span class='kt'>time</span> <span class='kt'>FLOAT</span> <span class='k'>NOT</span> <span class='no'>NULL</span><span class='p'>,</span>
	<span class='n'>meta</span> <span class='kt'>VARCHAR</span><span class='p'>(</span><span class='mi'>255</span><span class='p'>),</span>
	<span class='k'>PRIMARY</span> <span class='k'>KEY</span><span class='p'>(</span><span class='n'>id</span><span class='p'>)</span>
<span class='p'>);</span>
</code></pre>
</div>
<h3 id='temporary_tablesish'>Temporary Tables&#8230;Ish.</h3>

<p>My first idea was to have a table that would be regenerated every <code>$increment</code> (probably an hour, maybe a minute when we were small.) These tables would be pretty simple, just:</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>CREATE</span> <span class='k'>TABLE</span> <span class='ss'>`response_ranking`</span> <span class='p'>(</span>
	<span class='n'>id</span> <span class='kt'>INT</span><span class='p'>(</span><span class='mi'>11</span><span class='p'>)</span> <span class='kp'>AUTO_INCREMENT</span> <span class='k'>NOT</span> <span class='no'>NULL</span><span class='p'>,</span>
	<span class='n'>response_id</span> <span class='kt'>INT</span><span class='p'>(</span><span class='mi'>11</span><span class='p'>)</span> <span class='k'>NOT</span> <span class='no'>NULL</span><span class='p'>,</span>
	<span class='k'>PRIMARY</span> <span class='k'>KEY</span><span class='p'>(</span><span class='n'>id</span><span class='p'>),</span>
	<span class='k'>FOREIGN</span> <span class='k'>KEY</span> <span class='p'>(</span><span class='n'>response_id</span><span class='p'>)</span> <span class='k'>REFERENCES</span> <span class='ss'>`response`</span> <span class='p'>(</span><span class='n'>id</span><span class='p'>)</span>
<span class='p'>);</span>
</code></pre>
</div>
<p>And then in order to populate the database with the appropriate ranks, we would run:</p>
<div class='highlight'><pre><code class='mysql'><span class='c1'>-- Truncate the table</span>
<span class='n'>TRUNCATE</span> <span class='k'>TABLE</span> <span class='n'>response_rank</span><span class='p'>;</span>

<span class='c1'>-- Put the data into the table in order by time.</span>
<span class='k'>INSERT</span> <span class='k'>INTO</span> <span class='nf'>response_rank</span> <span class='p'>(</span><span class='n'>response_id</span><span class='p'>,</span> <span class='kt'>time</span><span class='p'>)</span>
<span class='k'>SELECT</span> <span class='n'>id</span> <span class='k'>AS</span> <span class='n'>response_id</span><span class='p'>,</span> <span class='kt'>time</span>
<span class='k'>FROM</span> <span class='n'>response</span>
<span class='k'>ORDER</span> <span class='k'>BY</span> <span class='kt'>time</span><span class='p'>;</span>
</code></pre>
</div>
<p>The SQL code would take the data from the <code>response</code> table in order of time, fastest to slowest, and then insert it into the <code>response_rank</code> table. The <code>response_rank</code> table&#8217;s ID would then directly be their rank amongst that dataset. The first record would be the fastest, the 257<sup>th</sup> record is the 257<sup>th</sup> fastest, etc. In order to find the rank for a particular record, the query is quite simple too:</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>SELECT</span> <span class='n'>id</span> <span class='k'>AS</span> <span class='n'>rank</span>
<span class='k'>FROM</span> <span class='n'>response_rank</span>
<span class='k'>WHERE</span> <span class='n'>response_id</span> <span class='o'>=</span> <span class='o'>?</span><span class='p'>;</span>
</code></pre>
</div>
<h3 id='why_this_is_a_bad_idea_tm'>Why This is a Bad Idea (tm)</h3>

<p>For the number of records I&#8217;ll have and the size of the site, caching the data isn&#8217;t necessary. Adding that level of complexity to a smaller site isn&#8217;t worth the potential scalability it may provide.</p>

<h3 id='how_i_did_it'>How I Did It</h3>

<p>Now this may not be the most efficient way to do it, however I imagine it&#8217;s much closer to a Good Idea (tm).</p>

<p>Instead of regenerating indexes or pushing massive amounts of data, let&#8217;s use a simple database operation which the database can be easily optimized to do, if it isn&#8217;t already by adding an index to the time column.</p>

<p>I present to you, <em>The Better Way</em>:</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>SELECT</span> <span class='nf'>count</span><span class='p'>(</span><span class='mi'>1</span><span class='p'>)</span> <span class='k'>AS</span> <span class='n'>rank</span>
<span class='k'>FROM</span> <span class='n'>response</span>
<span class='k'>WHERE</span> <span class='kt'>time</span> <span class='o'>&lt;</span> <span class='o'>?</span><span class='p'>;</span>
</code></pre>
</div>
<p>When you run the query, <code>rank</code> is exactly the rank within the current dataset, with nothing waiting to be aggregated into the database, or an index needing to be regenerated.</p>

<p>Now I know, this is stupidly simple, but it wasn&#8217;t extremely obvious to me or my coworker - so maybe someone else is stuck on such a simple problem too. However, this also may not be the most efficient way to do it either - if there&#8217;s a better way, I&#8217;d love to know.</p>]]></description>
        <link>http://grahamc.com/blog/ranking-items-in-a-database</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/forcing-ssl-with-symfony-1-2</guid>
        <title>Forcing SSL and HTTPS with Redirects on Symfony 1.2, 1.3, 1.4</title>
        <pubDate>Tue, 01 Sep 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>Forcing SSL on certain modules and actions used to be pretty simple with Symfony&#8217;s sfSslRequirementPlugin, however since Symfony 1.2 came out - it isn&#8217;t necessarily compatible. I took a look around the internet for options, however I was rather unsatisfied with the options. Because I need to be able to secure modules and actions, I took it upon myself to create a better way to secure modules.</p>

<p>The code I wrote It is based off of <a href='http://www.saynotoflash.com/archives/symfony-1-2-redirect-specific-modules-and-actions-to-https-ssl/'>Say No To Flash</a>&#8217;s filter that they wrote, however I was generally displeased with their method. t loops over the list twice, and is generally a garble of logic that is a little bit hard to understand, and could probably be done better.</p>

<p>I was planning on making this system more complicated by specifying if SSL was enabled or disabled by default, however that became too distorted in the code to make good, logical sense that was easy to read and maintain.</p>

<h3 id='edit_your_filtersyml_file'>Edit your filters.yml File</h3>

<p>Open up your <code>apps/app_name/config/filters.yml</code> file, and add in after the security filter:</p>
<div class='highlight'><pre><code class='yaml'><span class='l-Scalar-Plain'>sslFilter</span><span class='p-Indicator'>:</span>
  <span class='l-Scalar-Plain'>class</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>sslFilter</span>
</code></pre>
</div>
<blockquote>
<p>This code tells Symfony to load and execute the filter you&#8217;ll be creating.</p>
</blockquote>

<p>It should look something like this:</p>
<div class='highlight'><pre><code class='yaml'><span class='l-Scalar-Plain'>rendering</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>~</span>

<span class='l-Scalar-Plain'>security</span><span class='p-Indicator'>:</span>  <span class='l-Scalar-Plain'>~</span>

<span class='l-Scalar-Plain'>sslFilter</span><span class='p-Indicator'>:</span>
  <span class='l-Scalar-Plain'>class</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>sslFilter</span>

<span class='l-Scalar-Plain'>cache</span><span class='p-Indicator'>:</span>     <span class='l-Scalar-Plain'>~</span>

<span class='l-Scalar-Plain'>common</span><span class='p-Indicator'>:</span>    <span class='l-Scalar-Plain'>~</span>

<span class='l-Scalar-Plain'>execution</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>~</span>
</code></pre>
</div>
<h3 id='edit_your_appyml_file'>Edit your app.yml File</h3>

<p>Open the <code>apps/app_name/config/app.yml</code> file, and add the following at the end:</p>
<div class='highlight'><pre><code class='yaml'><span class='l-Scalar-Plain'>all</span><span class='p-Indicator'>:</span>
  <span class='l-Scalar-Plain'>ssl</span><span class='p-Indicator'>:</span>
    <span class='l-Scalar-Plain'>strict</span><span class='p-Indicator'>:</span> <span class='l-Scalar-Plain'>true</span>
    <span class='l-Scalar-Plain'>modules</span><span class='p-Indicator'>:</span>
      <span class='p-Indicator'>-</span> <span class='p-Indicator'>{</span> <span class='nv'>module</span><span class='p-Indicator'>:</span> <span class='nv'>some_module</span> <span class='p-Indicator'>}</span>
      <span class='p-Indicator'>-</span> <span class='p-Indicator'>{</span> <span class='nv'>module</span><span class='p-Indicator'>:</span> <span class='nv'>another_module</span> <span class='p-Indicator'>}</span>
      <span class='p-Indicator'>-</span> <span class='p-Indicator'>{</span> <span class='nv'>module</span><span class='p-Indicator'>:</span> <span class='nv'>insecure_module</span><span class='p-Indicator'>,</span> <span class='nv'>action</span><span class='p-Indicator'>:</span> <span class='nv'>secure_action</span> <span class='p-Indicator'>}</span>
      <span class='p-Indicator'>-</span> <span class='p-Indicator'>{</span> <span class='nv'>module</span><span class='p-Indicator'>:</span> <span class='nv'>insecure_module</span><span class='p-Indicator'>,</span> <span class='nv'>action</span><span class='p-Indicator'>:</span> <span class='nv'>another_secure_action</span> <span class='p-Indicator'>}</span>
</code></pre>
</div>
<blockquote>
<p>In the previous code, the <code>strict: true</code> code forces strict checking. Strict</p>
</blockquote>

<p>checking means that if someone accesses a URL that isn&#8217;t specified as secure via HTTPS, it will redirect them to the HTTP. If strict is set to false, it will allow them to access any module through HTTPS.</p>

<p>After that, the <code>- { module: insecure_module, action: another_secure_action }</code> code is how you set each module and action. If you want an entire module to be secure, don&#8217;t include the action section of that, however you need a line like that for every module and action you want to secure.</p>

<h3 id='create_a_filter'>Create a Filter</h3>

<p>Create a file in <code>apps/app_name/lib/</code> named <code>sfSslFilter.class.php</code>, and put in it:</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='sd'>/**</span>
<span class='sd'> * @author Graham Christensen</span>
<span class='sd'> *          graham@grahamc.com</span>
<span class='sd'> */</span>
<span class='k'>class</span> <span class='nc'>sslFilter</span> <span class='k'>extends</span> <span class='nx'>sfFilter</span> <span class='p'>{</span>
    <span class='k'>public</span> <span class='k'>function</span> <span class='nf'>execute</span> <span class='p'>(</span><span class='nv'>$filterChain</span><span class='p'>)</span> <span class='p'>{</span>
        <span class='nv'>$context</span> <span class='o'>=</span> <span class='nv'>$this</span><span class='o'>-&gt;</span><span class='na'>getContext</span><span class='p'>();</span>
        <span class='nv'>$request</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getRequest</span><span class='p'>();</span>

        <span class='c1'>// Perform strict checking of security</span>
        <span class='c1'>// IE: If it&#39;s HTTPS and shouldn&#39;t be, make it HTTP</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='nx'>sfConfig</span><span class='o'>::</span><span class='na'>has</span><span class='p'>(</span><span class='s1'>&#39;app_ssl_strict&#39;</span><span class='p'>))</span> <span class='p'>{</span>
            <span class='nv'>$only_explicit</span> <span class='o'>=</span> <span class='p'>(</span><span class='nx'>bool</span><span class='p'>)</span>
                             <span class='nx'>sfConfig</span><span class='o'>::</span><span class='na'>get</span><span class='p'>(</span><span class='s1'>&#39;app_ssl_strict&#39;</span><span class='p'>);</span>
        <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
            <span class='nv'>$only_explicit</span> <span class='o'>=</span> <span class='k'>false</span><span class='p'>;</span>
        <span class='p'>}</span>

        <span class='c1'>// Get a list of all the modules to check for</span>
        <span class='nv'>$modules</span> <span class='o'>=</span> <span class='nx'>sfConfig</span><span class='o'>::</span><span class='na'>get</span><span class='p'>(</span><span class='s1'>&#39;app_ssl_modules&#39;</span><span class='p'>);</span>

        <span class='c1'>// Set the modules variable to an array, this is</span>
        <span class='c1'>// if it&#39;s not configured for this particular environment.</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>is_array</span><span class='p'>(</span><span class='nv'>$modules</span><span class='p'>))</span> <span class='p'>{</span>
            <span class='nv'>$modules</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>();</span>
        <span class='p'>}</span>

        <span class='c1'>// Store the module name and action name into variables</span>
        <span class='c1'>// to simplify the code, and reduce function calls.</span>
        <span class='nv'>$module_name</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getModuleName</span><span class='p'>();</span>
        <span class='nv'>$action_name</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getActionName</span><span class='p'>();</span>

        <span class='c1'>// Check if the current request matches a security module</span>
        <span class='c1'>// If the module or module &amp; action is specified, then</span>
        <span class='c1'>// ensure it&#39;s correctly set.</span>
        <span class='nv'>$listed</span> <span class='o'>=</span> <span class='k'>false</span><span class='p'>;</span>
        <span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$modules</span> <span class='k'>as</span> <span class='nv'>$action</span><span class='p'>)</span> <span class='p'>{</span>
            <span class='c1'>// If the module name is listed</span>
            <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;module&#39;</span><span class='p'>]</span> <span class='o'>==</span> <span class='nv'>$module_name</span><span class='p'>)</span> <span class='p'>{</span>
                <span class='c1'>// If the whole module is listed, or the action</span>
                <span class='c1'>// specifically</span>
                <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>isset</span><span class='p'>(</span><span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;action&#39;</span><span class='p'>])</span>
                    <span class='o'>||</span> <span class='nv'>$action_name</span> <span class='o'>==</span> <span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;action&#39;</span><span class='p'>])</span> <span class='p'>{</span>
                    <span class='nv'>$listed</span> <span class='o'>=</span> <span class='k'>true</span><span class='p'>;</span>
                    <span class='k'>break</span><span class='p'>;</span>
                <span class='p'>}</span>
            <span class='p'>}</span>
        <span class='p'>}</span>

        <span class='nv'>$is_secure</span> <span class='o'>=</span> <span class='nv'>$request</span><span class='o'>-&gt;</span><span class='na'>isSecure</span><span class='p'>();</span>

        <span class='c1'>// If modules have to be explicitly listed, it is</span>
        <span class='c1'>// secure, and it&#39;s not listed - then redirect</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$only_explicit</span> <span class='o'>&amp;&amp;</span> <span class='nv'>$is_secure</span> <span class='o'>&amp;&amp;</span> <span class='o'>!</span><span class='nv'>$listed</span><span class='p'>)</span> <span class='p'>{</span>
            <span class='k'>return</span> <span class='nx'>self</span><span class='o'>::</span><span class='na'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>);</span>
        <span class='p'>}</span>

        <span class='c1'>// If it&#39;s not secure, and it&#39;s listed as having to be</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nv'>$is_secure</span> <span class='o'>&amp;&amp;</span> <span class='nv'>$listed</span><span class='p'>)</span> <span class='p'>{</span>
            <span class='k'>return</span> <span class='nx'>self</span><span class='o'>::</span><span class='na'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>);</span>
        <span class='p'>}</span>

        <span class='c1'>// Continue on with the chain, but it will only do that if</span>
        <span class='c1'>// we didn&#39;t need to redirect.</span>
        <span class='nv'>$filterChain</span><span class='o'>-&gt;</span><span class='na'>execute</span><span class='p'>();</span>
    <span class='p'>}</span>

    <span class='k'>public</span> <span class='k'>static</span> <span class='k'>function</span> <span class='nf'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>)</span> <span class='p'>{</span>
        <span class='nv'>$request</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getRequest</span><span class='p'>();</span>
        <span class='nv'>$controller</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getController</span><span class='p'>();</span>

        <span class='c1'>// Determine which direction we want to go</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$request</span><span class='o'>-&gt;</span><span class='na'>isSecure</span><span class='p'>())</span> <span class='p'>{</span>
            <span class='c1'>// Switch to insecure</span>
            <span class='nv'>$from</span> <span class='o'>=</span> <span class='s1'>&#39;https://&#39;</span><span class='p'>;</span>
            <span class='nv'>$to</span>   <span class='o'>=</span> <span class='s1'>&#39;http://&#39;</span><span class='p'>;</span>
        <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
            <span class='c1'>// Switch to secure</span>
            <span class='nv'>$from</span> <span class='o'>=</span> <span class='s1'>&#39;http://&#39;</span><span class='p'>;</span>
            <span class='nv'>$to</span>   <span class='o'>=</span> <span class='s1'>&#39;https://&#39;</span><span class='p'>;</span>
        <span class='p'>}</span>

        <span class='nv'>$redirect_to</span> <span class='o'>=</span> <span class='nb'>str_replace</span><span class='p'>(</span><span class='nv'>$from</span><span class='p'>,</span> <span class='nv'>$to</span><span class='p'>,</span> <span class='nv'>$request</span><span class='o'>-&gt;</span><span class='na'>getUri</span><span class='p'>());</span>
        <span class='k'>return</span> <span class='nv'>$controller</span><span class='o'>-&gt;</span><span class='na'>redirect</span><span class='p'>(</span><span class='nv'>$redirect_to</span><span class='p'>,</span> <span class='m'>0</span><span class='p'>,</span> <span class='m'>301</span><span class='p'>);</span>
    <span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<p>The beginning of this is pretty simple, it just gets the configuration settings outlined in the <code>app.yml</code> file, and then goes to town doing it&#8217;s job.</p>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?</span>
<span class='c1'>// Check if the current request matches a security module</span>
<span class='c1'>// If the module or module &amp; action is specified, then</span>
<span class='c1'>// ensure it&#39;s correctly set.</span>
<span class='nv'>$listed</span> <span class='o'>=</span> <span class='k'>false</span><span class='p'>;</span>
<span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$modules</span> <span class='k'>as</span> <span class='nv'>$action</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='c1'>// If the module name is listed</span>
    <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;module&#39;</span><span class='p'>]</span> <span class='o'>==</span> <span class='nv'>$module_name</span><span class='p'>)</span> <span class='p'>{</span>
        <span class='c1'>// If the whole module is listed, or the action</span>
        <span class='c1'>// specifically</span>
        <span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nb'>isset</span><span class='p'>(</span><span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;action&#39;</span><span class='p'>])</span>
            <span class='o'>||</span> <span class='nv'>$action_name</span> <span class='o'>==</span> <span class='nv'>$action</span><span class='p'>[</span><span class='s1'>&#39;action&#39;</span><span class='p'>])</span> <span class='p'>{</span>
            <span class='nv'>$listed</span> <span class='o'>=</span> <span class='k'>true</span><span class='p'>;</span>
            <span class='k'>break</span><span class='p'>;</span>
        <span class='p'>}</span>
    <span class='p'>}</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>That code goes over every module in the app.yml file, and sees if the current requests&#8217; module matches, or if the module and action matches. If it does, it sets $listed to true and exits the loop. This tells the code that it is needs to ensure security on the current request.</p>
</blockquote>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span><span class='o'>&gt;</span>
<span class='c1'>// If modules have to be explicitly listed, it is</span>
<span class='c1'>// secure, and it&#39;s not listed - then redirect</span>
<span class='k'>if</span> <span class='p'>(</span><span class='nv'>$only_explicit</span> <span class='o'>&amp;&amp;</span> <span class='nv'>$is_secure</span> <span class='o'>&amp;&amp;</span> <span class='o'>!</span><span class='nv'>$listed</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='k'>return</span> <span class='nx'>self</span><span class='o'>::</span><span class='na'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>);</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>That code ensures that if explicit checking is on and that the request is currently using HTTPS and it shouldn&#8217;t be, it is redirected to become HTTP.</p>
</blockquote>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='c1'>// If it&#39;s not secure, and it&#39;s listed as having to be</span>
<span class='k'>if</span> <span class='p'>(</span><span class='o'>!</span><span class='nv'>$is_secure</span> <span class='o'>&amp;&amp;</span> <span class='nv'>$listed</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='k'>return</span> <span class='nx'>self</span><span class='o'>::</span><span class='na'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>);</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>If the module/action is listed as needing to be secure and it isn&#8217;t, then perform the redirect.</p>
</blockquote>
<div class='highlight'><pre><code class='php'><span class='cp'>&lt;?php</span>
<span class='k'>public</span> <span class='k'>static</span> <span class='k'>function</span> <span class='nf'>doRedirect</span><span class='p'>(</span><span class='nv'>$context</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='nv'>$request</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getRequest</span><span class='p'>();</span>
    <span class='nv'>$controller</span> <span class='o'>=</span> <span class='nv'>$context</span><span class='o'>-&gt;</span><span class='na'>getController</span><span class='p'>();</span>

    <span class='c1'>// Determine which direction we want to go</span>
    <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$request</span><span class='o'>-&gt;</span><span class='na'>isSecure</span><span class='p'>())</span> <span class='p'>{</span>
        <span class='c1'>// Switch to insecure</span>
        <span class='nv'>$from</span> <span class='o'>=</span> <span class='s1'>&#39;https://&#39;</span><span class='p'>;</span>
        <span class='nv'>$to</span>   <span class='o'>=</span> <span class='s1'>&#39;http://&#39;</span><span class='p'>;</span>
    <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
        <span class='c1'>// Switch to secure</span>
        <span class='nv'>$from</span> <span class='o'>=</span> <span class='s1'>&#39;http://&#39;</span><span class='p'>;</span>
        <span class='nv'>$to</span>   <span class='o'>=</span> <span class='s1'>&#39;https://&#39;</span><span class='p'>;</span>
    <span class='p'>}</span>

    <span class='nv'>$redirect_to</span> <span class='o'>=</span> <span class='nb'>str_replace</span><span class='p'>(</span><span class='nv'>$from</span><span class='p'>,</span> <span class='nv'>$to</span><span class='p'>,</span> <span class='nv'>$request</span><span class='o'>-&gt;</span><span class='na'>getUri</span><span class='p'>());</span>
    <span class='k'>return</span> <span class='nv'>$controller</span><span class='o'>-&gt;</span><span class='na'>redirect</span><span class='p'>(</span><span class='nv'>$redirect_to</span><span class='p'>,</span> <span class='m'>0</span><span class='p'>,</span> <span class='m'>301</span><span class='p'>);</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>
<blockquote>
<p>The previous method is really pretty simple. If doRequest is called, it means that the current protocol is not valid. So, if it is HTTP, make it tHTTPS. If it&#8217;s HTTPS, make it HTTP.</p>
</blockquote>

<h3 id='finishing_up'>Finishing Up</h3>

<p>When you&#8217;re finishing up, make sure you clear your cache via <code>./symfony cc</code> and then test it on your site. Make sure that your strict option is working, and you should check each individual module and action to make sure you didn&#8217;t forget anything.</p>]]></description>
        <link>http://grahamc.com/blog/forcing-ssl-with-symfony-1-2</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/sane-pre-commit-hooks-for-symfony-git</guid>
        <title>Sane Pre-Commit Hooks for Symfony + Git</title>
        <pubDate>Mon, 24 Aug 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>Throughout my history of working with Symfony, I&#8217;ve noticed a trend that I&#8217;ll make a minor edit in a database configuration file, forget to actually regenerate the models and forms, commit the edit, and then find several days later (when I do want to regenerate the models) that they&#8217;re breaking. I then do this little dance of going through the history finding out where exactly I went wrong.</p>

<p>Today I was working alongside <a href='http://www.phpcult.com/blog'>Vid Luther</a> and running into peculiar problems. Lo and behold, it was a minor edit that I had forgotten to test. Dammit. Company policy is pushups for fuckups, and so well.. you know.</p>

<p>I began thinking about switching back to Subversion for the pre-commit hooks, as I stupidly forgot that Git <em>must</em> have them too. (The lack of a centralized server threw me off.) I did a bit of research, found that, in fact, Git does have them - and in a way that I much prefer. Thus the development began of, essentially, a locally-run continuous-integration script to verify that none of the developers (including myself) screw anything up.</p>

<p>Behold, The Symfony Pre-Commit Hook For Git:</p>
<div class='highlight'><pre><code class='php'><span class='x'>#!/usr/bin/env php</span>
<span class='cp'>&lt;?php</span>
<span class='sd'>/**</span>
<span class='sd'> * @author Graham Christensen &lt;graham@grahamc.com&gt;</span>
<span class='sd'> * @license Here, just take it.</span>
<span class='sd'> */</span>

<span class='c1'>// A list of commands you want to run on the entire codebase.</span>
<span class='c1'>// You could also add in tests</span>
<span class='nv'>$test_commands</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>(</span><span class='s1'>&#39;./symfony propel:build-sql&#39;</span><span class='p'>,</span>
                       <span class='s1'>&#39;./symfony propel:build-model&#39;</span><span class='p'>,</span>
                       <span class='s1'>&#39;./symfony propel:build-forms&#39;</span><span class='p'>,</span>
                       <span class='s1'>&#39;./symfony propel:build-filters&#39;</span><span class='p'>,</span>
                       <span class='s1'>&#39;./symfony propel:insert-sql --no-confirmation&#39;</span><span class='p'>,</span>
                       <span class='s1'>&#39;./symfony propel:data-load&#39;</span><span class='p'>);</span>

<span class='c1'>// This is pretty static, since the git repository doesn&#39;t move</span>
<span class='nv'>$repository_parent_directory</span> <span class='o'>=</span> <span class='nb'>realpath</span><span class='p'>(</span><span class='nx'>__DIR__</span> <span class='o'>.</span> <span class='s1'>&#39;/../../&#39;</span><span class='p'>);</span>

<span class='c1'>// Where to put the testing directory. It cleans up after itself, I</span>
<span class='c1'>// promise. Note: if the testing directory is inside the</span>
<span class='c1'>// repository&#39;s parent directory, it might get stuck in an infinite</span>
<span class='c1'>// copy loop.</span>
<span class='nv'>$test_parent_directory</span> <span class='o'>=</span> <span class='s1'>&#39;/tmp/&#39;</span><span class='p'>;</span>

<span class='c1'>// Negotiate a temporary directory that doesn&#39;t exist yet, so</span>
<span class='c1'>// it doesn&#39;t get in the way of anything already there.</span>
<span class='nv'>$i</span> <span class='o'>=</span> <span class='m'>0</span><span class='p'>;</span>
<span class='k'>do</span> <span class='p'>{</span>
    <span class='nv'>$test_directory</span> <span class='o'>=</span> <span class='nv'>$test_parent_directory</span>
                    <span class='o'>.</span> <span class='s1'>&#39;/git_pre_commit_hook_&#39;</span> <span class='o'>.</span> <span class='nv'>$i</span><span class='o'>++</span><span class='p'>;</span>
<span class='p'>}</span> <span class='k'>while</span> <span class='p'>(</span><span class='nb'>file_exists</span><span class='p'>(</span><span class='nv'>$test_directory</span><span class='p'>));</span>

<span class='c1'>// Create a testing environment</span>
<span class='nx'>debug</span><span class='p'>(</span><span class='s1'>&#39;Copying the working copy from &#39;</span>
      <span class='o'>.</span> <span class='nv'>$repository_parent_directory</span> <span class='o'>.</span> <span class='s1'>&#39; to &#39;</span> <span class='o'>.</span> <span class='nv'>$test_directory</span><span class='p'>);</span>
<span class='nb'>mkdir</span><span class='p'>(</span><span class='nv'>$test_directory</span><span class='p'>);</span>

<span class='c1'>// the run_command function is used for easy debugging of what&#39;s</span>
<span class='c1'>// actually being executed.</span>
<span class='nv'>$pdir</span> <span class='o'>=</span> <span class='nb'>escapeshellarg</span><span class='p'>(</span><span class='nv'>$repository_parent_directory</span> <span class='o'>.</span> <span class='s1'>&#39;/&#39;</span><span class='p'>);</span>
<span class='nv'>$tdir</span> <span class='o'>=</span> <span class='nb'>escapeshellarg</span><span class='p'>(</span><span class='nv'>$test_directory</span><span class='p'>);</span>
<span class='nx'>run_command</span><span class='p'>(</span><span class='s1'>&#39;cp -r &#39;</span> <span class='o'>.</span> <span class='nv'>$pdir</span> <span class='o'>.</span> <span class='s1'>&#39; &#39;</span> <span class='o'>.</span> <span class='nv'>$tdir</span><span class='p'>;</span>

<span class='c1'>// Get into it, start running the test commands</span>
<span class='nb'>chdir</span><span class='p'>(</span><span class='nv'>$test_directory</span><span class='p'>);</span>

<span class='c1'>// Iterate over all the commands. This has to happen one by one in</span>
<span class='c1'>// order to catch the errors as they happen. Also, the debugging</span>
<span class='c1'>// code is the same.</span>
<span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$test_commands</span> <span class='k'>as</span> <span class='nv'>$command</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='c1'>// Create error files within the testing directory so they&#39;re</span>
    <span class='c1'>// cleaned up nicely</span>
    <span class='nv'>$error_file</span> <span class='o'>=</span> <span class='nv'>$test_directory</span> <span class='o'>.</span> <span class='s1'>&#39;/errfile_&#39;</span>
                  <span class='o'>.</span> <span class='nb'>md5</span><span class='p'>(</span><span class='nv'>$command</span> <span class='o'>.</span> <span class='nb'>mt_rand</span><span class='p'>())</span> <span class='o'>.</span> <span class='s1'>&#39;.err_log&#39;</span><span class='p'>;</span>

    <span class='c1'>// Pipe ALL of the command&#39;s output to the file for convenient</span>
    <span class='c1'>// error messages.</span>
    <span class='nv'>$cmd</span> <span class='o'>=</span> <span class='nv'>$command</span> <span class='o'>.</span> <span class='s1'>&#39; &gt; &#39;</span> <span class='o'>.</span> <span class='nv'>$error_file</span> <span class='o'>.</span> <span class='s1'>&#39; 2&gt;&amp;1&#39;</span><span class='p'>;</span>
    <span class='nb'>exec</span><span class='p'>(</span><span class='nv'>$cmd</span><span class='p'>,</span> <span class='nv'>$r</span><span class='p'>,</span> <span class='nv'>$return_code</span><span class='p'>);</span>

    <span class='c1'>// Symfony doesn&#39;t always return something other than 0 when</span>
    <span class='c1'>// errors occur. Because of that you have to test for both</span>
    <span class='c1'>// conditions, note that because errorsInLog is second - it is</span>
    <span class='c1'>// only executed if the first one doesn&#39;t pass which saves time</span>
    <span class='c1'>// if Symfony does what it should be.</span>
    <span class='k'>if</span> <span class='p'>(</span><span class='nv'>$return_code</span> <span class='o'>!=</span> <span class='m'>0</span> <span class='o'>||</span> <span class='nx'>errorsInLog</span><span class='p'>(</span><span class='nv'>$error_file</span><span class='p'>))</span> <span class='p'>{</span>
        <span class='c1'>// because $error_code isn&#39;t always 1 when it fails, set it</span>
        <span class='nv'>$return_code</span> <span class='o'>=</span> <span class='m'>1</span><span class='p'>;</span>
        <span class='nx'>debug</span><span class='p'>(</span><span class='nv'>$command</span> <span class='o'>.</span> <span class='s1'>&#39;: Failue.&#39;</span><span class='p'>);</span>
        <span class='nx'>debug</span><span class='p'>(</span><span class='nb'>file</span><span class='p'>(</span><span class='nv'>$error_file</span><span class='p'>));</span>
        <span class='k'>break</span><span class='p'>;</span>
    <span class='p'>}</span> <span class='k'>else</span> <span class='p'>{</span>
        <span class='nx'>debug</span><span class='p'>(</span><span class='nv'>$command</span> <span class='o'>.</span> <span class='s1'>&#39;: Success.&#39;</span><span class='p'>);</span>
    <span class='p'>}</span>
<span class='p'>}</span>

<span class='c1'>// Delete the temporary testing location</span>
<span class='nx'>debug</span><span class='p'>(</span><span class='s1'>&#39;Removing &#39;</span> <span class='o'>.</span> <span class='nv'>$test_directory</span><span class='p'>);</span>
<span class='nb'>chdir</span><span class='p'>(</span><span class='nv'>$repository_parent_directory</span><span class='p'>);</span>
<span class='nb'>shell_exec</span><span class='p'>(</span><span class='s1'>&#39;rm -rf &#39;</span> <span class='o'>.</span> <span class='nv'>$test_directory</span><span class='p'>);</span>

<span class='c1'>// Git reads the returning error code. At this point, $return_code</span>
<span class='c1'>// is either set to 0 by succesfull executions, or 1 by a failure;</span>
<span class='c1'>// so exit with the correct status.</span>
<span class='k'>exit</span><span class='p'>(</span><span class='nv'>$return_code</span><span class='p'>);</span>

<span class='c1'>// Check for errors on the provided log file. They don&#39;t</span>
<span class='c1'>// necessarily have a standard format, so check a few things that</span>
<span class='c1'>// are generally common.</span>
<span class='k'>function</span> <span class='nf'>errorsInLog</span><span class='p'>(</span><span class='nv'>$logfile</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='nv'>$emsgs</span> <span class='o'>=</span> <span class='k'>array</span><span class='p'>();</span>
    <span class='nv'>$emsgs</span><span class='p'>[]</span> <span class='o'>=</span> <span class='s1'>&#39;If the exception message is not clear enough, &#39;</span>
             <span class='o'>.</span> <span class='s1'>&#39;read the output of the task for more information&#39;</span><span class='p'>;</span>
    <span class='nv'>$emsgs</span><span class='p'>[]</span> <span class='o'>=</span> <span class='s1'>&#39;Some problems occurred when executing the task:&#39;</span><span class='p'>;</span>
    <span class='nv'>$emsgs</span><span class='p'>[]</span> <span class='o'>=</span> <span class='s1'>&#39;Aborting&#39;</span><span class='p'>;</span>

    <span class='c1'>// This could be optimized to fgets the file line by line</span>
    <span class='k'>foreach</span> <span class='p'>(</span><span class='nb'>file</span><span class='p'>(</span><span class='nv'>$logfile</span><span class='p'>)</span> <span class='k'>as</span> <span class='nv'>$line</span><span class='p'>)</span> <span class='p'>{</span>
        <span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$emsgs</span> <span class='k'>as</span> <span class='nv'>$error</span><span class='p'>)</span> <span class='p'>{</span>
            <span class='k'>if</span> <span class='p'>(</span><span class='nb'>strstr</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>,</span> <span class='nv'>$error</span><span class='p'>))</span> <span class='p'>{</span>
                <span class='k'>return</span> <span class='k'>true</span><span class='p'>;</span>
            <span class='p'>}</span>
        <span class='p'>}</span>
    <span class='p'>}</span>
    <span class='k'>return</span> <span class='k'>false</span><span class='p'>;</span>
<span class='p'>}</span>

<span class='c1'>// Handle debug messages, recursively if necessary.</span>
<span class='k'>function</span> <span class='nf'>debug</span><span class='p'>(</span><span class='nv'>$message</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='k'>if</span> <span class='p'>(</span><span class='nb'>is_array</span><span class='p'>(</span><span class='nv'>$message</span><span class='p'>))</span> <span class='p'>{</span>
        <span class='k'>foreach</span> <span class='p'>(</span><span class='nv'>$message</span> <span class='k'>as</span> <span class='nv'>$line</span><span class='p'>)</span> <span class='p'>{</span>
            <span class='nx'>debug</span><span class='p'>(</span><span class='nv'>$line</span><span class='p'>);</span>
        <span class='p'>}</span>
    <span class='k'>return</span><span class='p'>;</span>
    <span class='p'>}</span>
    <span class='k'>echo</span> <span class='nb'>trim</span><span class='p'>(</span><span class='nv'>$message</span><span class='p'>)</span> <span class='o'>.</span> <span class='s2'>&quot;</span><span class='se'>\n</span><span class='s2'>&quot;</span><span class='p'>;</span>
<span class='p'>}</span>

<span class='c1'>// This function could easily be switched out to dump the exact</span>
<span class='c1'>// command being executed, which can be quite handy.</span>
<span class='k'>function</span> <span class='nf'>run_command</span><span class='p'>(</span><span class='nv'>$command</span><span class='p'>)</span> <span class='p'>{</span>
    <span class='nb'>shell_exec</span><span class='p'>(</span><span class='nv'>$command</span><span class='p'>);</span>
<span class='p'>}</span>
<span class='cp'>?&gt;</span><span class='x' />
</code></pre>
</div>]]></description>
        <link>http://grahamc.com/blog/sane-pre-commit-hooks-for-symfony-git</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/what-not-to-do-ever</guid>
        <title>Business: What to do, and what not to do</title>
        <pubDate>Tue, 21 Jul 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<h3 id='what_you_shouldnt__do'>What You Shouldn&#8217;t <em>Ever</em> Do</h3>

<h4 id='even_if_youre_starving'>Even If You&#8217;re Starving</h4>

<ul>
<li>Write bad checks, even if you can promise that the money will be there.</li>

<li>Under-value your services. If you are good, they will pay. If they won&#8217;t pay, chance are they aren&#8217;t worth it.</li>

<li>Over-promise on what you can deliver. Do what they want, and later on see what you can do to improve their project.</li>

<li>Under-deliver and let them be disappointed.</li>

<li>Give unrealistic deadlines. A salesman might say its good for sales, but your development team will hate you, and you will lose them.</li>

<li>Take flat-rate projects. These are screaming feature creep, and they have probably have no budget for it.</li>

<li>Allow feature-creep for free. Feature creep is a natural part of a project. Clients don&#8217;t know everything that they want, and will refine and expand the project as it goes. This is ok, but not if they don&#8217;t pay for it.</li>

<li>Let the client strangle you. If they can&#8217;t be pleased and won&#8217;t pay, make sure your company can survive to finish the project. Be willing to drop a client that is strangling your company, its not worth it.</li>

<li>Let a good idea keep you from getting anything done. Just because something might be better long-term, doesn&#8217;t mean now is a good time to do it.</li>
</ul>

<h3 id='what_you_should_do'>What You <em>Should</em> Do</h3>

<h4 id='especially_if_youre_starving'>Especially If You&#8217;re Starving</h4>

<ul>
<li>Keep open conversations with your clients to make sure they&#8217;re happy. An unhappy client makes everything harder, try to keep communication open to understand their needs and desires, and to make sure that minor things aren&#8217;t becoming major.</li>
</ul>

<p>Of course, the &#8220;Do&#8221; list is short because &#8220;boss&#8221; didn&#8217;t make very many good decisions in my opinion.</p>]]></description>
        <link>http://grahamc.com/blog/what-not-to-do-ever</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/openssl-madness-how-to-create-keys-certificate-signing-requests-authorities-and-pem-files</guid>
        <title>Creating SSL keys, CSRs, self-signed certificates, and .pem files.</title>
        <pubDate>Tue, 14 Jul 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<h3 id='what_is_the_whole_darned_process'>What is the whole darned process?</h3>

<p>Well that&#8217;s a good question. For my purposes, this is what I need to know:</p>

<ol>
<li>Create a Private Key. These usually end in the file extension &#8220;key&#8221; If you already have one, don&#8217;t worry - it&#8217;s cool, we&#8217;ll be using that one.</li>

<li>Create a Certificate Signing Request. These usually end in the extension &#8220;csr&#8221;, and are sent to the certificate authority to generate a certificate.</li>

<li>If you&#8217;re not going to be using an existing service (usually for pay) as a certificate authority, you can create your own Certificate Authority, or self-sign your certificate.</li>

<li>Submit your CSR to the CA and get the results. If you&#8217;re doing it yourself, I&#8217;ll tell you how. The CA creates a Certificate file, which ends in &#8220;.crt&#8221;.</li>

<li>Take the whole collection of files, keep them somewhere safe, and mash them together to create your PEM file (this is usually just used for email.)</li>
</ol>

<p>So. Let&#8217;s get started, eh?</p>

<h3 id='step_zero_basic_assumptions'>Step Zero: Basic Assumptions</h3>

<ul>
<li>I&#8217;ll assume your domain name is domain.tld.</li>

<li>I&#8217;ll assume you have OpenSSL installed.</li>

<li>I&#8217;ll assume that you are running some form of Linux. I use Debian.</li>
</ul>

<h3 id='step_one_create_your_private_key'>Step One: Create your Private Key</h3>

<p>Ok, here you&#8217;re going to create your key - and treat is as such. This should be kept private, and not shared with anyone.</p>

<p>Now, you have a couple of options here - the first is to create your private key with a password, the other is to make it without one. If you create it with a password, you have to type it in every time your start any server that uses it.</p>

<p><strong>Important:</strong> If you create your private key with a password, you can remove it later. I recommend creating your private key with a password, and then removing it temporarily every time you need to use it. When you&#8217;re done with the key without a password, delete it so it isn&#8217;t a security risk.</p>

<h4 id='create_your_private_key_with_a_password'>Create your Private key <strong>with</strong> a password</h4>
<div class='highlight'><pre><code class='bash'>openssl genrsa -des3 -out domain.tld.encrypted.key 1024
</code></pre>
</div>
<h4 id='create_your_private_key_without_a_password'>Create your Private key <strong>without</strong> a password</h4>
<div class='highlight'><pre><code class='bash'>openssl genrsa -out domain.tld.key 1024
</code></pre>
</div>
<p>If you created your private key with a password, you&#8217;ll want to complete the rest of the steps using a decrypted private key - else you&#8217;ll have to type in your password every time you use the certificate (ie: every time you start a daemon using that certificate.)</p>

<h4 id='remove_the_password_and_encryption_from_your_private_key'>Remove the password and encryption from your private key</h4>
<div class='highlight'><pre><code class='bash'>openssl rsa -in domain.tld.encrypted.key -out domain.tld.key
</code></pre>
</div>
<h3 id='step_two_create_a_csr'>Step Two: Create a CSR</h3>

<p>On this step you&#8217;re going to create what you actually send to your Certificate Authority. If you set a password with your Private Key, you&#8217;ll be required to enter it to create the CSR. After you finish all these steps, you can delete your CSR.</p>

<h4 id='create_your_certificate_signing_request'>Create your Certificate Signing Request</h4>
<div class='highlight'><pre><code class='bash'>openssl req -new -key domain.tld.key -out domain.tld.csr
</code></pre>
</div>
<h3 id='step_three_create_your_certificate'>Step Three: Create your Certificate</h3>

<p>You have three options here:</p>

<ol>
<li>Self-signing</li>

<li>Creating a certificate authority (CA)</li>

<li>Paying a CA to create your certificate for you.</li>
</ol>

<p>Here&#8217;s what&#8217;s up: Self-signing is easy, free, and quick. Creating a CA isn&#8217;t terribly difficult, but probably more than you want to handle for something small. Paying for a CA can be cheap ($20), easy, quick, and comes with browser-recognition, which is generally important for public websites; especially commercial ones.</p>

<p><strong>My advise:</strong> Self-sign your certificates for personal things, and pay for a certificate if its public and important.</p>

<p>If you&#8217;d like to pay for someone to sign your certificates, do some research and find which one you want to use. Next, find their instructions for submitting your CSR file.</p>

<h4 id='selfsign_your_certificate'>Self-Sign your Certificate</h4>
<div class='highlight'><pre><code class='bash'>openssl x509 -req -days 365 -in domain.tld.csr -signkey domain.tld.key -out
domain.tld.crt
</code></pre>
</div>
<p>If you do happen to want to setup your own certificate authority, check these resources out:</p>

<ul>
<li><a href='http://www.g-loaded.eu/2005/11/10/be-your-own-ca/'>http://www.g-loaded.eu/2005/11/10/be-your-own-ca/</a></li>

<li><a href='http://codeghar.wordpress.com/2008/03/17/create-a-certificate-authority-and-certificates-with-openssl/'>http://codeghar.wordpress.com/2008/03/17/create-a-certificate-authority-and-certificates-with-openssl/</a></li>
</ul>

<h3 id='step_four_creating_a_pem_file'>Step Four: Creating a PEM file</h3>

<p>A PEM file is used by many different daemons, however how to generate such a PEM file can be hard to come by. There are some complicated ways to build one, however I have had pretty good success with simply combining the .key and the .crt file together:</p>
<div class='highlight'><pre><code class='bash'>cat domain.tld.key domain.tld.crt &gt; domain.tld.pem
</code></pre>
</div>
<h3 id='disclaimer'>Disclaimer</h3>

<p>I am not an expert with SSL, which is exactly why I created this. This may not be accurate, YMMV, etc. Be careful. Also: Your .key is private. Keep that safe, with appropriate permissions. Make sure nobody else can access it, and do not give it away to anyone. If you have any insight, feel free to comment - I would appreciate them.</p>

<h3 id='sources'>Sources</h3>

<p>Just a thank-you to everyone that was kind enough to document this process.</p>

<ul>
<li><a href='http://www.rapidssl.com/ssl-certificate-support/generate-csr/apache_mod_ssl.htm'>http://www.rapidssl.com/ssl-certificate-support/generate-csr/apache_mod_ssl.htm</a></li>

<li><a href='http://www.akadia.com/services/ssh_test_certificate.html'>http://www.akadia.com/services/ssh_test_certificate.html</a></li>
</ul>]]></description>
        <link>http://grahamc.com/blog/openssl-madness-how-to-create-keys-certificate-signing-requests-authorities-and-pem-files</link>
    </item>
	
    
	
    <item>
        <guid>http://grahamc.com//blog/getting-list-of-users-with-access-to-a-database</guid>
        <title>Listing Users with Database Access</title>
        <pubDate>Sun, 24 May 2009 00:00:00 -0700</pubDate>
        <description><![CDATA[<p>As a part of my server migration, I&#8217;ve begun noting which databases to transfer, which I can trash, and who owns them. This is pretty eye-opening, as it lets me know which users I had forgotten to purge as they left my services.</p>
<div class='highlight'><pre><code class='mysql'><span class='k'>SELECT</span> <span class='n'>User</span> <span class='k'>FROM</span> <span class='n'>mysql</span><span class='p'>.</span><span class='n'>db</span> <span class='k'>WHERE</span> <span class='n'>Db</span> <span class='o'>=</span> <span class='s1'>&#39;databasename&#39;</span><span class='p'>;</span>
</code></pre>
</div>
<p>That will retrieve all of the users that have access to databasename. Thanks to <a href='http://ishouldbecoding.com'>Elazar</a> (on Freenode) for this solution.</p>

<p>Only issue with this, is it doesn&#8217;t list the users who have global permissions (ie: <code>*.*</code>). Any ideas on solutions that would include that? Or is there not a &#8220;simpler&#8221; way.</p>]]></description>
        <link>http://grahamc.com/blog/getting-list-of-users-with-access-to-a-database</link>
    </item>
	
    
</channel>
</rss>
