Category Archives: PHPUnit

Building a FTP client library with PHP

In my daily work I need to connect very often to FTP servers. Put files, read, list and things like that. I normally use the standard PHP functions for Ftp it’s pretty straight forward to use them. Just enable it within our installation (–enable-ftp) and it’s ready to use them. But last Sunday it was raining again and I start with this simple library.

Lets connect to a FTP server, switch to passive mode, put a file from one real file stored in our local filesystem and delete it.

use FtpLib\Ftp,
    FtpLib\File;

list($host, $user, $pass) = include __DIR__ . "/credentials.php";

$ftp = new Ftp($host, $user, $pass);
$ftp->connect();
$ftp->setPasv();

$file = $ftp->putFileFromPath(__DIR__ . '/fixtures/foo');
echo $file->getName();
echo $file->getContent();
$file->delete();

Now the same, but without a real file. We are going to create the file on-the-fly from one string:

use FtpLib\Ftp,
    FtpLib\File;

list($host, $user, $pass) = include __DIR__ . "/credentials.php";

$ftp = new Ftp($host, $user, $pass);
$ftp->connect();
$ftp->setPasv();

$file = $ftp->putFileFromString('bar', 'bla, bla, bla');
echo $file->getName();
echo $file->getContent();
$file->delete();

We also can create directories, change the working directory and delete folders in the FTP server with a fluent interface (I love fluent interfaces, indeed):

$ftp->mkdir('directory')
  ->chdir('directory')
  ->putFileFromString('newFile', 'bla, bla')
  ->delete();

$ftp->rmdir('directory');

And finally we can iterate files in the FTP (I must admit that this feature was the main purpose of the library)

$ftp->getFiles(function (File $file) use ($ftp) {
    switch($file->getName()) {
        case 'file1':
            $file->delete();
            break;
        case 'file2':
            $ftp->mkdir('backup')->chdir('backup')->putFileFromString($file->getName(), $file->getContent());
            break;
    }
});

And that’s all. You can find the library in github and you also can use it with composer.

"gonzalo123/ftplib": "dev-master"

You can also see usage examples within the unit tests

Handling dates with PHP

I’ve seen a lot of newbies (and not newbies) having problems handling dates in PHP (and even with SQL and another languages). When I see someone having problems with dates, I always ask the same question. I type in a text editor “27/11/2012″ and I ask him: What is it? If your answer is “This is a date” you should continue reading the post :)

“27/11/2012″ in a text editor is not a date. It’s a string representing a date (my birthday this year, indeed :) ). We also must take into account that we cannot show a “raw” date. We only can apply a mask to a date if we want to show it. Because of that dates are normally stored internally as UNIX timestams or something similar.You can say that when we perform one SELECT statement with a date field we don’t see one timestamp. That’s because the tool that you are using to show the date field applies one mask to your date. The default mask can be also a problem. “01/02/2012″ represents 01/February/2012 or 02/January/2012? We don’t know. Depends on the mask that we are using.

When we work with PHP is very usual to use dates. Sometimes we need to pass them to SQL queries, perform operations (such as add days, diffs, compare, …). When I started with PHP 10 years ago we use to use mktime(), date(), and insane operations with split/join with strings. That’s the past. Now we have DateTime.

It’s pretty straightforward to use it. We can use one static factory to create DateTime objects

$date = DateTime::createFromFormat('d/m/Y', '27/11/2012');

Now $date is a variable that stores a DateTime object. If we want to show it, we need to apply one format. For example:

$date = DateTime::createFromFormat('d/m/Y', '27/11/2012');
echo $date->format('m/d/Y');  // outputs 11/27/2012

I’m not going to create a tutorial of DateTime here. It’s very good described (as always) within PHP official documentation. There is something that I love with DateTime objects also:

$date1 = DateTime::createFromFormat('d/m/Y', '27/11/2012');
$date2 = DateTime::createFromFormat('d/m/Y', '27/11/2011');

if ($date1 > $date2) {
    echo "It works!"
}

In my last projects when I need to use Dates I like to cast the variables as DateTime objects. Let me show you a little example:

<?php

class Dummy
{
    /** @var DateTime */
    private $date;
    private $defaultFormat = 'd/m/Y';

    public function setDate(DateTime $date)
    {
        $this->date = $date;
    }

    public function getDate()
    {
        return $this->date;
    }

    public function getFormattedDate($format = NULL)
    {
        return $this->date->format($this->getFormat($format));
    }

    public function setFormattedDate($formatedDate, $format = NULL)
    {
        $this->date = DateTime::createFromFormat($this->getFormat($format), $formatedDate);
    }

    public function setDefaultFormat($format)
    {
        $this->defaultFormat = $format;
    }

    private function getFormat($format)
    {
        return is_null($format) ? $this->defaultFormat : $format;
    }
}

But maybe, as always, the best documentation are the Unit Tests

<?php

class DummyTest extends \PHPUnit_Framework_TestCase
{
    public function testDate()
    {
        $date  = DateTime::createFromFormat('d/m/Y', '1/2/2012');
        $dummy = new Dummy();
        $dummy->setDate($date);
        $this->assertEquals($date, $dummy->getDate());
    }

    public function testDateWithAlternativeSetter()
    {
        $dummy = new Dummy();
        $dummy->setFormattedDate('1/2/2012', 'd/m/Y');
        $this->assertEquals(DateTime::createFromFormat('d/m/Y', '1/2/2012'), $dummy->getDate());
    }

    public function testDateWithAlternativeSetterWithDeffaultFormatSet()
    {
        $dummy = new Dummy();
        $dummy->setDefaultFormat('d/m/Y');
        $dummy->setFormattedDate('1/2/2012');
        $this->assertEquals(DateTime::createFromFormat('d/m/Y', '1/2/2012'), $dummy->getDate());
    }

    public function testFormatGetterWithDefaultFormat()
    {
        $dummy = new Dummy();
        $dummy->setFormattedDate('1/2/2012');
        $this->assertEquals('2012', $dummy->getDate()->format('Y'));
    }
    
    public function testFormatGetter()
    {
        $dummy = new Dummy();
        $dummy->setFormattedDate('1/2/2012');
        $this->assertEquals('2012', $dummy->getFormattedDate('Y'));
    }

    public function testDiffDates()
    {
        $dummy = new Dummy();
        $dummy->setFormattedDate('1/2/2012');
        $date = DateTime::createFromFormat('d/m/Y', '1/2/2011');

        $this->assertTrue($date < $dummy->getDate());
    }

    public function testModifyDates()
    {
        // leap-years
        $dummy = new Dummy();
        $dummy->setFormattedDate('28/02/1908');
        $this->assertEquals('29/02/1908', $dummy->getDate()->modify("+1 day")->format('d/m/Y'));

        // Non leap-years
        $dummy = new Dummy();
        $dummy->setFormattedDate('28/02/2001');
        $this->assertEquals('01/03/2001', $dummy->getDate()->modify("+1 day")->format('d/m/Y'));
    }
}

What do you think?

The reason why singleton is a “problem” with PHPUnit

Singleton is a common design pattern. It’s easy to understand and we can easily implement it with PHP:

<?php
class Foo
{
    static private $instance = NULL;

    static public function getInstance()
    {
        if (self::$instance == NULL) {
            self::$instance = new static();
        }
        return self::$instance;
    }
}

Maybe this pattern is not as useful as it is in J2EE world. With PHP everything dies within each request, so we cannot persist our instances between requests (without any persistent mechanism such as databases, memcached or external servers). But at least in PHP we can share the same instance, with this pattern, in our script. No matter were we are, we use Foo::getInstance() and we get our instance. It useful when we work, for example, with database connections and service containers.

If we work with TDD we most probably use PHPUnit. Imagine a simple script to test the instantiation of our Foo class

class FooTest extends PHPUnit_Framework_TestCase
{
    public function testGetInstance()
    {
        $this->assertInstanceOf('Foo', Foo::getInstance());
    }
}

All is green. It works.

Imagine now we want to “improve” our Foo class and we want to create a counter:

    public function testCounter()
    {
        $foo = Foo::getInstance();
        $this->assertEquals(0, $foo->getCounter());
        $foo->incrementCounter();
        $this->assertEquals(1, $foo->getCounter());
    }

Now our test fails, So we change our implementation of the class to pass the test and we add to Foo class

    private $counter = 0;

    public function getCounter()
    {
        return $this->counter;
    }

    public function incrementCounter()
    {
        $this->counter++;
    }

It’s green again. We are using a singleton pattern to get the instance of the class and we are using TDD, so what’s the problem? I will show you with an example. Imagine we need to improve our Foo class and we want a getter to say if counter is even or not. We add a new test:

    public function testIsOdd()
    {
        $foo = Foo::getInstance();
        $this->assertEquals(FALSE, $foo->counterIsOdd(), '0 is even');
        $foo->incrementCounter();
        $this->assertEquals(TRUE, $foo->counterIsOdd(), '1 is uneven');
    }

And we implement the code to pass the test again:

    public function counterIsOdd()
    {
        return $this->counter % 2 == 0 ? FALSE : TRUE;
    }

But it doesn’t work. Our test is red now. Why? The answer is simple. We are sharing the same instance of Foo class in both tests, so in the first one our counter start with 0 (the default value) but with the second one it start with 1, because the first test has changed the state of the instance (and we are reusing it).

This is a trivial example, but real world problems with this issue are a bit nightmare. Imagine, for example, that we use singleton pattern to get the database connection (a common usage of this pattern). Suddenly we break one test (because we have created a wrong SQL statement). Imagine we have a test suite with 100 assertions. We have broken one assertion (the second one, for example), and our PHPUnit script will say that we have 99 errors (the second one and all the following ones). That happens because our script can’t reuse the database connection (it’s broken in the second test). Too much garbage in the output of the PHPUnit script and that’s not agile.

How to solve it? We have two possible solutions. The first one is avoid singletons as a plague. We have alternatives such as dependency injection, but if we really want to use them (they are not forbidden, indeed) we need to remember to write one static function in our class to reset all our static states and call after each test. PHPUnit allow to execute something at the end of each test with tearDown() function. So we add to our test:

class FooTest extends PHPUnit_Framework_TestCase
{
...
    public function tearDown()
    {
        Foo::tearDown();
    }
}

And now we implement the tearDown function in our Foo Class

    public static function tearDown()
    {
        static::$instance = NULL;
    }

And all works again. All is green and green is cool, isn’t it? :)

Note: Take into account that “problem” is between quotes in the title. That’s beacause singleton is not a “real” problem. We can use it, it isn’t forbiden, but we need to realize the collateral effects that its usage can throw to our code.

Follow

Get every new post delivered to your Inbox.

Join 550 other followers