7 posts on PHP

In defense of reinventing wheels

3 min read 0 comments Report broken page

One of the first things a software engineer learns is “don’t reinvent the wheel”. If something is already made, use that instead of writing your own. “Stand on the shoulders of giants, they know what they’re doing better than you”. Writing your own tools and libraries, even when one already exists, is labelled “NIH syndrome”  and is considered quite bad. “But what if my version is better?”. Surely, reinventing the wheel can’t be bad when your new wheel improves existing wheel designs, right? Well, not if the software is open source, which is usually the case in our industry. “Just contribute to it” you’ll be told. However, contributing to an open source project is basically teamwork. The success of any team depends on how well its members work together, which is not a given. Sometimes, your vision about the tool might be vastly different from that of the core members and it might be wiser to create your own prototype than to try and change the minds of all these people.

However, Open Source politics is not what I wanted to discuss today. It’s not the biggest potential benefit of reinventing the wheel. Minimizing overhead is. You hardly ever need 100% of a project. Given enough time to study its inner workings, you could always delete quite a large chunk of it and it would still fit your needs perfectly. However, the effort needed to do that or to rewrite the percentage you actually need is big enough that you are willing to add redundant code to your codebase.

Redundant code is bad. It still needs to get parsed and usually at least parts of it still need to be executed. Redundant code hinders performance. The more code, the slower your app. Especially when we are dealing with backend code, when every line might end up being executed hundreds or even thousands of times per second. The slower your app becomes, the bigger the need to seriously address performance. The result of that is even more code (e.g. caching stuff) that could have been saved in the first place, by just running what you need. This is the reason software like Joomla, Drupal or vBulletin is so extremely bloated and brings servers to their knees if a site becomes mildly successful. It’s the cost of code that tries to match everyone’s needs.

Performance is not the only drawback involved in redundant code. A big one is maintainability. This code won’t only need to be parsed by the machine, it will also be parsed by humans, that don’t know what’s actually needed and what isn’t until they understand what every part does. Therefore, even the simplest of changes become hard.

I’m not saying that using existing software or libraries is bad. I’m saying that it’s always a tradeoff between minimizing effort on one side and minimizing redundant code on the other side. I’m saying that you should consider writing your own code when the percentage of features you need from existing libraries is tiny (lets say less than  20%). It might not be worth carrying the extra 80% forever.

For example, in a project I’m currently working on, I needed to make a simple localization system so that the site can be multilingual. I chose to use JSON files to contain the phrases. I didn’t want the phrases to include HTML, since I didn’t want to have to escape certain symbols. However, they had to include simple formatting like bold and links, otherwise the number of phrases would have to be huge. The obvious solution is Markdown.

My first thought was to use an existing library, which for PHP is PHP Markdown. By digging a bit deeper I found that it’s actually considered pretty good and it seems to be well maintained (last update in January 2012) and mature (exists for over 2 years). I should happily use it then, right?

That’s what I was planning to do. And then it struck me: I’m the only person writing these phrases. Even if more people write translations in the future, they will still go through me. So far, the only need for such formatting is links and bold. Everything else (e.g. lists) is handled by the HTML templates. That’s literally two lines of PHP! So, I wrote my own function. It’s a bit bigger, since I also added emphasis, just in case:

function markdown($text) {
 // Links
 $text = preg\_replace('@\\\\\[(.+?)\\\\\]\\\\((#.+?)\\\\)@', '<a href="$2">$1</a>', $text);

// Bold $text = preg_replace(‘@(?<!\\\\)\\*(?<!\\\\)\\*(.+?)(?<!\\\\)\\*(?<!\\\\)\\*@’, ‘<strong>$1</strong>’, $text);

// Emphasis $text = preg_replace(‘@(?<!\\\\)\\*(.+?)(?<!\\\\)\\*@’, ‘<em>$1</em>’, $text);

return $text; }

Since PHP regular expressions also support negative lookbehind, I can even avoid escaped characters, in the same line. Unfortunately, since PHP lacks regular expression literals, backslashes have to be doubled (\\ instead of \ so \\\\ instead of \\, which is pretty horrible).

For comparison, PHP Markdown is about 1.7K lines of code. It’s great, if you need the full power of Markdown (e.g. for a comment system) and I’m glad Michel Fortin wrote it. However, for super simple, controlled use cases, is it really worth the extra code? I say no.

Rachel Andrew recently wrote about something tangentially similar, in her blog post titled “Stop solving problems you don’t yet have”. It’s a great read and I’d advise you to read that too.


Convert PHP serialized data to Unicode

1 min read 0 comments Report broken page

I recently had to convert a database of a large Greek website from single-byte Greek to Unicode (UTF-8). One of the problems I faced was the stored PHP serialized data: As PHP stores the length of the data (in bytes) inside the serialized string, the stored serialized strings could not be unserialized after the conversion.

I didn’t want anyone to go through the frustration I went through while searching for a solution, so here is a little function I wrote to recount the string lengths, since I couldn’t find anything on this:

function recount_serialized_bytes($text) {
	mb_internal_encoding("UTF-8");
	mb_regex_encoding("UTF-8");

mb_ereg_search_init($text, ‘s:[0-9]+:"’);

$offset = 0;

while(preg_match(‘/s:([0-9]+):"/u’, $text, $matches, PREG_OFFSET_CAPTURE, $offset) || preg_match(‘/s:([0-9]+):"/u’, $text, matches,PREGOFFSETCAPTURE,++offset)) { $number = $matches[1][0]; $pos = $matches[1][1];

digits = strlen(&quot;number"); poschars=mbstrlen(substr(text, 0, $pos)) + 2 + $digits;

str=mbsubstr(text, $pos_chars, $number);

newnumber=strlen(str); newdigits=strlen(new_number);

if($number != $new_number) { // Change stored number text=substrreplace(text, $new_number, $pos, $digits); $pos += $new_digits - $digits; }

$offset = $pos + 2 + $new_number; }

return $text; }

My initial approach was to do it with regular expressions, but the PHP serialized data format is not a regular language and cannot be properly parsed with regular expressions. All approaches fail on edge cases, and I had lots of edge cases in my data (I even had nested serialized strings!).

Note that this will only work when converting from single-byte encoded data, since it assumes the stored lengths are the string lengths in characters. Admittedly, it’s not my best code, it could be optimized in many ways. It was something I had to write quickly and was only going to be used by me in a one-time conversion process. However, it works smoothly and has been tested with lots of different serialized data. I know that not many people will find it useful, but it’s going to be a lifesaver for the few ones that need it.


rgba.php v1.2: Improved URL syntax, now at Github

1 min read 0 comments Report broken page

I wrote the first version of rgba.php as a complement to an article on RGBA that I posted on Februrary 2009. Many people seemed to like the idea and started using it. With their valuable input, I made many changes and released v.1.1 (1.1.1 shortly after I posted the article due to another little fix) on October 2009. More than a year after, quite a lot of people still ask me about it and use it, so I decided to make a github repo for it and release a new version, with a much easier to use syntax for the URL, which lets you just copy and paste the color instead of rewriting it:

background: url(‘rgba.php/rgba(255, 255, 255, 0.3)’); background: rgba(255, 255, 255, 0.3);

instead of:

background: url(‘rgba.php?r=255&g=255&b=255&a=30’); background: rgba(255, 255, 255, 0.3);

I also made a quick about/demo page for it. Enjoy :)


Quickly find the Gravatar that cor­res­ponds to a given email

1 min read 0 comments Report broken page

Today I needed to quickly find the Gravatars that corresponded to a bunch of email addresses for some reason (don’t ask). After a bit of googling and wandering around in Gravatar’s official site and others, I firgured out it’s probably much quicker to write a short PHP script for that myself, than keep looking.

Here it is, in case someone ever needs to do something similar: (click on the screenshot)

Quickly find the Gravatar that cor­res­ponds to a given email

(has anyone noticed my latest love affair with Helvetica/Arial? :P )


New version of rgba.php is out!

2 min read 0 comments Report broken page

It’s been a while since I posted my little server-side solution for cross-browser RGBA colors (in a nutshell: native rgba for the cool browsers that support it, a PHP-generated image for those that don’t). For features, advantages, disadvantages etc, go see the original post. In this one I’ll only discuss the new version.

So, since it’s release I’ve received suggestions from many people regarding this script. Some other ideas were gathered during troubleshooting issues that some others faced while trying to use it. I hope I didn’t forget anything/anyone :)

Changelog (+credits):

  1. You may now specify the size of the generated image (thanks Sander Arts!)
  2. If the PHP version is below 5.1.7 the call to imagepng() uses 2 parameters instead of 4, to workaround the bug found by Bridget (thanks Chris Neale for suggesting the use of phpversion()!)
  3. Added error_reporting() to only allow for fatal errors and parse errors to go through (I should had done this anyway but I completely forgot). This solves an issue that Erin Doak pointed out, since they had set up notices to be displayed and even a reference to an undefined index made the whole script collapse.
  4. Mariotti Raffaele pointed out that apache_request_headers() was not defined in all PHP installations. After looking into it a bit, I found out that it’s available only when PHP is installed as an Apache module. After some more research it turned out that the only way to get the If-Modified-Since header otherwise is an .htaccess, so I  ruled that out (It would complicate the workaround I think and I doubt all hosts allow .htaccess (?). On the other hand, an .htacess would also allow for some URL rewriting goodness… Hmmm… Should I consider this?). So, if the function is not available, it serves the file with an 200 response code every time, instead of just sending a 304 response when the If-Modified-Since header is present.
  5. Igor Zevaka for pointing out that the Expires header wasn’t a valid HTTP date.

rgba.php

Demo

Enjoy :) and please report any bugs!


CSS3 colors, today (MediaCampAthens session)

1 min read 0 comments Report broken page

Yesterday, I had a session at MediaCampAthens (a BarCamp-style event), regarding CSS3 colors. If you’ve followed my earlier posts tagged with “colors”, my presentation was mostly a sum-up of these.

It was my first presentation ever, actually, the first time I talked to an audience for more than 1 minute :P . This caused some goofs:

  • When introducing myself, I said completely different things than I intended to and ended up sounding like an arrogant moron :P
  • I tried not to look at the audience too much, in order to avoid sounding nervous, and this caused me to completely ignore 2 questions (as I found out afterwards)! How embarrasing!
  • At a certain point, I said “URL” instead of “domain” :P

Also, I had prepared some screenshots (you’ll see them in the ppt) and the projector completely screwed them up, as it showed any dark color as black.

Apart from those, I think it went very well, I received lots of positive feedback about it and the audience was paying attention, so I guess they found it interesting (something that I didn’t expect :P ).

Here is the presentation:

Please note that Slideshare messed up slide #8 and the background seems semi-transparent grey instead of semi-transparent white.

By the way, I also thought afterwards that I had made a mistake: -ms-filter is not required if we combine the gradient filter with Data URIs, since IE8 supports Data URIs (for images at least). Oops, I hate making mistakes that I can’t correct.

Here are some photos from my session. If I did it correctly, every facebook user can see them. If I messed things up, tell me :P

News, Personal, CMYK, Colors, CSS, CSS Values, Feature Detection, Hsla, JS, PHP, RGBA, Speaking
Edit post on GitHub

Bulletproof, cross-browser RGBA backgrounds, today

4 min read 0 comments Report broken page

UPDATE: New version

First of all, happy Valentine’s day for yersterday. :) This is the second part of my “Using CSS3 today” series. This article discusses current RGBA browser support and ways to use RGBA backgrounds in non-supporting browsers. Bonus gift: A PHP script of mine that creates fallback 1-pixel images on the fly that allow you to easily utilize RGBA backgrounds in any browser that can support png transparency. In addition, the images created are forced to be cached by the client and they are saved on the server’s hard drive for higher performance.

Browsers that currently support RGBA

These are:

  • Firefox 3+
  • Safari 2+
  • Opera 10 (still in beta)
  • Google Chrome

In these browsers you can write CSS declarations like:

background: rgba(255,200,35,0.5) url(somebackground.png) repeat-x 0 50%; border: 1px solid rgba(0,0,0,0.3); color: rgba(255,255,255,0.8);

And they will work flawlessly.

Internet Explorer

Surprisingly, it seems that Internet Explorer supported RGBA backgrounds long before the others. Of course, with it’s very own properietary syntax, as usual:

filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#550000FF, endColorstr=#550000FF);

And since nothing is ever simple with IE, IE8 requires a special syntax which has to be put before the first one to work properly in IE8 beta1:

-ms-filter: “progid:DXImageTransform.Microsoft.gradient(startColorstr=#550000FF, endColorstr=#550000FF)”;

The code above actually draws a gradient from rgba(0,0,255,0.33) to rgba(0,0,255,0.33) using a Microsoft-proprietary “extended” hex format that places the Alpha parameter first (instead of last) and in the range of 00-FF (instead of 0-1). The rest is a usual hex color, in that case #0000FF.

Caution: The “gradients” that are created via the gradient filter are placed on top of any backgrounds currently in effect. So, if you want to have a background image as well, the result may not be what you expected. If you provide a solid color as a background, it will also not work as expected (no alpha transparency), since the gradients created are not exactly backgrounds, they are just layers on top of backgrounds.

Problems with the filter method

  • Filters are bad for client-side performance.
  • Filters cause the text rendering to be aliased and especially when it’s bold and there is no background-color set it becomes completely unreadable. (the worst disadvantage if you ask me)
  • Filters only work with IE. What about Firefox 2- and Opera 9.6-?
  • Filters are lengthy (especially now that you have to include 2 different syntaxes) so they significantly increase the size of your CSS when used frequently.
  • You have to convert the red, green and blue values to hex to use that method.
  • To use a filter, the element has to have Layout. This is usually done via zoom:1. More non-standard clutter in your CSS.
  • Doesn’t play along well with other workarounds, since it doesn’t modify the background of the element.

So, personally, I only use that approach sparingly, in particular, only when “no/minimum external files” is a big requirement.

A bulletproof solution

My favored approach is to use rgba() for all RGBA-capable browsers and fallback pngs for the ones that don’t support RGBA. However, creating the pngs in Photoshop, or a similar program and then uploading them is too much of a fuss for me to bare (I get bored easily :P ). So, I created a small PHP script that:

  • Creates a 1-pixel png image with the parameters passed for red, green, blue and alpha. No need to convert to hex.
  • Supports named colors, to speed up typing even more for colors that you use commonly in a site (it includes white and black by default, but you may easily add as many as you like).
  • Stores the generated images on the server, so that they don’t have to be created every time (generating images on the fly has quite an important performance impact).
  • Forces the images to be cached on the browser so that they don’t have to be generated every time (even though their size is very small, about 73 bytes).

Here it is: rgba.php

You use it like this:

background: url(rgba.php?r=255&g=100&b=0&a=50) repeat; background: rgba(255,100,0,0.5);

or, for named colors:

background: url(rgba.php?name=white&a=50) repeat; background: rgba(255,255,255,0.5);

Browsers that are RGBA-aware will follow the second background declaration and will not even try to fetch the png. Browsers that are RGBA-incapable will ignore the second declaration, since they don’t understand it, and stick with the first one. Don’t change the order of the declarations: The png one goes first, the rgba() one goes second. If you put the png one second, it will always be applied, even if the browser does support rgba.

Before you use it, open it with an editor to specify the directory you want it to use to store the created pngs (the default is 'colors/') and add any color names you want to be able to easily address (the defaults are white and black). If the directory you specify does not exist or isn’t writeable you’ll get an error.

Caution: You have to enter the alpha value in a scale of 0 to 100, and not from 0 to 1 as in the CSS. This is because you have to urlencode dots to transfer them via a URI and it would complicate things for anyone who used this.

Edit: It seems that IE8 sometimes doesn’t cache the image produced. I should investigate this further.

IMPORTANT: If your PHP version is below 5.1.2 perform this change in the PHP file or it won’t work.

Why not data:// URIs?

Of course, you could combine the IE gradient filter, rgba() and data:// URIs for a cross-browser solution that does not depend on external files. However, this approach has some disadvantages:

  • All the disadvantages of filters mentioned above.
  • You can’t be spontaneous in your CSS and changes are difficult. Every time you want to use RGBA, you have to resort to some converter to create the png and it’s data:// URI. Unless you are some kind of a cyborg with an embedded base64 encoder/decoder in your head :P
  • Larger filesize (you have to use 4-5 declarations (the rgba() one, the data:// one, 2 filters, one for IE7- and one for IE8 and a zoom:1; to give the element “layout” so that filters can be applied) instead of 2, and the data:// URI has the same size as the png). Also, the data:// URI can not be cached so every time you use it, you increase the filesize even more.  Ok, you save an http request per use, but is it worth it?

and some advantages:

  • You will not see the site without a background for even a single millisecond. Since the png is embedded in the CSS, it’s loaded as soon as the CSS itself is loaded. If your site background is too dark and you rely on the RGBA background to make the content legible, you might want to consider this solution.
  • No external files, no extra http requests.
  • The filter method works in IE6- without the script for transparent PNGs.

Choose the method that fits your needs better. :)

RGBA is not only for backgrounds!

It’s also for every CSS property that accepts color values. However, backgrounds in most cases are the easiest to workaround. As for borders, if you want solid ones, you can simulate them sometimes by wrapping a padded container with an RGBA background around your actual one and giving it as much padding as your desired border-width. For text color, sometimes you can fake that with opacity. However, these “solutions” are definitely incomplete, so you’d probably have to wait for full RGBA support and provide solid color fallbacks for those (unless someone comes up with an ingenious solution in <canvas>, it’s common these days :P ).