How to run a Web Server from a PHP application

Normally we deploy our PHP applications in a webserver (such as apache, nginx, …). I used to have one apache webserver in my personal computer to play with my applications, but from time to now I preffer to use PHP’s built-in webserver for my experiments. It’s really simple. Just run:

php -S 0.0.0.0:8080 

and we’ve got one PHP webserver at our current directory. With another languages (such as node.js, Python) we can start a Web Server from our application. For example with node.js:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8080, '0.0.0.0');
console.log('Server running at http://0.0.0.0:8080');

With PHP we cannot do it. Sure? That assertion isn’t really true. We can do it. I’ve just create one small library to do it in two different ways. First running the built-in web server and also running one React web server.

I want to share the same interface to start the server. In this implementation we will register one callback to handle incomming requests. This callback will accept a Symfony\Component\HttpFoundation\Request and it will return a Symfony\Component\HttpFoundation\Response. Then we will start our server listening to one port and we will run our callback per Request (a simple implementeation of the reactor pattern)

We will create a static factory to create the server

namespace G\HttpServer;
use React;

class Builder
{
    public static function createBuiltInServer($requestHandler)
    {
        $server = new BuiltInServer();
        $server->registerHandler($requestHandler);

        return $server;
    }

    public static function createReactServer($requestHandler)
    {
        $loop   = React\EventLoop\Factory::create();
        $socket = new React\Socket\Server($loop);

        $server = new ReactServer($loop, $socket);
        $server->registerHandler($requestHandler);

        return $server;
    }
}

Each server (BuiltIn, and React) has its own implementation.

And basically that’s all. We can run a simple webserver with the built-in server

use G\HttpServer\Builder;
use Symfony\Component\HttpFoundation\Request;

Builder::createBuiltInServer(function (Request $request) {
        return "Hello " . $request->get('name');
    })->listen(1337);

Or the same thing but with React

use G\HttpServer\Builder;
use Symfony\Component\HttpFoundation\Request;

Builder::createReactServer(function (Request $request) {
        return "Hello " . $request->get('name');
    })->listen(1337);

As you can see our callback handles one Request and returns one Response (The typical HttpKernel), because of that we also can run one Silex application:
With built-in:

use G\HttpServer\Builder;
use Symfony\Component\HttpFoundation\Request;

$app = new Silex\Application();

$app->get('/', function () {
        return 'Hello';
    });

$app->get('/hello/{name}', function ($name) {
        return 'Hello ' . $name;
    });

Builder::createBuiltInServer(function (Request $request) use ($app) {
        return $app->handle($request);
    })->listen(1337);

And the same with React:

use G\HttpServer\Builder;
use Symfony\Component\HttpFoundation\Request;

$app = new Silex\Application();

$app->get('/', function () {
        return 'Hello';
    });

$app->get('/hello/{name}', function ($name) {
        return 'Hello ' . $name;
    });

Builder::createReactServer(function (Request $request) use ($app) {
        return $app->handle($request);
    })->listen(1337);

As an exercise I also have created one small benchmark (with both implementations) with apache ab running 100 request with a 10 request at the same time. Here you can see the outcomes.

  builtin react
Simple response    
ab -n 100 -c 10 http://localhost:1337/
Time taken for tests 0.878 seconds 0.101 seconds
Requests per second (mean) 113.91 [#/sec] 989.33 [#/sec]
Time per request (mean) 87.791 [ms] 10.108 [ms]
Time per request (mean across all concurrent requests) 8.779 [ms] 1.011 [ms]
Transfer rate 21.02 [Kbytes/sec] 112.07 [Kbytes/sec]
Silex application
ab -n 100 -c 10 http://localhost:1337/
Time taken for tests 2.241 seconds 0.247 seconds
Requests per second (mean) 44.62 [#/sec] 405.29 [#/sec]
Time per request 224.119 [ms] 24.674 [ms]
Time per request (mean across all concurrent requests) 22.412 [ms] 2.467 [ms]
Transfer rate 10.89 [Kbytes/sec] 75.60 [Kbytes/sec]
ab -n 100 -c 10 http://localhost:1337/hello/gonzalo
Time taken for tests 2.183 seconds 0.271 seconds
Requests per second (mean) 45.81 [#/sec] (mean) 369.67 [#/sec]
Time per request (mean) 218.290 [ms] (mean) 27.051 [ms]
Time per request (mean across all concurrent requests) 21.829 [ms] 2.705 [ms]
Transfer rate 11.54 [Kbytes/sec] 71.84 [Kbytes/sec]

Built-in web server is not suitable for production environments, but React would be a useful tool in some cases (maybe not good for running Facebook but good enough for punctual situations).

Library is available at github and also you can use it with composer

Taking photos with a phonegap/cordova application and uploading them to the server.

Last days I’ve working in a phonegap/cordova project. The main purpose of the project was taking photos with the device’s camera and sending them to the server. It’s a simple apache cordova project using the camera plugin. According to the documentation we can upload pictures with the following javascript code:

navigator.camera.getPicture(onSuccess, onFail, { 
    quality: 100,
    destinationType: Camera.DestinationType.DATA_URL
});

function onSuccess(imageData) {
    // here we can upload imageData to the server
}

function onFail(message) {
    alert('Failed because: ' + message);
}

As we can see we our plugin retrieves a base64 encoded version of our image and we can send it to the server, using jQuery for example

function onSuccess(imageData) {
  $.post( "upload.php", {data: imageData}, function(data) {
    alert("Image uploaded!");
  });
}

Our server side is trivial. We only need to read the request variable ‘data’, perform a base64 decode and we have our binary picture ready to be saved.

I test it with an old android smartphone (with a not very good camera) and it’s works, but when I tried to use it with a better android phone (with 8mpx camera) it hangs on and it didn’t work. After property reading the documentation I realized that it isn’t the better way to upload files to the server. It only works if the image file is small. Base64 increases the size of the image and our device can have problems handling the memory. This way Is also slow as hell.

The best way (the way that works, indeed) is, instead of sending the base64 files to the server, to save them into a device’s temporary folder and send them using the file transfer plugin.

var pictureSource;   // picture source
var destinationType; // sets the format of returned value

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    pictureSource = navigator.camera.PictureSourceType;
    destinationType = navigator.camera.DestinationType;
}

function clearCache() {
    navigator.camera.cleanup();
}

var retries = 0;
function onCapturePhoto(fileURI) {
    var win = function (r) {
        clearCache();
        retries = 0;
        alert('Done!');
    }

    var fail = function (error) {
        if (retries == 0) {
            retries ++
            setTimeout(function() {
                onCapturePhoto(fileURI)
            }, 1000)
        } else {
            retries = 0;
            clearCache();
            alert('Ups. Something wrong happens!');
        }
    }

    var options = new FileUploadOptions();
    options.fileKey = "file";
    options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
    options.mimeType = "image/jpeg";
    options.params = {}; // if we need to send parameters to the server request
    var ft = new FileTransfer();
    ft.upload(fileURI, encodeURI("http://host/upload"), win, fail, options);
}

function capturePhoto() {
    navigator.camera.getPicture(onCapturePhoto, onFail, {
        quality: 100,
        destinationType: destinationType.FILE_URI
    });
}

function onFail(message) {
    alert('Failed because: ' + message);
}

I just realized that sometimes it fails. It looks like a bug of cordova plugin (I cannot assert it), because of that, if you read my code, you can see that if fp.upload fails I retry it (only once). With this little hack it works like a charm (and it’s also fast).

The server part is pretty straightforward. We only need to handle uploaded files. Here a minimalistic example with php

<?php
move_uploaded_file($_FILES["file"]["tmp_name"], '/path/to/file');

And that’s all. We can easily upload our photos from our smartphone using phonegap/cordova.

Playing with event dispatcher and Silex. Sending logs to a remote server.

Today I continue playing with event dispatcher and Silex. Now I want to send a detailed log of our Kernel events to a remote server. We can do it something similar with Monolog, but I want to implement one working example hacking a little bit the event dispatcher. Basically we’re going to create one Logger class (implementing PSR-3 of course)

namespace G;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;

class Logger implements LoggerInterface
{
    private $socket;

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

    function __destruct()
    {
        @fclose($this->socket);
    }

    public function emergency($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::EMERGENCY);
    }

    public function alert($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::ALERT);
    }

    public function critical($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::CRITICAL);
    }

    public function error($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::ERROR);
    }

    public function warning($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::WARNING);
    }

    public function notice($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::NOTICE);
    }

    public function info($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::INFO);
    }

    public function debug($message, array $context = array())
    {
        $this->sendLog($message, $context, LogLevel::DEBUG);
    }

    public function log($level, $message, array $context = array())
    {
        $this->sendLog($message, $context, $level);
    }

    private function sendLog($message, array $context = array(), $level = LogLevel::INFO)
    {
        $data = serialize([$message, $context, $level]);
        @fwrite($this->socket, "{$data}\n");
    }
}

As you can see our Logger class send logs to a remote server, with a socket passed within the constructor.
We also need one Service Provider called LoggerServiceProvider to integrate our Logger instance into our Silex application.

namespace G;

use Silex\Application;
use Silex\ServiceProviderInterface;

class LoggerServiceProvider implements ServiceProviderInterface
{
    private $socket;

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

    public function register(Application $app)
    {
        $app['remoteLogger'] = $app->share(
            function () use ($app) {
                return new Logger($this->socket);
            }
        );
    }

    public function boot(Application $app)
    {
    }
}

And now the last part is our Silex application:

use G\LoggerServiceProvider;
use G\Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel;
use Symfony\Component\HttpKernel\Event;

$app = new Application();
$app->register(new LoggerServiceProvider(stream_socket_client('tcp://localhost:4000')));

$app->on(HttpKernel\KernelEvents::REQUEST, function (Event\GetResponseEvent $event) use ($app) {
        $app->getLogger()->info($event->getName());
    }
);

$app->on(HttpKernel\KernelEvents::CONTROLLER, function (Event\FilterControllerEvent $event) use ($app) {
        $app->getLogger()->info($event->getName());
    }
);

$app->on(HttpKernel\KernelEvents::TERMINATE, function (Event\PostResponseEvent $event) use ($app) {
        $app->getLogger()->info($event->getName());
    }
);

$app->on(HttpKernel\KernelEvents::EXCEPTION, function (Event\GetResponseForExceptionEvent $event) use ($app) {
        $app->getLogger()->critical($event->getException()->getMessage());
    }
);

$app->get('/', function () {
    return 'Hello';
});

$app->run();

As we can see the event dispacher send each event to a remote server (in this example: tcp://localhost:4000). Now we only need a tcp server to handle those sockets. We can use different tools and libraries to do that. In this example we’re going to use React.

use React\EventLoop\Factory;
use React\Socket\Server;

$loop   = Factory::create();
$socket = new Server($loop);

$socket->on('connection', function (\React\Socket\Connection $conn){
    $unique = uniqid();
    $conn->on('data', function ($data) use ($unique) {
            list($message, $context, $level) = \unserialize($data);
            echo date("d/m/Y H:i:s")."::{$level}::{$unique}::{$message}" . PHP_EOL;
        });
});

echo "Socket server listening on port 4000." .PHP_EOL;
echo "You can connect to it by running: telnet localhost 4000" . PHP_EOL;

$socket->listen(4000);
$loop->run();

Now we only need to start our servers:
our silex one

php -S 0.0.0.0:8080 -t www

and the tcp server

php app/server.php

One screencast showing the prototype in action:

You can see the full code in my github account.

Using the event dispatcher in a Silex application

Symfony has one component called The Event Dispatcher. This component is one implementation of Mediator pattern and it’s widely used in modern frameworks, such as Symfony. Silex, as a part of Symfony, also uses this component and we can easily use it in our projects. Let me show you one little example. Imagine one simple route in Silex to create one png file containing one text:

$app->get("/gd/{text}", function($text) {
    $path = "/tmp/qr.png." . uniqid();
    $im = imagecreate(90, 30);
    $background = imagecolorallocate($im, 255, 255, 255);
    $color = imagecolorallocate($im, 0, 0, 0);
    imagestring($im, 5, 5, 5,  $text, $color);
    imagepng($im, $path);
    imagedestroy($im);
    return $app->sendFile($path);
});

It works, but there’s one mistake. We need to unlink our temporally file $path, but where? We need do if after “return $app->sendFile($path);” but it’s not possible.

$app->get("/gd/{text}", function($text) {
    $path = "/tmp/qr.png." . uniqid();
    $im = imagecreate(90, 30);
    $background = imagecolorallocate($im, 255, 255, 255);
    $color = imagecolorallocate($im, 0, 0, 0);
    imagestring($im, 5, 5, 5,  $text, $color);
    imagepng($im, $path);
    imagedestroy($im);
    return $app->sendFile($path, 200, ['Content-Type' => 'image/png']);;
    unlink($path); // unreachable code
});

We can use BinaryFileResponse instead of the helper function “sendFile”, but there’s one smarter solution: The event dispatcher.

use Symfony\Component\HttpKernel\KernelEvents;

$app->get("/gd/{text}", function($text) use (app) {
    $im = imagecreate(90, 30);
    $path = "/tmp/qr.png." . uniqid();
    $background = imagecolorallocate($im, 255, 255, 255);
    $color = imagecolorallocate($im, 0, 0, 0);
    imagestring($im, 5, 5, 5,  $text, $color);
    imagepng($im, $path);
    imagedestroy($im);
    
    $app['dispatcher']->addListener(KernelEvents::TERMINATE, function() use ($path) {
        unlink($path);
    });

    return $app->sendFile($path, 200, ['Content-Type' => 'image/png']);
});

(Updated! thanks to Hakin’s recommendation)
Or even better using Silex’s Filters. In this case we after or finish. In fact those filters are nothing more than an elegant way to speak to the event dispatcher.


$app->get("/gd/{text}", function($text) use (app) {
    $im = imagecreate(90, 30);
    $path = "/tmp/qr.png." . uniqid();
    $background = imagecolorallocate($im, 255, 255, 255);
    $color = imagecolorallocate($im, 0, 0, 0);
    imagestring($im, 5, 5, 5,  $text, $color);
    imagepng($im, $path);
    imagedestroy($im);
    
    $app->after(function() use ($path) {
        unlink($path);
    });

    return $app->sendFile($path, 200, ['Content-Type' => 'image/png']);
});

We also can use the generic function to add events to the event listener:

use Symfony\Component\HttpKernel\KernelEvents;

$app->get("/gd/{text}", function($text) use (app) {
    $im = imagecreate(90, 30);
    $path = "/tmp/qr.png." . uniqid();
    $background = imagecolorallocate($im, 255, 255, 255);
    $color = imagecolorallocate($im, 0, 0, 0);
    imagestring($im, 5, 5, 5,  $text, $color);
    imagepng($im, $path);
    imagedestroy($im);
    
    $app->on(KernelEvents::TERMINATE, function() use ($path) {
        unlink($path);
    });

    return $app->sendFile($path, 200, ['Content-Type' => 'image/png']);
});

Now our temporally file will be deleted once a response is sent. Life is simpler with event dispatcher :)

Multiple Phonegap Push Notifications in the Android’s status bar

Last month I worked within an Android project using Phonegap, jQuery Mobile and Push Notifications. I also wrote one post explaining how to use PHP to send the server side’s part of the push notifications. Today I want to show one small hack, that I’ve done to change the default behaviour of push notifications. Let me explain it a little bit:

When you use the Push Plugin “out of the box” you will see one message in your Android’s status bar everytime we send one push notification (and you application isn’t running at this moment). If you click on the notification you application will start and you can handle this notification. But if you send more than one notifications to the device, only the last one will be shown on the status bar. This behaviour can be suitable for most situations, but within my application I wanted to see all the notifications in the status bar until I click on one (then all must disappear). If we want to do that we need to hack a little bit our Phonegap application. Let me show you what I’ve done.

Basically we need to change com.plugin.gcm.GCMIntentService file. If we open this Java file we can see that there’s one constant called: NOTIFICATION_ID and a public function called createNotification with something like that:

public static final int NOTIFICATION_ID = 237;
...

public void createNotification(Context context, Bundle extras)
{
    ...
    mNotificationManager.notify((String) appName, NOTIFICATION_ID, mBuilder.build());

}

I’m not a Java expert, but I notice that if I change this function to:

public static final int NOTIFICATION_ID = 237;
public static int MY_NOTIFICATION_ID = 237;
...

public void createNotification(Context context, Bundle extras)
{
    ...
    MY_NOTIFICATION_ID++;
    mNotificationManager.notify((String) appName, MY_NOTIFICATION_ID, mBuilder.build());

}

Now my android device will show multiple notifications, exactly as I need.

If we need to handle properly the way that our notifications are cancelled we also need to modify the public function cancelNotification

public static void cancelNotification(Context context)
{
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    //mNotificationManager.cancel((String)getAppName(context), MY_NOTIFICATION_ID);
    mNotificationManager.cancelAll();
    MY_NOTIFICATION_ID = NOTIFICATION_ID;
}

And that’s all. Multiple notifications as I needed.

Sending automated emails with PHP, Swiftmailer and Twig

I’m the one of hosts of a Coding Dojo in my city called Katayunos. Katayunos is the mix of the word Kata (coding kata) and “Desayuno” (breakfast in Spanish). A group of brave programmers meet together one Saturday morning and after having breakfast we pick one coding kata and we practise TDD and pair programming. It’s something difficult to explain to non-geek people (why the hell we wake up early one Saturday morning to do this) but if you are reading this post probably it sounds good:).

My work as host is basically pick the place and encourage people to join to the Coding Dojo. One way of doing this (besides twitter buzz) is take my address book and send one bulk email to all of them inviting to join us. I don’t like this kind of mails. They look like spam, so I prefer to send a personalized email. This email has a common part (the place location, the hour, the event description, …) and the personalized part. I can do it manually, the list isn’t so huge, but definitely that’s not cool. Because of that I have done a little script to perform this operation. I can do a simple PHP script but we are speaking about announcing a event about TDD, SOLID and things like that, so I must use the “right way”. Let’s start.

I manage my list of contacts within a spreadsheet. In this spreadsheet I have the name, the email and a one paragraph with the personalized part to each one of my contact. I can easily export this spreadsheet to a csv document like this:

Peter Parker, spiderman@gmail.com, "Lorem ipsum dolor sit amet, ..."
Clark Kent, superman@gmail.com, "consectetur adipisicing elit, ..."
Juan López Fernández, superlopez@gmail.com, "sed do eiusmod tempor incididunt .."

So first of all I need to parse this file.

class Parser
{
    private $data;

    public function createFromCsvFile($path)
    {
        $handle = fopen($path, "r");
        while (($data = fgetcsv($handle)) !== false) {
            $this->data[] = [
                'name'  => trim($data[0]),
                'email' => trim($data[1]),
                'body'  => isset($data[2]) ? trim($data[2]) : null,
            ];
        }
    }

    public function getData()
    {
        return $this->data;
    }
}

Easy. Now I want to send this parsed array by email. Because of that I will include Swiftmailer in my composer.json file.

My email will also be one template and one personalized part. We will use Twig to manage the template.

"require": {
        "swiftmailer/swiftmailer": "v5.0.2",
        "twig/twig": "v1.13.2",
}

Now we will create a class to wrap the needed code to send emails

class Mailer
{
    private $swiftMailer;
    private $swiftMessage;

    function __construct(Swift_Mailer $swiftMailer, Swift_Message $swiftMessage)
    {
        $this->swiftMailer  = $swiftMailer;
        $this->swiftMessage = $swiftMessage;
    }

    public function sendMessage($to, $body)
    {
        $this->swiftMessage->setTo($to);
        $this->swiftMessage->setBody(strip_tags($body));
        $this->swiftMessage->addPart($body, 'text/html');

        return $this->swiftMailer->send($this->swiftMessage);
    }
}

Our Mailer class sends mails. Our Parser class parses one csv file. Now we need something to join those two classes: the Spammer class. Spammer class will take one parsed array and it will send one by one the mails using Mailer class.

class Spammer
{
    private $twig;
    private $mailer;

    function __construct(Twig_Environment $twig, Mailer $mailer)
    {
        $this->twig       = $twig;
        $this->mailer     = $mailer;
    }

    public function sendEmails($data)
    {
        foreach ($data as $item) {
            $to = $item['email'];
            $this->mailer->sendMessage($to, $this->twig->render('mail.twig', $item));
        }
    }
}

Ok with this three classes I can easily send my emails. This script is a console script and we also want pretty console colours and this kind of stuff. symfony/console to the rescue. But I’ve a problem now. I want to write one message when one mail is sent and another one when something wrong happens. If I want to do that I need to change my Spammer class. But my Spammer class does’t know anything about my console Command. If I inject the console command into my Spammer class I will violate the Demeter law, and that’s a sin. What can we do? Easy: The mediator pattern. We can write one implementation of mediator pattern but we also can use symfony/event-dispatcher, a well done implementation of this pattern. We change our Spammer class to:

use Symfony\Component\EventDispatcher\EventDispatcher;

class Spammer
{
    private $twig;
    private $mailer;
    private $dispatcher;

    function __construct(Twig_Environment $twig, Mailer $mailer, EventDispatcher $dispatcher)
    {
        $this->twig       = $twig;
        $this->mailer     = $mailer;
        $this->dispatcher = $dispatcher;
    }

    public function sendEmails($data)
    {
        foreach ($data as $item) {
            $to = $item['email'];
            try {
                $this->mailer->sendMessage($to, $this->twig->render('mail.twig', $item));
                $this->dispatcher->dispatch(MailEvent::EVENT_MAIL_SENT, new MailEvent\Sent($to));
            } catch (\Exception $e) {
                $this->dispatcher->dispatch(MailEvent::EVENT_SENT_ERROR, new MailEvent\Error($to, $e));
            }
        }
    }
}

Now can easily build of console command class:

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;

class SpamCommand extends Command
{
    private $parser;
    private $dispatcher;

    protected function configure()
    {
        $this->setName('spam:run')
            ->setDescription('Send Emails');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln("Sending mails ...");
        $this->dispatcher->addListener(MailEvent::EVENT_MAIL_SENT, function (MailEvent\Sent $event) use ($output) {
                $output->writeln("<info>Mail sent to</info>: <fg=black;bg=cyan>{$event->getTo()}</fg=black;bg=cyan>");
            }
        );

        $this->dispatcher->addListener(MailEvent::EVENT_SENT_ERROR, function (MailEvent\Error $event) use ($output) {
                $output->writeln("<error>Error sending mail to</error>: <fg=black;bg=cyan>{$event->getTo()}</fg=black;bg=cyan> Error: " . $event->getException()->getMessage());
            }
        );

        $this->spammer->sendEmails($this->parser->getData());
        $output->writeln("End");
    }

    public function setSpammer(Spammer $spammer)
    {
        $this->spammer = $spammer;
    }

    public function setParser(Parser $parser)
    {
        $this->parser = $parser;
    }

    public function setDispatcher(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
}

With all this parts we can build our script. Our classes are decoupled. That’s good but setting up the dependencies properly can be hard. Because of that we will use symfony/dependency-injection. With symfony DIC we can set up our dependency tree within a yaml file:

Our main services.yml

imports:
  - resource: conf.yml
  - resource: mail.yml
  - resource: twig.yml

parameters:
  base.path: .

services:
  parser:
    class: Parser
    calls:
      - [createFromCsvFile, [%mail.list%]]

  mailer:
    class: Mailer
    arguments: [@swift.mailer, @swift.message]

  spam.command:
    class: SpamCommand
    calls:
      - [setParser, [@parser]]
      - [setDispatcher, [@dispatcher]]
      - [setSpammer, [@spammer]]

  spammer:
    class: Spammer
    arguments: [@twig, @mailer, @dispatcher]

  dispatcher:
    class: Symfony\Component\EventDispatcher\EventDispatcher

I like to separate the configuration files to reuse those files between projects and to make them more readable.

One for twig:

parameters:
  twig.path: %base.path%/templates
  twig.conf:
    auto_reload: true

services:
  twigLoader:
    class: Twig_Loader_Filesystem
    arguments: [%twig.path%]

  twig:
    class: Twig_Environment
    arguments: [@twigLoader, %twig.conf%]

another one for swiftmailer:

services:
  swift.message:
    class: Swift_Message
    calls:
      - [setSubject, [%mail.subject%]]
      - [setFrom, [%mail.from.mail%: %mail.from.name%]]

  swift.transport:
    class: Swift_SmtpTransport
    arguments: [%mail.smtp.host%, %mail.smtp.port%, %mail.smtp.encryption%]
    calls:
      - [setUsername, [%mail.smtp.username%]]
      - [setPassword, [%mail.smtp.password%]]

  swift.mailer:
    class: Swift_Mailer
    arguments: [@swift.transport]

and the last one for the configuration parameters:

parameters:
  mail.do.not.send.mails: false

  mail.list: %base.path%/mailList.csv
  mail.subject: mail subject
  mail.from.name: My Name
  mail.from.mail: my_email@mail.com

  mail.smtp.username: my_smtp_username
  mail.smtp.password: my_smtp_password
  mail.smtp.host: smtp.gmail.com
  mail.smtp.port: 465
  mail.smtp.encryption: ssl

Now we can build our script.

use Symfony\Component\Console\Application;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/conf'));
$loader->load('services.yml');

$container->setParameter('base.path', __DIR__);

$application = new Application();
$application->add($container->get('spam.command'));
$application->run();

n

And that’s all. My colleagues of the next Katayuno will be invited in a “SOLID” way :).
Source code is available in my github account.

BTW: Do you want to organize one Katayuno in your city? It’s very easy. Feel free to contact me for further information.

Releasing unmanaged resources (a PHP port from C#’s “using” statement)

Sometimes we work with instances that needs to released even when exceptions happens. Something typical when we work with resources (Files, Database connections, …) Let me show you with an example:

Imagine this class for handling file resources:

class File
{
    private $resource;
    private $logger;

    public function __construct($filename, Loger $logger)
    {
        $this->logger = $logger;
        $this->resource = fopen($filename);
    }

    public function write($string)
    {
        fwrite($this->resource, $string);
    }

    public function close()
    {
        $this->logger->log("file closed")   
        fclose($this->resource);
    }
}

We can use this class:

$file = new File(__DIR__ . "/file.txt", 'w');
$file->write("Hello\n");
// ...
// some other things
// ...
$file->write("Hello\n");
$file->close();

OK. What happens if one exception happens inside “some other things”? Simple answer: close() function isn’t called. This can be a problem. We can face this problem with a try/catch block like this:

try {
    $file->write("Hello\n");
    // ...
    // some other things
    // ...
    $file->write("Hello\n");
    $file->close();
} catch (\Exception $e) {
    $file->close();
}

Or even if we’re using PHP5.5 we can use “finally” keyword

try {
    $file->write("Hello\n");
    // ...
    // some other things
    // ...
    $file->write("Hello\n");
} catch (\Exception $e) {
} finally {
    $file->close();
}

Sometimes I need collaborate with C# projects. C# is a great language. I really like it. It has a really cool feature to solve this problem: the “using” statement. Because of that we are going to build today one small library to implement something similar in PHP.

First we will add G\IDisposable interface to our File class

namespace G;

interface IDisposable
{
    public function dispose();
}

Now our File class looks like this:

use G\IDisposable;

class File implements IDisposable
{
    private $resource;

    public function __construct($filename, $mode)
    {
        $this->resource = fopen($filename, $mode);
    }

    public function write($string)
    {
        fwrite($this->resource, $string);
    }

    public function close()
    {
        fclose($this->resource);
    }

    public function dispose()
    {
        $this->close();
    }
}

And we can use our “using” function in PHP:

using(new File(__DIR__ . "/file.txt", 'w'), function (File $file) {
        $file->write("Hello\n");
        $file->write("Hello\n");
        $file->write("Hello\n");
    });

As we can see we can forget to close() our file instance. “using” will do it for us, even if one exception is triggered inside. We need to take into account that “using” is not a way to handle exceptions. If you want to handle them you need to do it. The only responsibility of “using” is to ensure that dispose() is been called.

We also can use an array of instances (implementing the IDisposable interface of course)

using([new Bar, new Foo], function (Bar $bar, Foo $foo) {
        echo $bar->hello("Gonzalo");
        echo $foo->hello("Gonzalo");
    });

And that’s all. Library is available in github and also you can use it with composer.

Update!
I’ve changed the Example. The first example wasn’t a good one. Now File::close() closes the resource and also write a log. With the first example (without the logger) it wasn’t important to close the resorce (PHP closes it).

Creating QR codes with PHP and Silex

Today we’re going to play with QR codes and how to use them within a Silex application using one Service Provider. First we need a QR code generator. If we find in Packagist we can see various libraries. We are going to use the library: endroid/qrcode.

We are not going to modify endroid/qrcode, because of that we will create a wrapper. This wrapper will receive in the constructor one instance of endroid/qrcode. It’s responsability will be to take one QrCode object and generate a Symfony\Component\HttpFoundation\Response with our QR code and the properly headers. Here you can see the unit tests of our QrWrapper:

use Symfony\Component\HttpFoundation\Response;
use G\QrWrapper;

class QrWrapperTest extends PHPUnit_Framework_TestCase
{
    public function testObjectInit()
    {
        $qrCode = $this->getMockBuilder('Endroid\QrCode\QrCode')
                ->disableOriginalConstructor()
                ->getMock();

        $wrapper = new QrWrapper($qrCode);

        $this->assertInstanceOf('G\QrWrapper', $wrapper);
    }

    public function testGetResponseWithDefaultParameters()
    {
        $qrCode = $this->getMockBuilder('Endroid\QrCode\QrCode')
                ->disableOriginalConstructor()
                ->getMock();

        $qrCode->expects($this->any())->method('get')->will($this->returnValue("hello"));
        $wrapper = new QrWrapper($qrCode);

        $response = $wrapper->getResponse();

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
        $this->assertEquals("hello", $response->getContent());
        $this->assertEquals("image/png", $response->headers->get('Content-Type'));
    }

    public function testGetResponseForJpg()
    {
        $qrCode = $this->getMockBuilder('Endroid\QrCode\QrCode')
                ->disableOriginalConstructor()
                ->getMock();

        $qrCode->expects($this->any())->method('get')->will($this->returnValue("hello"));
        $wrapper = new QrWrapper($qrCode);
        $wrapper->setImageType('jpg');

        $response = $wrapper->getResponse();

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
        $this->assertEquals("hello", $response->getContent());
        $this->assertEquals("image/jpeg", $response->headers->get('Content-Type'));
    }

    public function testGetResponseForJpeg()
    {
        $qrCode = $this->getMockBuilder('Endroid\QrCode\QrCode')
                ->disableOriginalConstructor()
                ->getMock();

        $qrCode->expects($this->any())->method('get')->will($this->returnValue("hello"));
        $wrapper = new QrWrapper($qrCode);
        $wrapper->setImageType('jpeg');

        $response = $wrapper->getResponse();

        $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
        $this->assertEquals("hello", $response->getContent());
        $this->assertEquals("image/jpeg", $response->headers->get('Content-Type'));
    }

    public function testReusingResponse()
    {
        $qrCode = $this->getMockBuilder('Endroid\QrCode\QrCode')
                ->disableOriginalConstructor()
                ->getMock();

        $qrCode->expects($this->any())->method('get')->will($this->returnValue("hello"));
        $wrapper = new QrWrapper($qrCode);

        $response = new Response('foo');
        $response->headers->set('xxx', 'gonzalo');

        $response = $wrapper->getResponse($response);

        $this->assertEquals("hello", $response->getContent());
        $this->assertEquals("image/png", $response->headers->get('Content-Type'));
        $this->assertEquals("gonzalo", $response->headers->get('xxx'));
    }
}

Now we will create the ServiceProvider. We only need to implement ServiceProviderInterface

use Silex\Application;
use Silex\ServiceProviderInterface;
use Endroid\QrCode\QrCode;

class QrServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['qrCode'] = $app->protect(function ($text, $size = null) use ($app) {
            $default = $app['qr.defaults'];

            $qr = new QrWrapper(new QrCode());
            $qr->setText($text);
            $qr->setPadding($default['padding']);
            $qr->setSize(is_null($size) ? $default['size'] : $size);
            $qr->setImageType($default['imageType']);

            return $qr;
        });
    }

    public function boot(Application $app)
    {
    }
}

And that’s all. Now we can use our service provider within one Silex Application:

use Silex\Application;
use G\QrServiceProvider;

$app = new Application();

$app->register(new QrServiceProvider(), [
    'qr.defaults' => [
        'padding'   => 5, // default: 0
        'size'      => 200,
        'imageType' => 'png', // png, gif, jpeg, wbmp (default: png)
    ]
]);

$app->get("/qr/base64/{text}", function($text) use ($app) {
    return $app['qrCode'](base64_decode($text))->getResponse();
});

$app->get("/qr/{text}", function($text) use ($app) {
    return $app['qrCode']($text)->getResponse();
});

$app->run();

You can fetch the full code in github and also use it with composer

Building a BDD framework with PHP

Do you know Jasmine, the BDD framework for JavaScript? This holidays I was looking for something like that in PHP and I didn’t found anything similar (please let me know if I’m wrong) (now I know a few of them thanks to Dave’s comment) . Because of that, and as an exercise, I hack a little bit building something similar for PHP.

I want to write as less code as I can (it’s only a proof of concept), so I will reuse the assertion framework or PHPUnit. As I’ve seen when studying Behat, we can use the assertion part as standalone functions. We only need to include vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php file

Here you can see one example.

class StringCalculator
{
    public function add($string)
    {
        return (int)array_sum(explode(",", $string));
    }
}

$stringCalculator = new StringCalculator;

describe("add mull returns zero", function () use ($stringCalculator) {
        assertEquals(null, $stringCalculator->add(""));
    });

describe("1,1 should return 2", function () use ($stringCalculator) {
        assertEquals(2, $stringCalculator->add("1,1"));
    });

We also can use something similar than DataProvider in PHPUnit:

describe("add number returns number", function ($expected, $actual, $message) use ($stringCalculator) {
        assertEquals($expected, $stringCalculator->add($actual), $message);
    }, [
        ['expected' => 1, 'actual' => "1", 'message' => 'add 1'],
        ['expected' => 2, 'actual' => "2", 'message' => 'add 1'],
        ['expected' => 10, 'actual' => "10", 'message' => 'add 10'],
    ]);

And if we need mocks we can use Mockery, for example:

class Temperature
{

    public function __construct($service)
    {
        $this->_service = $service;
    }

    public function average()
    {
        $total = 0;
        for ($i=0;$i<3;$i++) {
            $total += $this->_service->readTemp();
        }
        return $total/3;
    }
}

$service = m::mock('service');

describe("testing mocks with mockery", function() use ($service) {
        $service->shouldReceive('readTemp')->andReturn(11, 12, 13);
        $temperature = new Temperature($service);
        assertEquals(12, $temperature->average(), "dummy message");
    });

I’ve created an small console application to run the test suites using symfony/console and symfony/finder components. We can run it with:

php ./bin/console.php texter:run ./tests

Beware because this library is a proof of concept. There’re a lot of remaining things. What do you think?

Source code at github

Sending Android Push Notifications from PHP to phonegap applications

Last days I’ve been working within a Phonegap project for Android devices using Push Notifications. The idea is simple. We need to use the Push Notification Plugin for Android. First we need to register the Google Cloud Messaging for Android service at Google’s console, and then we can send Push notifications to our Android device.

The Push Notification plugin provides a simple example to send notifications using Ruby. Normally my backend is built with PHP (and sometimes Python) so instead of using the ruby script we are going to build a simple PHP script to send Push Notifications.

The script is very simple

<?php
$apiKey = "myApiKey";
$regId = "device reg ID";

$pusher = new AndroidPusher\Pusher($apiKey);
$pusher->notify($regId, "Hola");

print_r($pusher->getOutputAsArray());

And the whole library you can see here:

<?php
namespace AndroidPusher;

class Pusher
{
    const GOOGLE_GCM_URL = 'https://android.googleapis.com/gcm/send';

    private $apiKey;
    private $proxy;
    private $output;

    public function __construct($apiKey, $proxy = null)
    {
        $this->apiKey = $apiKey;
        $this->proxy  = $proxy;
    }

    /**
     * @param string|array $regIds
     * @param string $data
     * @throws \Exception
     */
    public function notify($regIds, $data)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, self::GOOGLE_GCM_URL);
        if (!is_null($this->proxy)) {
            curl_setopt($ch, CURLOPT_PROXY, $this->proxy);
        }
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getHeaders());
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->getPostFields($regIds, $data));

        $result = curl_exec($ch);
        if ($result === false) {
            throw new \Exception(curl_error($ch));
        }

        curl_close($ch);

        $this->output = $result;
    }

    /**
     * @return array
     */
    public function getOutputAsArray()
    {
        return json_decode($this->output, true);
    }

    /**
     * @return object
     */
    public function getOutputAsObject()
    {
        return json_decode($this->output);
    }

    private function getHeaders()
    {
        return [
            'Authorization: key=' . $this->apiKey,
            'Content-Type: application/json'
        ];
    }

    private function getPostFields($regIds, $data)
    {
        $fields = [
            'registration_ids' => is_string($regIds) ? [$regIds] : $regIds,
            'data'             => is_string($data) ? ['message' => $data] : $data,
        ];

        return json_encode($fields, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
    }
}

Maybe we could improve the library with a parser of google’s ouptuput, basically because we need to handle this output to notice if the user has uninstalled the app (and we need the remove his reg-id from our database), but at least now it cover all my needs. You can see the code at github

Follow

Get every new post delivered to your Inbox.

Join 952 other followers