PHP switch

Posted on Tuesday, August 31st, 2010 under , ,

Over the years, I’ve encountered a lot of strange things in PHP, but this one is off the scale:

$value = 'zero';
 
switch ($value) {
    case 0:
        echo 'value is zero';
        break;
    default:
        echo 'value is not zero';
        break;
}
echo PHP_EOL;

What do you think that the code above will print? Well…I’ll spare you the hassle and give you the answer:

% php test.php  
value is zero

This weird behavior originates in the fact that PHP uses the equality operator (==) instead of the identity (===) one when evaluating expressions inside a switch statement. It’s basically the same as:

if ('foo' == 0) {
    echo 'bar';
}

…which also yields unexpected results. I hate this type of casting!!!

Accessing a method defined in the current class’ “granpa”

Posted on Wednesday, August 4th, 2010 under ,

Problem: we have an hierarchy of 3 classes, each extending the one in front (grandfather, father, son). A method – let’s say foo() – is defined in the grandfather class and overridden with a new functionality in the father class.

Question: Is there a way in the son class to access the original method (with the grandfather code) in the son class?

Of course, the obvious solution is to try something like:

parent::parent::method();

But it won’t work. It will just yield an error like:

Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in …

After some struggling, I have found a way to get around and access a method from the grandparent class that was overridden in the parent and run its “original” code. It’s loosely based on the strange PHP scoping that I wrote about in this article. The approach goes something like this:

class Grandfather
{
    protected $_message = 'Luke, I am your grandfather';
 
    public function say()
    {
        echo $this->_message;
    }
}
 
class Father extends Grandfather
{
    protected $_message = 'Luke, I am your father';   
 
    public function say()
    {
        throw new Exception("I can't breath under this f**cking mask :(");
    }
}
 
class Son extends Father
{
    protected $_message = 'I have a very bad feeling about this';
 
    public function say()
    {
        Grandfather::say();
    }
}
 
$son = new Son();
$son->say();

Now PHP will bind the $this pointer in the body of the say() method – using the code defined in the grandfather. I guess that weird scoping is there for a reason.

Remove empty array elements with recursive lambda in PHP 5.3

Posted on Thursday, June 17th, 2010 under , , ,

How do you remove empty elements from a PHP array? The answer’s quite simple: array_filter(). Straight from manual and works like a charm:

$filtered = array_filter($raw);

Well, most of the time. It’s not recursive by default, so it only removes empty items on the first level of the array. If you have nested arrays and wish to remove all the empty items, regardless of their position in the matrix, array_filter() won’t work.

For example, let’s consider the following construct:

$raw = array(
    'firstname' => 'Foo',
    'lastname'  => 'Bar',
    'nickname' => '',
    'birthdate' => array( 
        'day'   => '',
        'month' => '',
        'year'  => '',
    ),
    'likes' => array(
        'cars'  => array('Subaru Impreza WRX STi', 'Mitsubishi Evo', 'Nissan GTR'),
        'bikes' => array(),
    ),
);

In this case, PHP’s built in array_filter() will miss the “birthdate” and “bikes” items. So, what now? Of course, you can create a function that will remove empty items recursively and pass it as a callback to PHP’s array_filter() function:

function removeEmptyItems($item)
{
    if (is_array($item)) {
        return array_filter($item, 'removeEmptyItems');
    }
 
    if (!empty($item)) {
        return true;    
    }
}
 
$filtered = array_filter($raw, 'removeEmptyItems');

But if you’re using a framework like Zend Framework that forbids using functions in the global scope and asks that all functions are wrapped in classes as static methods, things become more complicated and verbose. Yeah, yeah, I know, I’m a standards nazi :)

But if you’re using PHP 5.3, there’s a much simpler solution:

$callback = function($item) use (&$callback) {
    if (is_array($item)) {
        return array_filter($item, $callback);
    }
    if (!empty($item)) {
        return $item;
    }
};
 
$filtered = array_filter($raw, $callback);

Lambdas are sweet :)

Strange PHP scoping

Posted on Tuesday, May 11th, 2010 under , ,

I came to the conclusion that PHP is the programing language with the weirdest features. After the variable variables mess, that allows to you to name your variables stuff like !@#$%^&*()_+= and not be able to use them directly, I thought I saw everything. But no, yesterday I’ve bumped in another strange PHP feature. An even stranger feature.

Take a look at the code below:

class Example
{
    public function dynamicMethod($string)
    {
        // calls method baz() of the same class
        // class Example *does not have* a baz() method 
        $this->baz($string);
    }    
}
 
class Foo
{
    public function bar()
    {
        // a dynamic method called statically
        // no Example object is being instantiated
        Example::dynamicMethod('whatever');
    }
 
    public function baz($string)
    {
        echo 'Method baz() called with param "' . $string . '"' . PHP_EOL;
    }
}
 
$foo = new Foo();
$foo->bar();

What do you think the code will do? Yield an exception? A syntax error? Work? Well, strangely enough, it works:

Tudor-Barbus-MacBook% php blog-example.php
Method baz() called with param "whatever"

…and it seems that this feature is here to stay and be supported in the future, since I’m using the new PHP 5.3 version:

Tudor-Barbus-MacBook% php -v
PHP 5.3.1 (cli) (built: Feb 11 2010 02:32:22) 
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

I wonder how this can be useful to somebody.

Insert at the beginning of an array in PHP

Posted on Tuesday, February 16th, 2010 under ,

Last week, while programming, I needed to insert an array at the beginning of another. So, since basically I was just merging 2 arrays, I tried to do it like this:

$originalArray = array(
    1 => 'First item',
    4 => 'Forth item',
    5 => 'Fift item',
    10 => 'Tenth item', // and so on
);
 
$insertAtBegining = array(
    0 => 'None',
);
 
$newArray = array_merge($insertAtBegining, $originalArray);

But it didn’t work. :( It was displaying something like:

Array
(
    [0] => None
    [1] => First item
    [2] => Forth item
    [3] => Fifth item
    [4] => Tenth item
)

Not a good result, because the arrays’ keys were actually primary keys used by the RDBMS so it was very important for me to keep the original keys. I didn’t want to take the lame approach and do a foreach loop:

$newArray = $insertAtBegining;
foreach($originalArray as $key => $value) {
    $newArray[$key] = $value;
}

…because it was too obvious, so I did something less obvious, and much more complicated:

$newArray = array_combine(
    array_merge(array_keys($insertAtBegining), array_keys($originalArray)),
    array_merge(array_values($insertAtBegining), array_values($originalArray))
);

But in the end, Chris, one of my colleagues who also has a blog at SegmentationFault.es pointed out the most simple and elegant solution:

$newArray = $insertAtBegining + $originalArray;

This reminds me of the saying “Keep It Simple Stupid” :) Which Chris uses as a wallpaper…

Unit testing & TDD

Posted on Wednesday, December 2nd, 2009 under , ,

Last week, I had a discussion with Ionut – my colleague at Ninespices – about a piece of code I had wrote in one of our applications. The piece was meant to log the current user’s actions to the database for future reference. It looked something like this (more or less, the actual code isn’t that important):

protected function _log($info) {
    $identity = Zend_Auth::getInstance()->getIdentity();
    $this->save(
        array(
            'user_id' => $identity->id,
            'info' => $info,
        )
    );
}

Ionut said to me: “I don’t like it! It’s hardcoded!”. I said that it’s not, as I don’t hardcode anything, since we all know that each time one hardcodes something in a software application, God kills a kitten.

But Ionut asked me a simple question: “How do you test it? How do you mock Zend_Auth?”. For the record, Ionut is the Test Driven Development guy of the team. He always writes tests for his applications, whereas I don’t, since my code “just works”…well, kind of…sometimes :) . The point he made is interesting: how do you mock Zend_Auth? The answer is obvious: D’oh, you don’t!

In order to be able to properly use unit testing to test a piece of code, that code must be written in a manner that allows unit testing. To make a method “testable”, you must not instantiate other objects, call other classes’ static methods and so on. For instance, let’s consider a piece of code that looks like this:

public function methodThatRequiresTesting($input) {
    // get data on the current logged user
    $identity = Zend_Auth::getInstance()->getIdentity();
    $userId = $identity->id;
 
    // instantiate a helper class
    $helper = new MyLibrary_Helpers_Foo();
 
    // do whatever
}

It’s quite obvious that this code isn’t “unit testing friendly” as you cannot mock the helper or Zend_Auth. The proper way to write it in order to be “unit-testable” is either:

public function methodThatRequiresTesting($input, $userId, MyLibrary_Helpers_Foo $helper) {
    // do whatever
}

…or…

public function methodThatRequiresTesting($input) {
    // get the user id
    $userId = Zend_Registry::get('userId');
 
    // get the helper
    $helper = Zend_Registry::get('Helpers/Foo');
 
    // do whatever
}

This way, one can easily add mocks instead of the actual objects, isolate the functionality of this particular method and test it. Of course, the first “testable” code is wrong, as it breaks separation of concerns. A method should have input and output, and any additional entities (functions, classes) used inside the method’s body in order to compute the output from the input should be encapsulated within the method. Receiving these entities as input is a very bad practice, for obvious reasons.

The second code example is better from an architectural point of view, but it can be quite memory intensive, as one might instantiate a lot of helpers and place them in the registry without ever using them, thus wasting valuable system resources.

That very night, Ionut & I went to the 26th edition of Wurbe, where one the the topics was – beside the crappy beer – Test Driven Development. There was a somewhat heated debate on whether to use TDD or not, unit testing, functional (system) testing and so on. I particularly liked one of the opinions expressed there – by a guy who’s name I forgot :) – on functional testing. There’s no need to write unit tests for all your components. Only write tests for those components which contain complicated algorithms, so each time you refactor the code and optimise the algorithm, you know if what you did is good or not. And write a system test, in the end, to test the whole application.

It makes more sense to me this way.

Backslash hell

Posted on Thursday, November 26th, 2009 under , , ,

How do you write a regular expression that will match \\test – two backslashes followed by some text in PHP? Well, obviously you’ll try something like this:

echo preg_match('/^\\([a-z]+)/', $word) ? 'match' : 'no match';

…but it won’t work. Furthermore, it will yield an error saying something like:

Compilation failed: unmatched parentheses at offset …

And it makes sense, since the backslash has a special meaning, as it’s the escape character, to give it a literal meaning you have to escape it. Like such:

echo preg_match('/^\\\\([a-z]+)/', $word) ? 'match' : 'no match';

…each of the two backslashes is escaped by another backslash placed in front of it. But this also doesn’t work :) The correct way to do it is:

echo preg_match('/^\\\\\\\\([a-z]+)/', $word) ? 'match' : 'no match';

Yeap. That’s right! With 8 backslashes. For each backslash you wanted matched, you need to add 4 in the regular expression. That’s because the backslash is considered to be an escape character by both PHP’s parser and its regexp engine. So, if you type a backslash in PHP, it’s considered and escape character by PHP’s parser.

If you write two backslashes in PHP, this construct will be interpreted as a literal backslash by PHP’s paser and sent to the regexp engine as an escape character. That’s right: ‘\\’ in PHP means a ‘\’ for the regexp engine. So, in order to pass a literal backslash to the regexp engine, you need to add 4 backslashes in PHP.

This is what I call backslash hell :(

Debugging PHP with FirePHP on Zend Framework

Posted on Thursday, October 1st, 2009 under , , , ,

firephpYou know the saying: if debugging means taking the bugs out, then programming means putting them in. Yes. We all have bugs in our code. And since not all of them can be marketed as “undocumented features”, from time to time we have to debug our applications.

The best debugger for PHP I’ve used so far is Zend’s. Zend Platform together with Zend Studio constitutes a very good development environment and a great debugging environment. Due to the fact that Zend Studio is a little pricey, I don’t use it any more, instead I’m using a highly customised vim. This makes a great development environment, but unfortunately isn’t not that great when debugging. I know you can use vim with Xdebug, but it’s quite a chore, and I don’t like it. Since old school debugging with var_dump() or print_r() is out of the question, I was looking for another way to debug my applications. And I’ve found just the thing: FirePHP. It’s a Firefox extension, just like FireBug – that can receive debug information from the server.

Since I do most of my bugging programming on Zend Framework, I also need debugging for this platform. I use the OOP based bootstraping method, where you extend your Bootstrap class from Zend_Application_Bootstrap_Bootstrap. And in the .htaccess file of the /public/ directory, I have an envelope with the current state of application (usually on of development/staging/production):

SetEnv APPLICATION_ENV development

Normally, I need the debug information only when the application is in the “development” state, so I’m using this method in the Bootstrap class.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
    // Bootstrap other components
 
    /**
     * inits FirePHP for debugging
     *
     * @return void
     */
    protected function _initFirebugDebugger() {
        if(APPLICATION_ENV == 'development') {
            // don't debug while not in "development"
            $logger = new Zend_Log();
            $writer = new Zend_Log_Writer_Firebug();
            $logger->addWriter($writer);
 
            Zend_Registry::set('logger',$logger);
        }
    }
}

I also like to have some syntactic sugar when developing, so I’ve define this function in the Bootstrap.php file. Yes, I know that this might be perceived as a blasphemy by some of the OOP purists out there, but I really don’t care. If you don’t want non-OOP “stains” on your code, simply create a YourApplication_Utility_Firebug class or whatever with a static debug() method and paste the code in it.

/**
 * syntactic sugar for logging errors
 * and debug messages to FireBug
 *
 * @param string $message
 * @param int $label
 * @return void
 */
function fb($message, $label = null) {
    if($label != null) {
    	$message = array($label, $message);
    }
 
    if(Zend_Registry::isRegistered('logger')) {
    	Zend_Registry::get('logger')->log($message);
    }
}

And now, any time you need to debug something, simply type:

fb($variable);
fb($_POST); // and so on

And all these variables will be sent to Firefox’s FirePHP toolbar and you can inspect them from there. For even better results, you can also send debug information from your ErrorController to FirePHP (comes in handy when using Ajax).

PS: I’ll have a look into FireLogger for PHP. It also look pretty interesting, although it’s only in Beta.

Zend Framework SameAs validator

Posted on Tuesday, September 29th, 2009 under , ,

While working on a Zend Framework project, I’ve found myself in need of a “same as” validator. If you’re familiar with Zend Framework’s form system, then you know what a validator is, if not, enhance your knowledge on the topic by reading this page from ZF’s manual.

My validator was supposed to check if the same value was entered into two password fields, to avoid the user’s typos in passwords. You know, those annoying “please re-type your password” fields. At the time, I couldn’t find a good validator for this purpose, so I’ve decided to write my own. The source code is available on Git Hub, here.

It’s quite easy to use:

// create some filters
$stringTrimFilter = new Zend_Filter_StringTrim();
$stripTagsFilter = new Zend_Filter_StripTags();
 
// other validators
$notEmptyValidator = new Zend_Validate_NotEmpty();
$notEmptyValidator->setMessage('This field is required');
 
// create the SameAs validator
$sameAsValidator = new Generic_Validate_SameAs();
$sameAsValidator->setMessage('The 2 fields do not coincide', Generic_Validate_SameAs::NOT_THE_SAME);
 
// create the main password field
$password = new Zend_Form_Element_Password('password');
$password->setOptions(
    array(
        'label'       => 'Password',
        'required'   => true,
        'filters'      => array($stringTrimFilter, $stripTagsFilter),
        'validators' => array($notEmptyValidator),
    )
);    
 
 
// add this field to the SameAs validator
$sameAsValidator->setElement($password);
 
// create the new 
$validateNewPassword = new Zend_Form_Element_Password('validateNewPassword');
$validateNewPassword->setOptions(
    array(
        'label'        => 'Re-type the password',
        'required'   => true,
        'filters'      => array($stringTrimFilter, $stripTagsFilter),
        'validators' => array($notEmptyValidator, $sameAsValidator), // add it as a validator to the second field
    )
);

If the value entered in the second field isn’t the same as the value entered in the first field, the validator will signal an error. Simple as that.

Better PHP exchange rate script

Posted on Monday, September 28th, 2009 under ,

Long, long time ago, in a galaxy far, far away :) I was searching for a way to get the exchange rate automatically and use it in a project I was working on back then. And, following the will of the Force, I’ve came up with this script, which queries Google for the exchange rate and parses the answer page with regular expressions.

The script has proven useful to a lot of people, but, several days ago, an user called Lars Sorhus posted a comment in which he posted a link to another Google service, that outputs a (malformed) JSON containing the exchange rate.

The JSON based solution is much more elegant than parsing a HTML file with regular expressions, so I went for it, but since Google’s conversion service doesn’t output well formatted json, PHP’s built-in json_decode() function won’t work, so I had to look for another parser.

I’ve settled for PEAR’s Services_JSON class for decoding the JSON, as the test said that it can parse almost anything. And it does. Here’s is an working example:

/**
 * queries Google for the current exchange rate, doesn't need cURL
 * 
 * @param mixed  $amount
 * @param string $currency
 * @param string $exchangeIn
 * @throws Exception
 * @return mixed
 */
function exchangeRate($amount, $currency, $exchangeIn) {
    $url = @ 'http://www.google.com/ig/calculator?hl=en&q=' . urlEncode($amount . $currency . '=?' . $exchangeIn);
    $data = @ file_get_contents($url);
 
    if(!$data) {
        throw new Exception('Could not connect');
    }
 
    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
 
    $array = $json->decode($data);
 
    if(!$array) {
        throw new Exception('Could not parse the JSON');
    }
 
    if($array['error']) {
        throw new Exception('Google reported an error: ' . $array['error']);
    }
 
    return (float) $array['rhs'];
}

It uses exception, because I think that the OOP exceptions based approach is much better than return false or adding a passed by reference parameter to be used for error signaling. It’s very simple to use:

try {
	$rate = exchangeRate(1, 'euro', 'usd');
	echo 'Exchange rate is: ' . $rate;
}
catch(Exception $exception) {
	// log $exception->getMessage()
	echo 'Due to technical difficulties, we couldn\'t get the exchange rate';
}

Of course, you must include the Services_JSON.php class from the PEAR repository prior to calling exchangeRate().