TK Studios Blog

Fixing Doctrine’s Geographical template precision

April 27th, 2010

Doctrine, an ORM library, has a convenient little behavior that you can attach to your tables to give them awesome superpowers of geolocation. It’s the Geographical template, and it resides in Doctrine/Template/Geographical.php. What it does it add two fields to your table: Latitude and Longitude, and extends your model with the ability to discern distances between any two of these locations.

That’s all well and good, except that as of 1.2.2, Doctrine’s default precision for a floating point field is 2. That doesn’t allow for very accurate geolocation, as it truncates something like “+33.544622″ down to “33.54″. Not good.

The documentation says absolutely nothing about fixing this behavior. I found a bug listing, but no actual fix. Thus began a long session of guesswork, all futile, and ending in a “duhhh” moment and a quick manual trace of the code to determine how the options for templates are handled.

Long story short, I found a fix, and here it is:

YAML version:

actAs:
  Geographical:
    latitude:
      options:
        scale: 7
    longitude:
      options:
        scale: 7

php model version (in your model’s setUp() function):

$geographical0 = new Doctrine_Template_Geographical(array(
    'latitude' =>
    array(
            'options' =>
            array(
                    'scale' => 7,
            ),
    ),
    'longitude' =>
    array(
            'options' =>
            array(
                    'scale' => 7,
            ),
    ),
));
$this->actAs($geographical0);

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

PHP hashing performance experiment

April 25th, 2010

Today, in the never-ending quest to tweak server performance by a few milliseconds, I decided to do a bit of testing of various php hashing methods. I therefore wrote a quick script under php (5.2.11 currently, I need to update), which ran each test case 10,000 times to achieve a decent min/avg/max for each case, on strings of 10KB, 100KB, and 1,000KB in size.

The short version of the result is that the md5() function won across the board. The comments in the php.net hash function documentation seemed to indicate a performance increase in using hash(‘md5′,$str), and an even better increase in hash(‘md4′,$str). I found this to only partially be the case; While using the hash function, md4 is minutely faster than md5, the md5() function itself is considerably faster than either of these.

So, for any performance sensitive case, I would say md5() is by far the best choice.

Actual results of the test suite can be seen here:

PHP Hash Performance by JSylvanus via Listy.us

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Changelog ala Listy

March 27th, 2010

I put together a change log for Listy.us IN Listy.us. And here it is.

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Southwest Understands Conversation

March 24th, 2010

I’m probably a bit late to the party on this one, but I flew Southwest up to & back from the MD/VA area this past week. It was unlike any prior flying experiences, and as far as I can tell, they know they’re doing it. It’s intentional. The staff are happy and conversational with passengers. They joke with you, they aren’t afraid to laugh. Probably the best customer experience out there as far as feeling like a person, rather than cash-dispensing cattle.

What really shocked me though was when, on the flight up on the 17th (#522 if someone from SW wants to look it up), the flight attendant sang to the crew. Thrice. I was on a non-connecting one-stop flight, and was treated to amusing, silly, fun singing three times. It put a smile on my face. She got applause each time.

Someone needs to introduce that flight attendant to the marketing director, because that was just awesome. It really shows that they’re doing a great job, too: Checking baggage, the lines at every other airline were ghost towns. Southwest was almost spilling out of their guide thingies.

Keep it up, SW.

(I’ve got a lot of posts to make about the latest update to Listy.us, but this seemed a more pressing post. I felt it was worth mentioning before I forgot about it.)

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Listy.us – Now with Embedding!

March 23rd, 2010

Today marks the first “Huge” update to Listy.us. It is now a paid service, handles uploaded files, and allows public lists to be embedded on any page. Like so:

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Playing with CSS3 – Sleek UI Buttons

February 11th, 2010

A while ago someone linked this post and I bookmarked it. Today I decided to toy around with a new button look for Listy.us. Using a mixture of CSS3 background gradients and border-radius, I’ve come up with this button:

New UI Button – don’t forget to click!

Which is just a link and a span, code-wise:

<a class="uiButton" href="#"><span class="uibb">New UI Button</span></a>

Internet Explorer kind of hates it, with no rounded corners and some questionable hover behavior, but overall I’d say it’s a win.

Browser testing:

Browser test for CSS3 buttons described in this post.

CSS3 Button Browser Test

Read the rest of this entry »

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

On Accessibility

December 10th, 2009

Today I ran into this really great article:

An Idiot’s Guide to Accessible Website Design

It’s great because it runs down a list of all the resources one could possibly need for accessibility testing. I must admit that in the rush to get www.listy.us online, I may have skimped a bit on the accessibility stuff. Of course I put alt tags or titles on images (or things that look like images), but testing for colorblindness? Well, damn. That one never even occurred to me, actually. Guess I’ll add an accessibility review to the task list for the next update.

Some parts of the app just won’t work without javascript, of course, but for the most part I think at least browsing the site’s content should be perfectly accessible.

Anyway, the links on that post should be in every designer’s toolbox.

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Zend Framework: Email templating with layouts & views

December 2nd, 2009

This is a solution that I came up with for sending out welcome emails, comment notifications, etc, with nice standardized HTML & text layouts, using a few components of the Zend Framework.

Basically you create a view (here called $renderer) and a layout ($layout), then render your views and layouts for both HTML and text versions. My file tree looks like this:

application/
	emails/
		welcome.html.phtml
		welcome.text.phtml
		layouts/
			layout.html.phtml
			layout.text.phtml

So, ‘welcome’ would be your template name, with html and text versions. The layout is what you want wrapped around either version of every email you send out (header graphics, font settings, contact info, etc).

I keep all of my mail functions in one class, creating a new function for each email that needs to be sent out regularly in an automatic fashion. You could even use this for newsletters, but I prefer more robust environments like MailChimp or CampaignMonitor for that sort of thing.

This simple function handles all the rendering, file paths, etc. It just needs to be called with the proper template name, and an array of items to be passed to the view renderer.

Here’s the meat of it:

/**
 * getMailContent
 * Renders mailer content in text and html and passes it back as an array('html'=>content,'text'=>content)
 *
 * @param string $templatename the name of the email template to use (APP/emails/[name].[format].phtml)
 * @param array $substitutions key=>value array of variables to pass to the view renderers
 * @return array
 */
public function getMailContent($templatename, $substitutions) {

    // create a view renderer and set it to app_path/emails/
    $renderer = new Zend_View();
    $renderer->setScriptPath(realpath(APPLICATION_PATH . '/emails/'));

    // create a layout object and set it to app_path/emails/layouts
    $layout = new Zend_Layout(APPLICATION_PATH . '/emails/layouts/');
    $layout->setView($renderer); // this probably isn't even necessary

    // assign all substitutions (e.g. view variables) to the view renderer
    foreach ($substitutions as $key => $sub) $renderer->$key = $sub;

    $output = array(); // output array        

    // render text version of template & assign to output['text']
    $layout->content = $renderer->render($templatename . '.text.phtml');
    $layout->setLayout('layout.text');
    $output['text'] = $layout->render();

    // render html version of template & assign to output['html']
    $layout->content = $renderer->render($templatename . '.html.phtml');
    $layout->setLayout('layout.html');
    $output['html'] = $layout->render();

    // all done, return output
    return $output;

}

Nice and simple, huh? All you need to do is call it and then assign the output to your Zend_Mail object like so:

        $bodies = $this->getMailContent('new_comment', array(
            'comment' => $comment,
            'comment_list' => $comment_list,
            'comment_user' => $comment_user,
            'list_owner' => $list_owner
        ));
        $mail->setBodyHtml($bodies['html']);
        $mail->setBodyText($bodies['text']);

Your email template accesses the variables passed to it just as it would a normal view script:

$this->[variable]

Commentary / suggestions / etc welcome in comments.

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

On Web Fonts

November 30th, 2009

Typekit is awesome, and I’m totally looking forward to using it, but until there’s Chrome support (I’m understand it’s coming soon), this link should be on every web designer’s tool belt:

Common fonts to all versions of Windows & Mac equivalents

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post

Listy.us is live, still a work in progress

November 24th, 2009

For those that have been following my work by means other than my blog (twitter, facebook), you already know that my big project, www.listy.us, is alive and kicking. I’ve been meaning to write an actual blog post about it for some time, since it would seem I forgot to do that back in September when the site actually launched. It’s improved a lot since then, I think.

Listy.us is a AJAXified table-based list making application. You create a list, edit it by clicking fields and entering your data, and it’s updated as you tab from item to item. It’s open-ended enough that you can use it for just about any kind of list you want to make. I designed Listy.us as an application that I would personally enjoy using, and I do use it. My user profile shows some of the lists I’ve made on the site so far – the ones I’ve marked as public, at least.

There have been a lot of features cut out in order to get the application on the internet and getting feedback. User groups, templates, and hypertemplates — templates with extra functionality such as pulling down extra data from outside sources — are all still on the list of “things to put back in ASAP.”

There are a lot of different things in this project to write about, so I’m going to try and break it up into a lot of smaller blog posts over the next couple weeks. What do you want to hear about? The marketing? Writing the editor javascript? The decision to remove advertising? Design revisions? Bits and pieces of Zend Framework code used on the backend?

Next post, I think I’ll share how I’m using some Zend Framework components to create a mail templating system for new user emails, comment notifications, and the like.

Post to Twitter Tweet This Post Post to Digg Digg This Post Post to Reddit Reddit Post to StumbleUpon Stumble This Post