Note: I'm migrating from gonzalo123.com to here. When I finish I'll swap the DNS to here. The "official" blog will be always gonzalo123.com

      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

      comments powered by Disqus