Symfony 1.4, Doctrine and the csDoctrineActAsGeolocateablePlugin Example
I spent many hours trying to decipher the documentation for Doctrine’s Geographical Behavior and the csDoctrineActAsGeolocatablePlugin for Symfony 1.4.7. So let me hopefully save you some time, and explain what I ran into and how I solved the problem.
I have geo-tagged content in my “yellow pages” project stored in a “Content” table, and needed to allow users to search for records within a distance of a number of various identifiers (Zip Code, City, State, GPS Coords from Mobile Devices, etc). With this knowledge, I enabled the Geographical behavior from Doctrine to add Latitude and Longitude fields to my database. I also imported a Census Zip Code Table and called it “GeoData”. The GeoData table contains ZipCode, City, State, Latitude and Longitude fields; I used Geographical on this table as well. My “Content” table also has the Geolocatable behavior attached to it, from the csDoctrineActAsGelocatablePlugin from Centre{source}.
I quickly became stumped on how to proceed from here. I created my custom search form, built a module and created some actions and views and then … nothing. I sat there reading documentation and experimenting by means of trial and error repeatedly until I almost put a blunt object through one of my displays.
The Doctrine documentation for Geographical has the following example:
// test.php
// ...
$q = $zipcode1->getDistanceQuery();
$q->orderby('miles asc')
->addWhere($q->getRootAlias() . '.city != ?', $zipcode1->city)
->limit(50);
echo $q->getSqlQuery();
The Geolocatable plugin has absolutely no documentation, but mentions that the following method is added to the “Table”:
Table Methods
addDistanceQuery( $query, $latitude, $longitude, $distance = null) adds distance query to a preexisting query.
field “distance” on each object represents the distance away from the passed latitude and longitude.
If $distance is not null, results are limited to that distance from the given geocodes.
After many hours, I discovered that the following code was what I needed:
$zipcode = Doctrine_Core::getTable('geoData')
->findOneByZipCode($this->form->getValue('zip_code'));
$query = Doctrine_Query::create()
->select('d.*, c.*')
->from('ContentDirectory d')
->innerJoin('d.Content c')
->orderBy('miles asc');
$query = Doctrine_Core::getTable('ContentDirectory')
->addDistanceQuery($query, $zipcode->getLatitude(), $zipcode->getLongitude(), 25);
$this->searchResults = $query->execute();
So let’s break this code down:
$zipcode = Doctrine_Core::getTable('geoData')
->findOneByZipCode($this->form->getValue('zip_code'));
This simply loads up an instance of my “GeoData” object for the zip code entered by the user in the form. Since the GeoData table contains many records for the same Zip Code I call the “findOneBy” magic method.
$query = Doctrine_Query::create()
->select('d.*, c.*')
->from('ContentDirectory d')
->innerJoin('d.Content c')
->orderBy('miles asc');
This code is my base query joining my “ContentDirectory” and “Content” tables together and then ordering them by the “miles” (distance) they are from the source (zipcode from search). I’d like to note that “miles” is not part of my data schema, and is added by the Geolocatable Plugins code in the following lines. This Doctrine_Query should be fairly familiar to most users, so I won’t go into any detail about it.
$query = Doctrine_Core::getTable('ContentDirectory')
->addDistanceQuery($query, $zipcode->getLatitude(), $zipcode->getLongitude(), 25);
This bit here is where the “magic” occurs. Since “addDistanceQuery” is a table method, I can’t just simply append it to my Doctrine_Query above. As such, I access my Geolocatable Table (ContentDirectory) and then call the ‘addDistanceQuery’ method of that table, passing in the necessary parameters as defined by the documentation. $query is the query we are adding the logic too, $latitude and $longitude are self explanitory and $distance allows me to limit my results within a specific distance (in miles) from the source. If distance is not passed, then the query simply appends the “miles” logic which allows me to sort my results by distance but not limit them by it.
This may seem quite simple to some, and it does to me now as well. However, it took quite a bit of time to realize how to string this all together.
This concludes, what I believe may be the first of many Symfony and Doctrine related posts.
Kid Challenge: Step 1
So, I was thinking earlier today … and, decided to challenge my 10-year old nephew. The challenge is as follows:
He is tasked with creating an educational video game for Kindergarten and First Graders, to teach simple math skills.
The rules are quite simple, he has to design the concept on his own (he’s allowed to ask for opinions, and receive guidance on the educational aspect). He then has to build this video game with any tools available. I bought him a copy of “The Game Makers Apprentice” sometime last year, and he has his own Game Maker license. So, more than likely, he’ll be building it with YoYo Game’s Game Maker software.
What does he get if he completes the challenge, successfully? Well, he receives a $100 ‘prize’ for completing the game and … we’ll build a web site together in which we can market the game to parents and sell it for a small fee (probably something like $9.95 … ).
So … if he keeps his interest in this challenge, and does anything with it … I’ll keep track of his progress here.
Anyone whose interested in knowing me, drop a comment … I’m sure the attention will just add incentive.
jQuery Growl 1.0.2 Released
I was informed of a bug in jQuery Growl 1.0.1 that occurs in the newer releases of jQuery (the 1.3.x releases), and have patched the Growl Notification Plugin to work with the latest version of jQuery.
The patch was submitted by James Moberg of Sunstar Media.
As usual, you can download the latest version of jQuery Growl here.
Stockboy Stanley in Warehouse Trouble Released!
Stockboy Stanley in Warehouse Trouble has been officially released on the Apple App Store for the iPhone and iPod Touch. The game is an addicting puzzle strategy with a bit of a platformer spin on it. Stanley, the main character, is trapped in a stock crate pit and the crate stacker has gone bezerk. Stanley must guide the crate stacker to get crates stacked in such a manner so that Stanley can climb out of the pit to safety. As Stanley progresses, the crates fall faster and faster.
Great fun for all ages, easy to use controls, simple enough concept that you don’t need to “learn how to play”, but for those of you who love the strategy, there’s always a better way to get out faster and go further.
Released by Gear Worx Productions, and developed by me, David Higgins. Art is completely by Steve Adamson, with a wicked custom sound track by PunkArts.com.
Check out the Stockboy Stanley homepage and view the gameplay trailer.
Cocos2D 0.7.1 Application Template for XCode
I updated the existing 0.7.0 XCode Template for Cocos2D to support the latest 0.7.1 updates. The template does not include the experimental sound engine, or Motion Streak. To implement these experimental features, you’ll have to include them in your project separately.
Website Experiment – Bartender’s Database
I’ve decided that I wanted to work on something rather simple, that had the potential to bring in some (not a lot, just some) Ad revenue. I use the AdBrite ad system, as opposed to Google, largely because they pay per impression and not just clicks. I don’t expect very many people to click the ads found on any of my sites — the adwords are poorly targetted due to the scattered content found on my sites, and the various topics I discuss. So, I just go for the ‘pay by impression’ model of ad revenue. If it helps pay for the hosting, thats good enough.
So, onto my experiment … I’ve decided to build a Recipe Database system using CakePHP 1.2, and am targetting Alcoholic beverages as my first set of targetted content. The recipe database framework is built on CakePHP and is being built in such a way as to allow me to extend it or derive from it later to include things such as Foods, and even Arts and Crafts instructions (Arts and Crafts really are just recipes, with quite a bit of instruction — a list of ‘ingredients’ and amounts of each, followed by instructions).
So, without furher ado (did I really just type that?) … I would like to announce the creation of BartenderDB.com. So far, it’s fairly simple and straight forward and has almost no recipes in it — I’ll get to that in a bit. It does have the ability to list the recipes by Name, list ingredients and show recipes containing those ingredients and even includes the custom ‘color tag’ so you can search for your drinks based on the end resulting color of the liquid in the glass (Hrm, that sounds a lot like a uhm … oh, nevermind, it’s a holiday).
Scheduling Projects
I’m a geek at heart, I love my job (software engineer) and I take my work home with me from time to time. I love creating ‘work’ for myself at home too, in the form of little projects here and there — most of which you can read about and explore through this blog. However, my children (I have three) all started school this year, so now I have three children in school. Kindergarten, First and Second grades – whoa.
Talk about a lot of work, I thought the whole point in school was for the kids to learn, they’ve only been in school for a couple weeks now and I’ve done more school work with my kids then I can remember ever having to do when I was in school myself. Absolutely insane, but entirely enjoyable to watch them learning and bringing their newfound knowledge home at the end of the day.
Now, onto my topic …
How do you work on personal projects, homework, and still have time to wind down at night and relax with a little TV. While, at the same time, trying to spend more then an adequate amount of time with your significant other. It’s a serious juggling act, and I’ve not yet figured out how to solve the problem — I’m anxious and ready to get cranking on some of my newest projects, and a little disappointed at the state of some of my older projects.
I just don’t know where all the ‘extra’ time that I think I need is going to come from. I will, however, continue to look for that ‘time door’ so I can walk through it and get back to my projects.
Inspiration and T-Shirts …
I was helping my mother setup a CafePress.com store and thought to myself, why not. So, I decided to open my own store and explore the possibilities. I downloaded a couple of there apparel templates and went at them with a little bit of PhotoShop magic.
I downloaded a couple of interesting fonts that were all listed as ‘free’ or ‘public domain’, thought of a few things I’ve heard or seen that made me laugh, chuckle or ponder ‘why …’ and threw them together on a few t-shirts, hats and mugs. I opened the store with the basic ‘free’ account, and realized the limitations rather quickly and then opted to go for the paid premium account. I figure I can run the premium store for a few months, and at the end of that time I’ll know whether or not it’s worth keeping online — a store that can’t pay for itself, is useless, yes?
So, I’m going to try to keep making new designs and hopefully come up with something that is just so creative and/or entertaining … that hopefully, everyone wants to buy one. Now, being as I’m a realist … I simply set the money I’m going to pay for the premium store aside and waved good bye to it, but … as with most things, you really never know until you try.
So, here’s to hoping my store pays for itself.
iPhone… as a Desktop Workstation?
I just read over an interesting article from Hamid Shojaee, about a “thought experiement” that he and Angelo Coppola performed recently. The end result, a concept that is most likely not too ‘far fetched’ to actually become reality … sooner then some people might think.
The idea is pretty simple, take an iPhone, ‘dock it’ to a 17″ Monitor ‘base station’, toss a bluetooth keyboard and mouse into the picture … and, Viola!
I don’t believe I can say much about the idea that Hamid or Angelo haven’t already, so, give their articles a read … I’m pretty sure you’ll be picking up your jaw and wiping the drool off your keyboard before you get to the end.
The original articles can be found here:
Hamid -> iPhone Desktop: Unleash the Leopard in Your Pocket. $299.
Angelo -> Set the Leopard Free


