January 1st 1900
So today while I was testing I noticed that dates of 1900-01-01 were being displayed as today’s date. I figured it had to do something with Smarty’s date handling (in particular the date_format modifier and the html_select_date plugin - I use those two everywhere). Initially I thought it had to do with something about pre 1970 dates and Unix timestamps but then I tried some pre 1970 dates and they worked as expected.
Since I knew that the date_format modifier uses PHP’s strototime() function internally I looked up the documentation. That’s when I noticed this ‘note’:
Note: The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.)
So that explained why pre-1970 dates were working but not something like 1900-01-01 itself.
And as it turns out whenever Smarty processes a date, it converts it into a Unix timestamp. If the timestamp fails (as in 1900-01-01) it defaults to today’s date:
$time = strtotime($string);
if ($time == -1 || $time === false) {
// strtotime() was not able to parse $string, use "now":
$time = time();
}
I thought about modifying the Smarty plugin but I still felt pretty guilty about my previous hack(!).
I vaguely remembered something about PHP having some kind of new DateTime class and after reading the docs I figured it would be benficial to use DateTime instances. The big selling points were a larger timestamp range and its format() function which formats the date automatically. Which meant that I no longer needed to use Smarty’s format_date modifer - and I no longer had to rely on PHP’s ridiculous date/time functions.
So I converted all dates to DateTime instances and I thought all is good in the world. But during the first test case I see my beloved 500 page and this message in the logs:
Warning: DateTime::format() [datetime.format]: The DateTime object has not been correctly initialized by its constructon
WTF does that mean? Google answered that for me which led to this little tidbit:
Note: It is not possible to serialize PHP built-in objects.
Some of my objects that were using DateTime instances were being stored in session (ie. being serialized/unserailized) and I guess that’s why I was getting the above warning.
So now I’m thinking ‘What kind of ridiculous hack can I come up with to overcome this?’ And here my non existent readers is that ridiculous hack:
$this->date; // a 'date string' formatted as YYYY-MM-DD
function getDate()
{
return new DateTime($this->date);
}
function setDate($date)
{
$this->date = $date->format('Y-m-d');
}
So basically my objects internally are storing the date as a string (YYYY-MM-DD) but its getters and setters are returning DateTime instances. I’m sure this violates all kinds of best practices but whatever it works.
An Interview
So What’s Been Troubling You These Past Few Days?
I’ve been writing a sh*tload of Javascript for The Project lately. And I’m sick and tired of wondering why that <div> shows up in one browser and not in another.
Why Don’t You Try Using One Of Those Javascript Framework That Are All The Rage Nowadays?
Because I like having full control over my Javascript. It makes me feel powerful! It makes me feel like a man! But these last few days have succeeded in breaking me. It’s time to learn a Javascript framework.
So Have You Picked One?
JQuery
Why JQuery?
Because Coding Horror told me to.
What Did You Think JQuery Was Before You Started Learning It?
I thought JQuery (and Prototype, DOJO, etc. etc.) just provided you a way of not typing something like ‘document.getElementById‘ all the time. Seriously.
What Do You Love Most About Learning JQuery?
It makes me not care about whether that ajax call will work across browsers. And the fact that it uses $ everywhere. Much like PHP. Now when I switch between PHP and Javascript files I don’t get that different-syntax jarring effect that give me headaches.
What Do You Hate Most About Learning JQuery?
It’s like trying to learn a new syntax. And the fact that 99.9% of the JQuery examples out there think that chaining on one line is the sh*ts. It’s not.
What The One Thing That Impresses You Most About JQuery?
The fact that it has a trim() function!
Seriously?
Hey every time I create a Javascript file I’m still including that trim utility that I wrote a hundred years ago. It’s nice to have an in built one.
So The #1 Reason To Use JQuery… Because It Has A Trim Function?
Yes. Definitely.
States And Provinces
Latest task: The Project has a bunch of address forms which needed this change:
- If the selected country is either Australia, Canada, or the United States, hide the state text box, load (from an external file) the appropriate set of provinces / states, populate and show the state combo box
- Otherwise, hide the state combo box and show the state text box.
So no big deal right?. I figured the ‘challenging’ part would be reading data from the external states / provinces (XML btw) file.
First off: Opening that XML file. Wouldn’t that be like Ajax without the ‘A’?
// for sake of simplicity showing only mozilla compatible code
var xmlHttp = new XHLHttpRequest();
xmlHttp.open('GET', <path_to_xml_file>, false);
var xmlDoc = xmlHttp.responseXML;
Apparently not - because the above didn’t work. After much googling I came up with this:
// for sake of simplicity showing only mozilla compatible code
var xmlDoc = document.implementation.createDocument('', 'doc', null);
xmlDoc.async = false;
xmlDoc.load(<path_to_xml_file>);
Now let’s read those states and provinces:
var countryId = 'USA'; var states = document.getElementById(countryId);
Hey… how come I’m not loading anything? Maybe it’s because I can’t use getElementsById() with non-strict XML! So I remove all the id attributes in the XML file and after much getElementsByTagName()-ing and attributes[i].nodeValue-ing I’m welcomed with this error:
Exception… “Access to restricted URI denied” code: “1012″ nsresult: “0×805303f4 (NS_ERROR_DOM_BAD_URI)”
WTF? However after seeing the word ‘restricted’ it become clear…
On our server, The Project is separated into ssl and non-ssl directories. All of the address forms are located in the ssl directory and the XML file is in the non-ssl one. Apparently a ssl page cannot load a non-ssl file because of security reasons(?). So all I had to do was move the XML file into the ssl directory.
Form Validation
This week at the top of my TODO list is (server-side) form validation for The Project. Basically I need the following:
- User fills out the form and submits
- If user missed something or provided invalid input the form is redisplayed pre-filled with the data that has already been entered
- The redisplayed form indicates which field(s) need to be corrected
- Repeat #1 until form validates
Now the kind of validation that The Project needs is pretty standard stuff (email addresses, phone numbers, credit card numbers, street addresses) plus your usual suspects (non empty, alpha/numerical) so I figured there has to be a PHP form validation library out there that I could use. Besides I don’t like rolling my own stuff if I don’t have to.
And of course there are tonnes of such libraries out there but I decided to roll my own anyways!
Why?
Because after analyzing things a little more I realized all I needed/wanted was a ‘data validator’ class that would validate data in Step #2. Smarty and my event handler scripts could deal with Steps #1, #3, and #4 based on the data returned in Step #2.
So to write this ‘data validator’ class I downloaded a few of these PHP form validation libraries (SmartyValidate and ZendFramework actually) and copied their validation code for the various types that I needed. Thank you Open Source!
Infected By Ajax
The Project has this shopping cart form. Each product in the cart has its own <select> drop down for the product quantity and a <div> to show the product total price. A user can update the product qty by selected a different qty.
When I first created this form I made the page re-load when the user clicked a different quantity. Admittedly not very slick but easy-peasy to implement.
However The Client now wants the above to happen … wait for it… without a page load. The Project is officially infected by Ajax!
Well… 153 plain vanilla Javascript lines later I was finished. I’m a little embarrassed to share the code but suffice to say that:
- I’m sure that I or someone (or even a third party Javascript library) could make it more concise.
- It works across all (well Firefox, Opera, Safari, and IE 6/7) browsers.
- The Client is satisfied. And that’s what matters most.
I just hope that The Client doesn’t start to want this ajax thing everywhere in The Project.