Archive for the ‘Net: Techy: PHP’ category

PHP: Difference in Dates Using Zend_Date

December 4th, 2008

I’ve had to write some code recently that handles peoples ages based on their date of births… Something simple you expect, until you realise that PHP can’t really deal with years before 1970 (due to UNIX date time restrictions). Luckily Zend_Date (in the Zend Framework) comes to hand to help!

But how do you actually turn a date in the format YYYY-MM-DD into a difference in years? Well, here’s how! We’re relying on the date to be consistently 10 characters long in the format YYYY-MM-DD with any unused date “zerod” out (for example, if we are using OpenID which allows people to “hide” parts of their DOB):

if (preg_match('/^([1-2][0-9][0-9][0-9])\-([0-1][0-9])\-([0-3][0-9])$/',$sDob,$aMatches)) {
    $iYear=$aMatches[1];
    $iMonth=$aMatches[2];
    if ($iMonth<1 || $iMonth>12) {
        // Set a minimum/standard month for this calculation
        $iMonth=1;
    }//end if ($iMonth<1 || $iMonth>12) {
    $iDay=$aMatches[3];
    if ($iDay<1 || $iDay>31) {
        // Set a minimum/standard day of the month for this calculation
        $iDay=1;
    }//end if ($iDay<1 || $iDay>31) {
    // If anybody was born before 1850 or after 3,000 (say they have a time machine)
    // then, sorry, they'll have to check their date of birth elsewhere!
    if ($iYear>1850 && $iYear<3000) {         if (checkdate($iMonth,$iDay,$iYear)) {             $cNowDate=new Zend_Date();             $cUserDate=new Zend_Date(Array('year'=>$iYear,'month'=>$iMonth,'day'=>$iDay));
            // Sanity check that the date the user entered is actually in the past!
            // No future time travellers welcome here!
            if ($cNowDate->isLater($cUserDate)) {
                $cDifference=$cNowDate->subDate($cUserDate);
                $aDifference=$cDifference->toArray();
                print 'Year difference is:'.$aDifference['year'];
            }//end if ($cNowDate->isLater($cUserDate)) {
        }//end if (checkdate($iMonth,$iDay,$iYear)) {
    }//end if ($iYear>1850 && $iYear<3000) {  }//end if (preg_match

PHP: Zend Framework, MVC, Cookies and 4096 byte oddities

November 27th, 2008

A little word of warning which has puzzled me for over 3 hours in debugging…

If you use Zend_Controller_Front::getInstance()->dispatch(); in your Zend Framework index.php file for firing off the MVC system, and the returned page is over 4096 bytes (4 kilobytes) in size you cannot set a cookie afterwards without causing the “fun” error “Cannot modify header information – headers already sent by (output started at …/library/Zend/Controller/Response/Abstract.php:546) in …”

To work around this, you’ll need to change the code from just:

Zend_Controller_Front::getInstance()->dispatch();
setcookie(. . .);

to:

$front=Zend_Controller_Front::getInstance();
$front->returnResponse(true);
$response=$front->dispatch();
#Zend_Controller_Front::getInstance()->dispatch();
setcookie(. . .);
$response->sendResponse();

I’m sure there is a slightly better way of setting Cookies in the Zend Framework, but that’s a work around for the normal way I’ve found.

If you’ve got any “better idea” suggestions, just let me know.

(I found this “buglet” because a drop down select menu I was making with Zend Form Element was causing the “Cannot modify header information – headers already sent by” error once a number of items were listed: it took 3 hours+ of detection work to narrow it down to a content size issue, then it was a process of elimination ruling out Zend_Form_Element, Zend_Form, Zend_View and Zend_View_Abstract (which helped a bit with the debugging on the issue) and then to Zend_Controller_Front to Zend_Controller_Response_Http and finally to Zend_Controller_Response_Abstract)

Snippet: PHP, MySQL and IDN Email addresses

November 20th, 2008

Here’s something to look out for if you are building an international website where you are handling email addresses…

Email addresses, as you are probably aware, comprise of two parts. The “local part” (the bit before the @ sign) and the “domain part” (the bit after the @ sign). Therefore with the email address richard@example.invalid , “richard” is the local part and “example.invalid” is the domain part.

The domain part of the email address can actually be 255 characters in length theoretically (it’s 63 characters for the actually domain name, then the TLD: however, you could have sub domains in force which can take it up to the 255 limit.

The local part of the email address can be 64 characters: bringing the count up to 319 characters. Allow an extra one for the “@” sign and 320… Just slightly too big to fit within the standard 255/256 character string field that has tended to be used. I’ve seen rumours that this section may be expanded to 128 characters, so plan for 383 characters.

Oh – don’t forget that Internationalised/Internationalized Domain Names are becoming popular in some countries and unless you want to handle conversion to/from Punycode or another storage format for the IDNs, then you’ll need to make your database store the email address in Unicode… However, that appears to cause a problem in some version of MySQL if you store it all in a Varchar field.

So in your programming language (such as PHP), you’re going to have to keep all the above in mind and then split the email address into two parts for storing in the database for sanity.

See http://www.faqs.org/rfcs/rfc2821.html, http://en.wikipedia.org/wiki/E-mail_address, http://www.santosj.name/general/stop-doing-email-validation-the-wrong-way/ and http://askville.amazon.com/maximum-length-allowed-email-address/AnswerViewer.do?requestId=1166932.

PHP: Avoiding “Headers already sent by…” errors

March 3rd, 2008

Just a quick post inspired by Techgirl, here’s how to avoid the annoying PHP errors “Headers already sent by…” when working with multiple files.

Basically, a PHP script usually looks like:

<?php
include "my.lib.php";
include "otherstuff.php";
....
?>

however, if my.lib.php (for example) looks like:

<?php
....
...
?>


(do you see the hidden “new line at the end”), you’ll get the “Warning: Cannot modify header information – headers already sent by (output started at my.lib.php:6) in index.php on line 2? error.

So how do you simpley avoid this? Easy! Omit the closing ?> from the library/include files. My.lib.php now looks like:

<?php
....
...

and the problem is solved.

Simple, quick solution which is worth remembering!

PHP: Making use of Object Orientated PHP

February 22nd, 2008

Just a quickie: From Tim of Sacratee there is a post on Jatecblog about Making use of Object Oriented PHP which provides a good simple example of how to use OOP in PHP5 to build a module-based system.

gamy-dance
%d bloggers like this: