Tag Archives: United States

5 PHP String Functions You Need to Know

Strings in PHP

The Task

First of all what we’d like to achieve? The task is to convert a string, most of the cases single word, by capitalize the first letter. In my case I’ve the world countries names all lower cased, while I need them with first letter capitalized. In example “united states” must become “United States”, but not “United states” or “UNITED STATES”. So here began the journey into PHP string functions, especially those for capitalization!

1. ucwords

The first thing you find in the PHP Manual is the ucwords function. It changes the first letter to a capital letter, but it does not do the job. Why? Well let me show you an example.

$str1 = 'foo bar';
$str2 = 'Foo bar';
$str3 = 'FOO BAR';
$str4 = 'фуу бар';
 
echo ucwords($str1); // Foo Bar
echo ucwords($str2); // Foo Bar
echo ucwords($str3); // FOO BAR
echo ucwords($str4); // фуу бар

Here we have four strings. A lower cased, an upper cased, a mixed cased and … a lower cased Cyrillic string. First of all the main reason why ucwords doesn’t fit here is because of the Cyrillic string. Whatever non-Latin string you have you can forget about capitalization. However the other strings conversions are also interesting. Take a look at the third string! Here the string remains “FOO BAR” instead of going “Foo Bar”, which simply means that this function only looks, and hopefully changes, the first letter.

So here we have two questions. How can we overcome the Cyrillic problem and how to “normalize” the UPPER CASE string?

2. ucfirst

This is another useful function in PHP. ucfirst as you may guess from its name converts a string by only changing its first letter. So “Foo bar” will remain “Foo bar”, while with ucwords it has become “Foo Bar”. Let’s see what this function does:

$str1 = 'foo bar';
$str2 = 'Foo bar';
$str3 = 'FOO BAR';
$str4 = 'фуу бар';
 
echo ucfirst($str1); // Foo bar
echo ucfirst($str2); // Foo bar
echo ucfirst($str3); // FOO BAR
echo ucfirst($str4); // фуу бар

Here even the first string has only one capital letter – “foo bar” became “Foo bar”, and yet again we’ve the Cyrillic string unchanged. It simply doesn’t help us here!

3. mb_convert_case

As a PHP developer you know what the “mb_” prefix means – multibyte. This is quite useful. You can convert the string whatever the encoding is, so perhaps we can overcome the Cyrillic problem. But before proceeding to tests, let’s take a look at the parameters of this function.

The first thing to note here is that mb_convert_case doesn’t contain the case in its name – upper or lower. There’s a second parameter, after the first which is the string itself, who setups that. Note that here you don’t have the typical camel case or capitals parameter name, but MB_CASE_TITLE (as you know in English the title is always capitalized):

echo mb_convert_case($str, MB_CASE_TITLE, ...

And a third one which specifies the encoding:

echo mb_convert_case($str, MB_CASE_TITLE, 'utf-8')

Now let’s see what we can achieve with it:

$str1 = 'foo bar';
$str2 = 'Foo bar';
$str3 = 'FOO BAR';
$str4 = 'фуу бар';
 
echo mb_convert_case($str1, MB_CASE_TITLE, 'utf-8'); // Foo Bar
echo mb_convert_case($str2, MB_CASE_TITLE, 'utf-8'); // Foo Bar
echo mb_convert_case($str3, MB_CASE_TITLE, 'utf-8'); // Foo Bar
echo mb_convert_case($str4, MB_CASE_TITLE, 'utf-8'); // Фуу Бар

As you can see now the Cyrillic problem doesn’t exists and mb_convert_case is intelligent enough to change “FOO BAR” into “Foo Bar” – as I said this is the English style titling. That is by no means the solution when you deal with capitalization with different encoding.

However there is another approach to overcome the all UPPER CASE conversion problem. A possible solution is to convert the string first to a lower case string.

4. strtolower

strtolower is very useful PHP string function and perhaps any PHP developer has used it at least once. But yet again – it does not do the job. Again because of the encoding problem.

echo strtolower('ФУУ БАР'); // #*&$(#*%#

As you can see the Cyrillic string cannot be lower cased! Let’s search again into the “mb_” universe.

5. mb_strtolower

This is the function. Again you’ve to specify the encoding:

echo mb_strtolower('ФУУ БАР', 'utf-8')

Conclusion

It doesn’t matter whether you’re native English speaker or not. Most of the web sites are multilingual and you cannot be sure what happens when you convert strings in Alphabets different from the Latin. Thus be careful even when everything seems to be OK with Latin string tests.

PHP: detecting mobile device

HTTP_USER_AGENT

Beside that most of the responses of $_SERVER[‘HTTP_USER_AGENT’] may return, it appears that this is the most reliable way to track down a user agent with PHP. It is weird that most of the clients, i.e. Safari and Chrome will return something with Mozilla in it’s strings, but however it’s enough to track the “chrome” or “safari” sub strings.

All the examples bellow are from Mac OS X:

Firefox 3.6:

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6

Note: there are both Mozilla and Firefox sub strings!

Safari 4:

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; bg-bg) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10

Chrome:

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.307.11 Safari/532.9

Note: Here they are Mozilla, Chorme and Safari!!!

Opera:

Opera/9.80 (Macintosh; Intel Mac OS X; U; en) Presto/2.2.15 Version/10.10

The day of mobile

Nowadays it’s normal to make a site with the presumption it will be visible from mobile. The war between Nexus One from Google and iPhone from Apple is just beginning and with all those devices with wide screens everything’s becoming more complicated.

User agent strings from Nexus One and iPhone

Both are weird, but both contain the keyword – “mobile” and that may help you make a check with something like this PHP snippet:

<?php
$mobile = !!(FALSE !== strstr(strtolower($_SERVER['HTTP_USER_AGENT']), 'mobile'));
?>

Zend_Date – make it work and benefit with locales

Although the documentation of Zend Framework is one of the most well structured documentation I’ve ever read it happened to me to stuck into it. And that happened exactly when I tried to use the date component of ZF – Zend_Date.

Why I’d prefer Zend_Date?

We all know what the date function of PHP is, and what it does. It has reach set of formating string that help you do the job but as I’m working mostly on multilingual projects almost every project needs multilingual dates, and more or less nobody wants only numbers into the dates. And all this is pretty natural, instead of using the simple

01.01.2010

format, which beside it’s natural ugliness is not clear. Because as you may know in the US this can be understood as month.date.year, while in Europe this is date.month.year. And when it comes to dates like 02.01.2010 this can be really frustrating.

Beside this ugly format, you can choose to format your dates either with:

1 January 2010 or 1 Jan 2010

which is clear enough, but it’s only for english speakers. You know that in a spanish speaking country you should format the same date as:

1 Ene 2010

where “ene” means enero – january in spanish. How should you overcome this natural PHP problem?

Well the answer is by using Zend_Date

The problem I found in Zend_Date usage is that the native copy/paste technique from the doc page doesn’t seem to work. What the doc page says you is:

// setup the default timezone
date_default_timezone_set('Europe/London');

and than you can simply request a date with:

$date = new Zend_Date(‘2010-01-02’);
echo $date->get('d MMM yyyy');

where this should print 1 Jan 2010.

It’s a shame that this doesn’t work. The good part is that this problem can be overcome very simply. You just need to setup some more things just before calling the get method.

First setup a cache mechanism where you can cache the date locales. This is really good practice because it speeds up the framework when dealing with dates. Just add those lines after the default timezone is set:

// setup the default timezone
date_default_timezone_set('Europe/London');

$locale = new Zend_Locale(‘es_ES’);
Zend_Registry::set('Zend_Locale', $locale);

$frontendOptions = array(
		'lifetime' => 600, // 10 minutes
		'automatic_serialization' => true
);

$backendOptions = array(
                'cache_dir' => '../cache/'
		);

// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core',
		             'File',
		              $frontendOptions,
		              $backendOptions);

First you setup the Zend_Locale – a locale for the entire application and set it up in this example for spanish, than setup the cache mechanism.

This is a typical cache setup for Zend Framework. If you’d like to dive more into cacheing you can checkout the doc pages for Zend_Cache.

After these lines just setup Zend_Date options with:

Zend_Date::setOptions(array('format_type' => 'php',
                   'cache' => $cache));

This is really what you need to do to start. All these lines of code you may place into the bootstrap.php or into some front controller plugin.

Then you can call Zend_Date’s get method wherever you’d like in every controller you need it!