Web Apps


GeoLocation Near You

We at Pivotal Action were recently given a task for a client – develop a tool for a mobile API where admin can upload a list of retailers so that their mobile app users could find locations near them. It’s basically a “Find near me” utility.

This type of project is broken down into 3 parts: Upload & store geolocation data, find addresses near a given point, and display those locations either textually or on a map display. This quick tutorial will cover the first two parts.

Part 1, Getting Located

The goal of this part is to obtain and store latitude/longitude pairs for given addresses. I’m going to assume you can already get a list of addresses, whether for a spreadsheet/csv file, or other source. With a parsed address, you can obtain the lat/lng pairs from the Google Maps API. Just be forewarned that Google limits you to 2,500 requests per 24h period. That could be a problem for some applications, so you may need another provider like SimpleGeo.com

There are a couple key parts in there. First, you need to URL encode the address details. Second, the curl stuff is pretty standard – you can find similar versions all over the net. Third, the response data comes back as a JSON string, so you need to decode it into a PHP array to make it useful. My default value for lat/lng pairs is 0.0/0.0. There may be cases where Google doesn’t understand the address information or perhaps you’ve gone over your rate limit, so you have to accept more or less a throw-away response. The important thing is that you have your address coordinates saved (dare I say, cached) in your DB. You need this.

Part 2, Finding Yourself

Now how are you supposed to find these stores that are near you, at this moment, without having to use a lame web form or other manual means? You’re going to use the Haversine, aka Great Circle  Formula. Don’t click that link unless you really want to be confused. Here’s the gist – the globe is a big sphere, and we know from high school and/or college trigonometry classes that you can figure out lengths and distances on geometric objects. Some guy long ago (whose name was not Haversine) sat down and figured this out for us. What we get as a result of running these maths is the distance between to points on earth, using lat/long pairs. The caveat is these are as the crow flies, not driving directions. What I’m going to show you below is some SQL you can use to find the N closest points within a given distance. This will work on MySQL, and I’m assuming other SQL-compliant DBs. YMMV.

(Thank Pavel Chuchuva on Stack Overflow for the SQL [answer here]). You only need a couple parameters to get this chugging along and giving you a list of distances, closest to farthest from the point you are feeding it. Along with your address information, you’re also provided a distance in miles (using 3959 for measurement in Km).

Now you can use these results to display distances to your users. Let Google be your guide for implementing Part 3.




Quiet the Console – PhoneGap / iOS

I have a confession – I’m a console logging junkie. I just like to see what’s going on. While that may be great for development, at some point you’ll have to quiet the logging down for production. Really – doing enough logging will slow everything down each time you’ve inserted a console.log() into your code.

Silencing the output to XCode’s debugging console wasn’t immediately obvious. Overriding console.log() in JS by setting it to an empty function worked in the browser for development, but as soon as I loaded the app onto the actual simulator, we were back to square one. Enter the PhoneGap DebugConsole prototype. Override it.

Insert this anywhere after your phonegap.js file loads. It’ll keep things quiet as long as DEBUG = true…

There you have it




Mobile Platform Detection on the web

I had a use case recently where I need to determine whether the client browser was a desktop/laptop/etc or a mobile device that supports tap events in JS. This will be useful to people who are dynamically binding different events to elements.

You would use it like this




Installing PEAR Libraries Locally

[I started this post quite a while ago and forgot about it. Here it is finished. Hopefully you find something useful here]

I’ve had a few projects already where I could really use some PEAR libraries but not sufficient enough access to the server so I could install them in the system-wide PEAR include directory. I went searching for an easy to manage way to package specific PEAR libs along with apps I was building and installing for clients – something that would work without access to system-wide PHP/PEAR setup, and even in rare cases where I couldn’t write outside the document root.

First place to at least read through is the documentation. I’m going to assume you already know the basics of PEAR.

This summary will discuss the FTP method, as it seems applicable to more situations. For me – I keep my sites under version control so I need to be able to perform a local install that I can commit to the repository and either export or update on my various server environments.

Tools:
* Terminal or command-line (CLI)
* CLI version of PHP
* CLI version of PEAR

Steps (code follows)

  1. Create a directory where you want the PEAR libs installed. Note: PEAR will create a directory named pear in the location you specify.
  2. CD into that directory.
  3. Create your config file for your local environment (probably won’t be needed on external servers unless you plan on installing from there, in which case you should create a separate config file for each site).
  4. Install and update packages.
  5. Update your app’s include paths.

The Code:

  1. Create your config file in the PEAR directory from step 1, above. Absolute paths, absolutely!

    The first path is the location where you want the files. The second path is the location where the pearrc file is located. I usually put the PEAR files in an includes directory within the site’s document root, just in case a host or client I’m dealing with doesn’t have write access in higher-level directories. It’s best to keep the pearrc file outside of the webroot, or deny access to the file via Apache’s Allow/Deny directives.
  2. To run PEAR commands on your local install, you will need to use the following format

    (otherwise you’re likely working on system-wide changes – doesn’t help you when it’s time to deploy to the server). An example,
    %> pear -c /path/to/setup/pearrc install File_CSV_DataSource
  3. Set your app’s includes path to search in the PEAR directory:

    Change as needed.

That should do it. It’s a basic introduction, but if you already know how to use PEAR, you’re already 95% of the way there.

 




Nasty WordPress Worms

I just ran across a nasty worm in one of my WordPress blogs (not the most current install). Not only did it overwrite a ton of files, inserting spam links and malware into the pages, but it was sneaky enough to go into my wp-admin/.svn/prop-base/ directory and re-write those files as well. It’s fairly ingenious from the hacker standpoint. Most people like me will rely on the svn revert file.php to send the file back to its original version. That won’t work if the .svn/prop-base files are altered because svn will see that they are the same – it doesn’t bother actually checking the repo, so you’re stuck with infected files.

I solved my problem by deleting the wp-admin directory and doing an svn-up on its parent. That forces SVN to say “hey – that directory is missing. I should pull it down from the repository.” Problem solved (for now).

And I am now running the most current version of WordPress, so hopefully I’m free of risk and infection from here on out.




CakePHP: Storing Configs in your DB

There are many situations in web apps where site-wide configurations need to be accessible to users through admin interfaces, rather than configuration files residing on the server. It is a practical method of storing configuration values that may need changing from time to time, but without access to the core configuration file.

UPDATE (2008-10-22): This article has been published to the CakePHP Bakery

Code

Settings are stored in the database, so we will first need to start by creating the table:
CREATE TABLE settings (
id int(10) unsigned NOT NULL auto_increment,
key varchar(48) NOT NULL,
value text,
PRIMARY KEY  (id),
UNIQUE KEY key (key)
)

Next, go ahead and bake your model and controller, but don’t worry about baking-in some of the pre-built methods. Modify your model to look like this:

class Setting extends AppModel {

var $name = ‘Setting’;
var $key = ‘MyApp’;

//retrieve configuration data from the DB
function getcfg(){
$key=$this->key;
$cfgs = $this->find(‘first’,array(‘fields’=>array(‘id’,’key’,’value’)));

if (count($cfgs)) {
$this->checksum=$cfgs[‘Setting’][‘value’];
$cfgVal = unserialize($cfgs[‘Setting’][‘value’]);

}
Configure::write($key,$cfgVal);
}

//write configuration data back to the DB
function writecfg(){
$key = $this->key;

$rev = Configure::read($key);

$value=serialize($rev);

//if the configs haven’t changed, no need to save them
if ($value==$this->checksum) return;

//otherwise the configs have changed, so

$this->data = array(‘key’=>$key,’value’=>$value);

if ($setting = $this->findByKey($key)) {
$this->data[‘id’] = $setting[‘Setting’][‘id’];
}

$this->save($this->data);
}
}

You’ll notice that Configure:: values are serialized and stored together using the MyApp Configure::key. At first this may seem somewhat counter intuitive to how we think we should store configurations. However, consider the hassle involved with trying to figure out how/where to store multi-dimensional arrays in an inherently flat storage system (db). It’s probably doable, but not without considerable headaches. Storing everything in a serialized string allows Cake to worry about creating the structure – we just save the output.

Next, open up your app_controller.php file and add the following code to the top of the class:
var $uses = array('Setting');

You will also need to add some code to your AppController beforeFilter() and afterFilter() methods:

class AppController extends Controller {

var $uses = array(‘Setting’);

function beforeFilter(){
//reads the site-wide config values from the DB and puts them through the Configure::write method
$this->Setting->getcfg();
}

function afterFilter(){
//retrieves the site-wide configurations from Configure::read($key) and puts it back into the db if new
$this->Setting->writecfg();
}
}

Usage

Any place you would like to store a Configure:: value in the database, you only need to use the $key specified in the model. If you don’t, the values will not get saved. An example would look something like:
<? Configure::write('MyApp.themeName','My Great Theme'); ?>

Since the retrieval code is run in the before filter, we can treat the Configure:: vars like any others in our app when we need to access them. To recall a value we would run something like:
<? $myVar = Configure::read('MyApp.themeName'); //returns 'My Great Theme' ?>

Next Steps

Because this is only a very simple way to store configuration data (one row for the entire app), there will likely be some desire to extend it. You may wish to segregate certain data into their own rows (perhaps individual plugins or components), which would only require some additional code to accept additional keys for read/write access. That, my friends, is a job for another tutorial.




Zend Framework – Getting Started

Working with a new client project this week that requires the Zend Framework. It’s not my choice of frameworks, but I’m still eager to get going on it. As I’m a bit more familiar with CakePHP, I thought it would be wise to watch a screencast or two about getting started on ZF to see what some of the main differences are. Watch them (from Mitchell Hashimoto).




Unchecked checkbox values

Working with form check boxes can be a bit of a pain on sites with dynamic content. Saving the checked data is easy, but how do you easily save the unchecked value without manually adding it to an array from inside your code? Keep reading.

revealCMS is working great – I’m really starting to see a lot of its strengths (and, admittedly, some weaknesses) as I use it more and begin extending it. Due to how data is saved to the database, the HTML checkboxes were a bit of a problem when trying to save their unchecked state. Typically I save the post data to the object, where it is filtered and scrubbed, as necessary.Only the posted values get updated in their respective rows (makes sense, right?).

The problem is that unless a box is checked, it’s not going to be sent with the form – a problem if you have a checked box, but want to save the unchecked state.The first option is easy and probably the first solution you’d think of – write a couple lines of code for every single checkbox and set it to some default value if it’s left unchecked when the form is posted. Fine, but that takes more thinking than I want to do for something so simple, and it’s somewhat prone to error. Instead…

…the solution: Insert a hidden form field with the same name as the checkbox and the default value right before the place where the checkbox is located:
<input type="hidden" name="box1" value="0" /> <input type="checkbox" name="box1" value="1" />
What happens here is that when the checkbox is left unchecked, the hidden field’s value gets submitted, as-is. When the check box is checked, the hidden field’s POST value gets overwritten by the activated checkbox’s.
Unactivated: Hidden field’s value.
Activated: Check box’s value.

Told you it was easy!




Award Winning : Davey Awards

I just received word that one of my projects just won a Davey Award for online marketing and email campaigns:

Munchkin’s Project Pink: Email a Duck, Raise a Buck!

Harley Bergsma at the UXB and I devised this brainchild together. From there he took care of project management and I took care of developing the back-end. The idea is that users can decorate their own pink duck on the site (using Flash), then forward their creation to all their friends. For each person that receives the duck and opens (don’t even have to click links!) the email five cents is donated to Susan G Komen for the Cure. One of the coolest things is that the email dynamically shows how much the duck raised (how many emails were sent) and how much the project’s running total was. If you were to come back to the email a few minutes, days, weeks later, it would continue to show fully-updated information. Rad!

In just a couple months there were over 131,000 forwards, for a total of over $6550 raised just from this part of the campaign alone.




SMARTY: Assigning variables to the header from the body

The problem recently presented itself to me when writing some new functionality for revealCMS: I needed to set some variables to load in the page head, but could only be set after a portion of the body had completed rendering. I wrote a plugin that essentially loads a different stylesheet depending on the input of the Smarty template function. The hard part wasn’t assigning the variable – it was figuring out the best way to get that assigned data to appear in a part of a page that had already been rendered – the head.

It makes sense why Smarty would work this way – that you can’t go back and re-assign variables. It would be too messy. So somehow you need to assign the variable first in the body, then go back and render the head. It’s simple… really. Believe it.

But why bother? Why not put <style> tags directly into the page body where the plugin is located? The reason is simple: <style> tags (and <script> tags, for that matter) MUST be in the page header. It’s a web standards thing.

First, break-up your page templates into two sections: the header (containing everything before the <body> section of your template), and the body, which contains the <body> section. First render the body using
$body = $smarty->fetch('body.tpl');
At this point, I’ll just assume that your page functions have loaded and you’ve either placed an {assign} tag somewhere in the template, or you’ve used a $smarty->assign() inside the template function. If you’re not familiar with $smarty->fetch(), it’s just like $smarty->display(), except it outputs the contents to a variable rather than the screen. And just like display() it can also take $compile_id and $cache_id as optional parameters.

Now render the head:

$head = $smarty->fetch('header.tpl');
By this point everything should work-out as we expect it. Our dynamically loaded css file is loaded in the head and our standards friends are happy. The beauty about this example is that you can now render a number of items in any order you need them then display properly, so long as it makes logical sense.

Here’s a tip: You can use this method to dynamically load javascript files and frameworks if your fancy web 2.0 page functions/plugins need it at some times, but not at others.