Human Readable bytes (Twig Filter Extension)

0

Recently we needed a Twig Filter that takes bytes (as an integer) and translates that to the nearest human readable version of it. For example… if you have 100 bytes, that’s easy, it’s written as in “100 B”. But, what if you have more than 1024 bytes? Then, for example of having 2000 bytes, it is “1.953125 KB” (i.e. the first 1024 bytes is a kilobyte and the remaining 976 bytes is 0.953125 kilobytes).

You can read more here: http://en.wikipedia.org/wiki/Byte

What we actually want to do here is “filter” the bytes and translate that to a human readable, close to the biggest denominator, string that makes it easy for us to see the size of data. For instance, it’s very very difficult to see at a glance how big 1234567890 Bytes are, but if you break it down to the closest 1024 multiple, you note that 1234567890 Bytes = 1.15 GB (rounded).

The easy way for us to solve this was to use a Twig Filter Extension. Our extension is used as below:

… this will take 123456789012345 and divide it by 1024 until it can go no further, and will then eventually print out 112.283 TB

How do we do this? We take advantage of some math and PHP:

The above code is common use for doing this calculation so I won’t go into this too much. You can read more on this at http://php.net/manual/en/function.log.php in the comments section.

Putting it into a Twig Extension is pretty easy, there’s mainly 3 steps:

  1. Create the Twig Extension (anywhere, really, we put it in our “util” bundle in Symfony2)
  2. Register the extension as a  service
  3. Use it 🙂 – anywhere in your project

To create a Twig Extension in Symfony2 read: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

We went one step further though, in order to make the extension a little more flexible. We used a wildcard. In the section where you register your twig filters you may use wildcards, here’s our getFilters method code:

The wildcard at the end of ‘bytesTo*’ means we can put just about anything we want there. This means we can have a filter saying, even though this might not resolve to the closest GB, we’d like to force it to resolve to GB and end up with something like 0.005 GB or 4000.123 GB even.

Full source of our Extension Class to see it all work together (with some sanity checks) can be seen below:

This gives us the following ways of using it:

… yielding the following results:

Hope this is helpful and somebody can use this! n-Joy!

Transposing Rows into Columns with MySQL

0

This is very basic, but figured there might be people out there that would find this useful. Say you have a table with signups to your site, and you want to chart these signups. However there are three different signups: guest, paid, pro. Let’s say, for argument sake you have a table with 2 columns, date and signup type, like below:

If you had to run the following group by query you’d get the results row by row:

… resulting in the following output:

Let’s say, however, you want to have each date in one row, yet you want to have a column for guest, another column for paid and yet another for pro with the resulting counts in them? Well that’s easy, here’s what you do in SQL:

… and then you have output like this:

What’s awesome about doing it this way, is that you could copy this into Excel or whatever the tool is you use and line chart these figures against each other for a nice visual representation of your signups (or whatever you use this for) 🙂

Let me know what you think!

Symfony2

Migrating from Symfony 1.4 to Symfony 2 iteratively via Apache Rewrites

2

A problem that we have currently is that our entire system is written on Symfony 1.4 (well, it’s still the bridging 1.3 actually, but who’s counting). Migrating a system that’s been in development for 4+ years with thousands of lines of code and a lot of not-so-MVC-code is a nightmare, and in fact in the modern fast-to-market environment it is impossible to spend a year, or even 6 months, re-developing a system like this only to launch it and find it’s not only outdated once again but you missed a years worth of opportunities.

The solution? Run two systems next to each other! Easier said than done though, because when we look at the software, it is our customer zone and runs off a subdomain. So how do you run zone.domain.com and use both Symfony 1.4 (old code) and write new code in Symfony 2?

The solution? Fool the world a little bit! Put something into your Symfony 2 URL’s that uniquely identify them. Let’s fool the world into thinking we are going to be moving to internationalization. Let’s say all Symfony 2 URL’s will have a …./en/… between the domain name, and the route. So, URL’s will look like this in future:

  • zone.domain.com – goes to front page of Symfony 1.4 system
  • zone.domain.com/products/list – goes to page listing the clients products Symfony 1.4 style
  • zone.domain.com/en/products/list – goes to new-school and new-style Symfony 2 listing of the products (the cool thing about this is, that we can test the new products listing page extensively – even live! In fact, we can even start a beta program where certain clients/customers (say 5%) are given the opportunity to see new things before it’s launched)

Now, how do we do this? Options, anybody?

  1. Option 1: PHP Hacking
  2. Option 2: Apache Virtual Host Hacking
  3. Option 3: .htaccess hacking – this is the option we went with

In short, PHP Hacking involves us taking our app.php controller file on Symfony 1.4 (which everything is linked to) and checking for the /en/ at the start of the route, if we find it we go and include the Symfony 2 app.php file instead. This gets messy, because you now have to change current-working-directories, you have to keep track of things to avoid infinite looping, etc. It generally sucked when we tried it.

Option 2 and 3 is basically the same from what we did, but hacking away at the vhost means each change you’ll have to restart apache – not a great idea if you have to make a change on a live system with thousands of users logged in and trying to do something at that time.

Let’s then look at what we did with Option 3: .htaccess hacking:

First, let’s explain the old and new directory structures:

  • /home/public_html
    • symfony1.4projectname
      • apps/
      • cache/
      • config/
        • databases.yml – config file holding database names, server addresses, usernames and passwords!
      • lib/
      • log/
      • web/
        • app.php
        • images/
        • js/
        • css/
    • symfony2projectname
      • app/
        • config/
      • bin/
      • src/
      • web/
        • app.php

The old system, had a virtual host set up for zone.domain.com to point to /home/public_html/symfony1.4projectname/web/app.php. Thus, if you go to say zone.domain.com/products/list it would translate into loading the php file at /home/public_html/symfony1.4projectname/web/app.php and appending to it the URI of /products/list. We want to keep the system the same and have it still use that controller file for the old-school system.

With the new system, we’d like the exact same to happen, but instead of pointing it to ..symfony1.4projectname/web/app.php we want to point it to ..symfony2projectname/web/app.php (note the 2 instead of 1.4).

Easy (and wrong) way of doing this, is to have the vhost point not to /home/public_html/symfony1.4projectname/web/ but to /home/public_html/ and then have the .htaccess file make the call of where it’s going. This, however, opens up your entire folder structure to the world (if you’re not very very careful) which kind of voids one of the big reasons for using frameworks like Symfony with a single controller file for your application inside a single non-connected web folder.

Better: Create a “switching” folder, and point vhost there!

We created the following new folder structure (new is in green):

  • /home/public_html
    • symfony1.4projectname/
    • symfony2projectname/
    • switch/
      • s1.4/
        • Symbolic link to: ../../symfony1.4projectname/web
      • s2/
        • Symbolic link to: ../../symfony2projectname/web
    • .htaccess
Now, with our vhost pointing to /home/public_html/switch/ we can safely say that we are still secure, however nothing is working 🙂 This is where the .htaccess file comes in:
The .htaccess file now has to figure out where to send us, first let’s make it work as it did in the past, here’s the file then:

Let’s look at this, all we’re basically saying is, whatever URI we call, send it to the destination of the symbolic link of 1.4 and load the app.php file with whatever parameters was given afterward.

Now that that’s working, let’s put in the /en/ rules:

The .htaccess file now changes to this (green is new code):

Here you can see, that the rule states that “if the URI begins with /en, then send it to the symbolic destination folder sitting at s2/web and load the app.php controller file, appending whatever parameters was given at the end”.

That worked great, except none of the images, css and js was loading. The great thing about Symfony 2 is that it has a /bundles folder inside web which holds all the assets. This is nice and identifiable of symfony 2 (granted that you don’t have that foldername in Symfony 1.4 though). Therefore, we just have to add another rule in for that. Here’s the new .htaccess file (again, green is new code):

And that, as they say, is that! Now all css, images, js etc is loading fine in Symfony 2 as well as the old-school Symfony 1.4 project is still working, and the best thing: Your PHP code doesn’t even know it’s been fooled! 🙂 Neither does the public users of your system, by the way.

The only drawback of this is, that all your routes in Symfony 2 now has to be prefixed by /en/. The solution to this, though, sits in the word “prefix” – the great thing about symfony2 is that it has that ability! Open your routing file (that should be in app/config/routing.yml) and merely change the line that says:

… to be:

Done! 🙂 Enjoy and please comment if you have some insight to give on this matter!

Go to Top