How to call shell programs as functions with PHP

I’m a big fan of Symfony’s Process Component. I’ve used intensively this component within a project and I noticed that I needed a wrapper to avoid to write again and again the same code. Suddenly a cool python library came to my head: sh. With python’s sh we can call any program as if it were a function:

from sh import ifconfig
print(ifconfig("wlan0"))

Outputs:

wlan0   Link encap:Ethernet  HWaddr 00:00:00:00:00:00
        inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
        inet6 addr: ffff::ffff:ffff:ffff:fff/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:0 errors:0 dropped:0 overruns:0 frame:0
        TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000
        RX bytes:0 (0 GB)  TX bytes:0 (0 GB)

So I decided to develop something similar in PHP. This library is not exactly the same than python one. Python’s sh allows more cool things such as non-blocking processes, baking, … not available in my PHP one’s, but at least I can call shell programs as functions in a simple way (and that’s was my scope). Let’s start.

One simple example of Process:

use Symfony\Component\Process\Process;

$process = new Process('-latr ~');
$process->setTimeout(3600);
$process->run();

echo $process->getOutput();

With sh library we can do:

use Sh/Sh;

$sh  = new Sh();
echo $sh->ls('-latr ~');

You can check the source code in github, but it’s very simple one. Basically it’s a parser that creates the command line string, and another class that calls to the parser and sends the output to Process component. Whit the magic function __call we can use shell commands as functions.

The command’s arguments can be one string ‘-latr ~’ or one array ['-latr', '~']. You can see more example in the unit tests here

Symfony/Process also allows us to get feedback in real time:

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
$process->run(function ($type, $buffer) {
    if ('err' === $type) {
        echo 'ERR > '.$buffer;
    } else {
        echo 'OUT > '.$buffer;
    }
});

Sh uses this feature, so we can do things like that:

$sh->tail('/var/log/messages', function ($buffer)  {
    echo $buffer;
});

We can see more examples here:

<?php
error_reporting(-1);
include __DIR__ . '/../vendor/autoload.php';
use Sh\Sh;

echo Sh::factory()->runCommnad('notify-send', ['-t', 5000, 'title', 'HOLA']);
$sh  = new Sh();
echo $sh->ifconfig("eth0");
echo $sh->ls('-latr ~');
echo $sh->ls(['-latr', '~']);
$sh->tail('-f /var/log/apache2/access.log', function ($buffer)  {
    echo $buffer;
});

As I said before the library is in github and also you can use with composer:

require: "gonzalo123/sh": "dev-master"

Updated!

Now Sh library supports chained arguments (baking)

// chainable commands (baking)
$sh->ssh(array('myserver.com', '-p' => 1393))->whoami();
// executes: ssh myserver.com -p 1393 whoami

$sh->ssh(array('myserver.com', '-p' => 1393))->tail(array("/var/log/dumb_daemon.log", 'n' => 100));
// executes: ssh myserver.com -p 1393 tail /var/log/dumb_daemon.log -n 100
});

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

Live changes within node.js scripts without stop/start

Imagine that you are working within a nodejs project. This simple script:

var CONF = ['item1', 'item2', 'item3'];

var last;
setInterval(function () {
    var next = CONF.indexOf(last) + 1;
    last = (CONF[next] == undefined) ? CONF[0] : CONF[next];
    console.log(last);
}, 1000);

If we run this script, we will see in the console one element of CONF each second. Simple, isn’t it?. OK, imagine now we want to add one new element to the list (let’s say item4). We can easily change the script, stop the execution and run again. OK but imagine that we cannot stop/start the script as many times as we want. What can we do?. We can store the CONF data into one external storage (Redis, for example), but today we are going to do something more easy. We are going to modify CONF in execution time. The idea is to open a TCP socket and let change CONF with a simple protocol.

If we change the script to:

var net = require('net');
var CONF_PORT = 9730;
var CONF = ['item1', 'item2', 'item3'];

var last;
setInterval(function () {
    var next = CONF.indexOf(last) + 1;
    last = (CONF[next] == undefined) ? CONF[0] : CONF[next];
    console.log(last);
}, 1000);

var serverConf = net.createServer(function (confSocket) {
    confSocket.on("data", function (data) {
        var dataAsString = data.toString().trim();
        switch (dataAsString.substr(0, 1)) {
            case '+':
                var userVariable = dataAsString.substr(1);
                if (CONF.indexOf(userVariable) < 0) {
                    CONF.push(userVariable);
                    confSocket.write("+ " + userVariable + " added\n");
                } else {
                    confSocket.write("+ " + userVariable + " already added\n");
                }
                break;
            case '-':
                var userVariable = dataAsString.substr(1);
                if (CONF.indexOf(userVariable) >= 0) {
                    CONF.splice(CONF.indexOf(userVariable), 1)
                    confSocket.write("- " + userVariable + " deleted\n");
                } else {
                    confSocket.write("- " + userVariable + " don't exists\n");
                }
                break;
            case '=':
                for (var i in CONF) {
                    confSocket.write(CONF[i] + "\n");
                }
                break;
        }
        confSocket.write("\n");
        confSocket.write("Number of elements: " + CONF.length + "\n");
        confSocket.end("\n");
    });
});
serverConf.listen(CONF_PORT);

You can see the script in action here:

Managing Windows services with Symfony/Process and PHP

Sometimes I need to stop/start remote Windows services with PHP. It’s quite easy to do it with net commnand. This command is a tool for administration of Samba and remote CIFS servers. It’s pretty straightforward to handle them from Linux command line:

net rpc service --help
Usage:
net rpc service list
    View configured Win32 services
net rpc service start
    Start a service
net rpc service stop
    Stop a service
net rpc service pause
    Pause a service
net rpc service resume
    Resume a service
net rpc service status
    View current status of a service
net rpc service delete
    Deletes a service
net rpc service create
    Creates a service

Today we are going to create a PHP wrapper for this tool. Our NetService library will have two classes: One Parser and one Service class.

The Parser’s responsibility will be create the command line instruction. I will use Behat in the developing process of Parser class. Here we can see the feature file:

Feature: command line parser

  Scenario: net service list
    Given windows server host called "windowshost.com"
    And credentials are "myDomanin/user%password"
    And action is "list"
    Then command line is "net rpc service list -S windowshost.com -U myDomanin/user%password"

  Scenario: net service start
    Given windows server host called "windowshost.com"
    And service name called "ServiceName"
    And credentials are "myDomanin/user%password"
    And action is "start"
    Then command line is "net rpc service start ServiceName -S windowshost.com -U myDomanin/user%password"

  Scenario: net service stop
    Given windows server host called "windowshost.com"
    And service name called "ServiceName"
    And credentials are "myDomanin/user%password"
    And action is "stop"
    Then command line is "net rpc service stop ServiceName -S windowshost.com -U myDomanin/user%password"

  Scenario: net service pause
    Given windows server host called "windowshost.com"
    And service name called "ServiceName"
    And credentials are "myDomanin/user%password"
    And action is "pause"
    Then command line is "net rpc service pause ServiceName -S windowshost.com -U myDomanin/user%password"

  Scenario: net service resume
    Given windows server host called "windowshost.com"
    And service name called "ServiceName"
    And credentials are "myDomanin/user%password"
    And action is "resume"
    Then command line is "net rpc service resume ServiceName -S windowshost.com -U myDomanin/user%password"

  Scenario: net service status
    Given windows server host called "windowshost.com"
    And service name called "ServiceName"
    And credentials are "myDomanin/user%password"
    And action is "status"
    Then command line is "net rpc service status ServiceName -S windowshost.com -U myDomanin/user%password"

The implementation of the feature file:

namespace NetService;

class Parser
{
    private $host;
    private $credentials;

    public function __construct($host, $credentials)
    {
        $this->host        = $host;
        $this->credentials = $credentials;
    }

    public function getCommandLineForAction($action, $service = NULL)
    {
        if (!is_null($service)) $service = " {$service}";
        return "net rpc service {$action}{$service} -S {$this->host} -U {$this->credentials}";
    }
}

and finally our Service class:

namespace NetService;

use Symfony\Component\Process\Process,
    NetService\Parser;

class Service
{
    private $parser;
    private $timeout;

    const START = 'start';
    const STOP = 'stop';
    const STATUS = 'status';
    const LIST_SERVICES = 'list';
    const PAUSE = 'pause';
    const RESUME = 'resume';

    const DEFAULT_TIMEOUT = 3600;

    public function __construct(Parser $parser)
    {
        $this->parser = $parser;
        $this->timeout = self::DEFAULT_TIMEOUT;
    }

    public function start($service)
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::START, $service));
    }

    public function stop($service)
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::STOP, $service));
    }

    public function pause($service)
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::PAUSE, $service));
    }

    public function resume($service)
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::RESUME, $service));
    }

    public function status($service)
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::STATUS, $service));
    }

    public function listServices()
    {
        return $this->runProcess($this->parser->getCommandLineForAction(self::LIST_SERVICES));
    }

    public function isRunning($service)
    {
        $status = explode("\n", $this->status($service));
        if (isset($status[0]) && strpos(strtolower($status[0]), "running") !== FALSE) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;
    }

    private function runProcess($commandLine)
    {
        $process = new Process($commandLine);
        $process->setTimeout($this->timeout);
        $process->run();

        if (!$process->isSuccessful()) {
            throw new RuntimeException($process->getErrorOutput());
        }

        return $process->getOutput();
    }

    private function parseStatus($status)
    {
        return explode("\n", $status);
    }
}

And that’s all. Now a couple of examples:

include __DIR__ . '/../vendor/autoload.php';

use NetService\Service,
    NetService\Parser;

$host        = 'windowshost.com';
$serviceName = 'ServiceName';
$credentials = '{domain}/{user}%{password}';

$service = new Service(new Parser($host, $credentials));

if ($service->isRunning($serviceName)) {
    echo "Service is running. Let's stop";
    $service->stop($serviceName);

} else {
    echo "Service isn't running. Let's start";
    $service->start($serviceName);
}

//dumps status output
echo $service->status($serviceName);
include __DIR__ . '/../vendor/autoload.php';

use NetService\Service,
    NetService\Parser;

$host        = 'windowshost.com';
$credentials = '{domain}/{user}%{password}';

$service = new Service(new Parser($host, $credentials));
echo $service->listServices();

You can see the full code in github here. The package is also available for composer at Packaist.

Building a Silex application from one Behat/Gherkin feature file

Last days I’ve playing with Behat. Behat is a behavior driven development (BDD) framework based on Ruby’s Cucumber. Basically with Behat we defenie features within one feature file. I’m not going to crate a Behat tutorial (you can read more about Behat here). Behat use Gherkin to write the features files. When I was playing with Behat I had one idea. The idea is simple: Can we use Gherking to build a Silex application?. It was a good excuse to study Gherking, indeed ;) .

Here comes the feature file:

Feature: application API
  Scenario: List users
    Given url "/api/users/list.json"
    And request method is "GET"
    Then instance "\Api\Users"
    And execute function "listUsers"
    And format output into json

  Scenario: Get user info
    Given url "/api/user/{userName}.json"
    And request method is "GET"
    Then instance "\Api\User"
    And execute function "info"
    And format output into json

  Scenario: Update user information
    Given url "/api/user/{userName}.json"
    And request method is "POST"
    Then instance "\Api\User"
    And execute function "update"
    And format output into json

Our API use this simple library:

<?php

namespace Api;
use Symfony\Component\HttpFoundation\Request;

class User
{
    private $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function info()
    {
        switch ($this->request->get('userName')) {
            case 'gonzalo':
                return array('name' => 'Gonzalo', 'surname' => 'Ayuso');
            case 'peter':
                return array('name' => 'Peter', 'surname' => 'Parker');
        }
    }

    public function update()
    {
        return array('infoUpdated');
    }
}
<?php

namespace Api;
use Symfony\Component\HttpFoundation\Request;

class Users
{
    public function listUsers()
    {
        return array('gonzalo', 'peter');
    }
}

The idea is simple. Parse the feature file with behat/gherkin component and create a silex application. And here comes the “magic”. This is a simple working prototype, just an experiment for a rainy sunday.

<?php
include __DIR__ . '/../vendor/autoload.php';
define(FEATURE_PATH, __DIR__ . '/api.feature');

use Behat\Gherkin\Lexer,
        Behat\Gherkin\Parser,
        Behat\Gherkin\Keywords\ArrayKeywords,
        Behat\Gherkin\Node\FeatureNode,
        Behat\Gherkin\Node\ScenarioNode,
        Symfony\Component\HttpFoundation\Request,
        Silex\Application;

$keywords = new ArrayKeywords([
    'en' => [
        'feature' => 'Feature',
        'background' => 'Background',
        'scenario' => 'Scenario',
        'scenario_outline' => 'Scenario Outline',
        'examples' => 'Examples',
        'given' => 'Given',
        'when' => 'When',
        'then' => 'Then',
        'and' => 'And',
        'but' => 'But'
    ],
]);

function getMatch($subject, $pattern) {
    preg_match($pattern, $subject, $matches);
    return isset($matches[1]) ? $matches[1] : NULL;
}

$app = new Application();

function getScenarioConf($scenario) {
    $silexConfItem = [];

    /** @var $scenario  ScenarioNode */
    foreach ($scenario->getSteps() as $step) {
        $route = getMatch($step->getText(), '/^url "([^"]*)"$/');

        if (!is_null($route)) {
            $silexConfItem['route'] = $route;
        }

        $requestMethod = getMatch($step->getText(), '/^request method is "([^"]*)"$/');
        if (!is_null($requestMethod)) {
            $silexConfItem['requestMethod'] = strtoupper($requestMethod);
        }

        $instance = getMatch($step->getText(), '/^instance "([^"]*)"$/');
        if (!is_null($instance)) {
            $silexConfItem['className'] = $instance;
        }

        $method = getMatch($step->getText(), '/^execute function "([^"]*)"$/');
        if (!is_null($method)) {
            $silexConfItem['method'] = $method;
        }

        if ($step->getText() == 'format output into json') {
            $silexConfItem['jsonEncode'] = TRUE;
        }
    }
    return $silexConfItem;
}

/** @var $features FeatureNode */
$features = (new Parser(new Lexer($keywords)))->parse(file_get_contents(FEATURE_PATH), FEATURE_PATH);

foreach ($features->getScenarios() as $scenario) {
    $silexConfItem = getScenarioConf($scenario);
    $app->match($silexConfItem['route'], function (Request $request) use ($app, $silexConfItem) {
            function getConstructorParams($rClass, $request) {
                $parameters =[];
                foreach ($rClass->getMethod('__construct')->getParameters() as $parameter) {
                    if ('Symfony\Component\HttpFoundation\Request' == $parameter->getClass()->name) {
                        $parameters[$parameter->getName()] = $request;
                    }
                }
                return $parameters;
            }

            $rClass = new ReflectionClass($silexConfItem['className']);
            $obj = ($rClass->hasMethod('__construct')) ?
                    $rClass->newInstanceArgs(getConstructorParams($rClass, $request)) :
                    new $silexConfItem['className'];

            $output = $obj->{$silexConfItem['method']}();

            return ($silexConfItem['jsonEncode'] === TRUE) ? $app->json($output, 200) : $output;
        }
    )->method($silexConfItem['requestMethod']);
}

$app->run();

You can see the source code in github. What do you think?

How to rewrite urls with PHP 5.4′s built-in web server

PHP 5.4 comes with a flaming built-in web server. This server is (obviously) not suitable to use in production environments, but it’s great if we want to check one project quickly:

  • git clone from github
  • composer install to install dependencies
  • run the built-in web server and test the application.
php -S localhost:8888 -t www/

But is very usual to use mod_rewrite or similar to send all requests to the front controller. With apache is pretty straight forward to do it:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

But, does it work with the built-in web server? The answer is yes, but with another syntax. We only need to create one router file and start our server with this router:

<?php
// www/routing.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
    return false;
} else {
    include __DIR__ . '/index.php';
}

And now we start the server with:

php -S localhost:8888 www/routing.php

Easy, isn’t it?

How to send the output of Symfony’s process Component to a node.js server in Real Time with Socket.io

Today another crazy idea. Do you know Symfony Process Component? The Process Component is a simple component that executes commands in sub-processes. I like to use it when I need to execute commands in the operating system. The documentation is pretty straightforward. Normally when I want to collect the output of the script (imagine we run those scripts within a crontab) I save the output in a log file and I can check it even in real time with tail -f command.

This approach works, but I want to do it in a browser (call me crazy :) ). I’ve written a couple of posts with something similar. What I want to do now? The idea is simple:

First I want to execute custom commands with process. Just follow the process documentation:

<?php
use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
$process->setTimeout(3600);
$process->run();
if (!$process->isSuccessful()) {
    throw new \RuntimeException($process->getErrorOutput());
}

print $process->getOutput();

Process has one cool feature, we can give feedback in real-time by passing an anonymous function to the run() method:

<?php
use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
$process->run(function ($type, $buffer) {
    if ('err' === $type) {
        echo 'ERR > '.$buffer;
    } else {
        echo 'OUT > '.$buffer;
    }
});

The idea now is to use this callback to send a TCP socket to one server with node.js

var LOCAL_PORT = 5600;
var server = require('net').createServer(function (socket) {
    socket.on('data', function (msg) {
        console.log(msg);
    });
}).listen(LOCAL_PORT);

server.on('listening', function () {
    console.log("TCP server accepting connection on port: " + LOCAL_PORT);
});

Now we change our php script to

<?php
include __DIR__ . "/../vendor/autoload.php";

use Symfony\Component\Process\Process;

function runProcess($command)
{
    $address = 'localhost';
    $port = 5600;
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_connect($socket, $address, $port);

    $process = new Process($command);
    $process->setTimeout(3600);
    $process->run(
        function ($type, $buffer) use ($socket) {
            if ('err' === $type) {
                socket_write($socket, "ERROR\n", strlen("ERROR\n"));
                socket_write($socket, $buffer, strlen($buffer));
            } else {

                socket_write($socket, $buffer, strlen($buffer));
            }
        }
    );
    if (!$process->isSuccessful()) {
        throw new \RuntimeException($process->getErrorOutput());
    }
    socket_close($socket);
}

runProcess('ls -latr /');

Now with the node.js started, if we run the php script, we will see the output of the process command in the node’s terminal. But we want to show it in a browser. What can we do? Of course, socket.io. We change the node.js command to:

var LOCAL_PORT = 5600;
var SOKET_IO_PORT = 8000;
var ioClients = [];

var io = require('socket.io').listen(SOKET_IO_PORT);

var server = require('net').createServer(function (socket) {
    socket.on('data', function (msg) {
        ioClients.forEach(function (ioClient) {
            ioClient.emit('log', msg.toString().trim());
        });
    });
}).listen(LOCAL_PORT);

io.sockets.on('connection', function (socketIo) {
    ioClients.push(socketIo);
});

server.on('listening', function () {
    console.log("TCP server accepting connection on port: " + LOCAL_PORT);
});

and finally we create a simple web client:

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script>
    var socket = io.connect('http://localhost:8000');
    socket.on('log', function (data) {
        console.log(data);
    });
</script>

Now if we start one browser we will see the output of our command line process within the console tab of the browser.

If you want something like webConsole, I also have created the example, With a Web UI enabling to send custom commands. You can see it in github.

Obviously that’s only one experiment with a lot of security issues that we need to take into account if we want to use it in production. What do you think?

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.

Building a simple TCP proxy server with node.js

Today we are going to build a simple TCP proxy server. The scenario is the following one. We have got one host (the client) that establishes a TCP connection to another one (the remote).

client —> remote

We want to set up a proxy server in the middle, so the client will establish the connection with the proxy and the proxy will forward it to the remote, keeping in mind the remote response also.
With node.js is really simple to perform those kind of network operations.

client —> proxy -> remote

var net = require('net');

var LOCAL_PORT  = 6512;
var REMOTE_PORT = 6512;
var REMOTE_ADDR = "192.168.1.25";

var server = net.createServer(function (socket) {
    socket.on('data', function (msg) {
        console.log('  ** START **');
        console.log('<< From client to proxy ', msg.toString());
        var serviceSocket = new net.Socket();
        serviceSocket.connect(parseInt(REMOTE_PORT), REMOTE_ADDR, function () {
            console.log('>> From proxy to remote', msg.toString());
            serviceSocket.write(msg);
        });
        serviceSocket.on("data", function (data) {
            console.log('<< From remote to proxy', data.toString());
            socket.write(data);
            console.log('>> From proxy to client', data.toString());
        });
    });
});

server.listen(LOCAL_PORT);
console.log("TCP server accepting connection on port: " + LOCAL_PORT);

Simple, isn’t it?
Source code in github

Follow

Get every new post delivered to your Inbox.

Join 551 other followers