Tutorials

Advanced and Multiple Ternary usage

The ternary within PHP has a right-to-left precedence (which is oddly different to those used in C and C++). If you have used the ternary extensively in either of those languages, be prepared for a few code alterations.

Let's just imagine a working code that returns an ordinal extension for a random number below ten (and above zero) - so we want 1 = 'st', 2 = 'nd', 3 = 'rd' and the rest are 'th'.
Because each subsequent conditional after the first will be executed within the 'false' return of its predecessor, every ternary again needs to be enclosed in parenthesis. A simple code construct would look like:

$r = rand(1,9);
echo
$r. (($r == 3) ? 'rd' : (($r == 2) ? 'nd' : (($r == 1) ? 'st' : 'th')));


To give an indication of parenthesis pairs I have used different font sizes - you should be able to see quite clearly how each ternary is nested within the false return of its predecessor. As on the basic samples page I have moved the echo statement outside the operator calls because it affects every return. If you needed a different function for each return, you would move the entire function call and parameter(s) within the return clauses.

Alternate syntax for multiple Ternary

The above cardinal=>ordinal output script could be written a different way by still using ternary operators as we can sequentially stack the conditionals in an order whereby each test is passed until a point where each subsequent test is failed. I tend to call this way of writing multiple ternary operators the "true until fail syntax", though it probably has a proper name elsewhere. I also find it a lot easier to understand than the first method (especially if you read from the outside inwards - ie read the conditionals forward and the assignments backwards *see notes below).

$r = rand(1,4);
echo
$r;
echo (
$r < 4) ? ($r < 3) ? ($r < 2) ? 'st' : 'nd' : 'rd' : 'th';


You may have noted that in this method I used a 'less than' < operator within the conditionals. This was to assure the "true until fail" methodology was used correctly - every conditional that returns true can be then used as one step from the far right of the assignments/clauses toward the centre. For example, if we had $r = 2 - our first conditional is ($r < 4) which is true so we take one step from the right (from 'th' we step to 'rd') - our next conditional is ($r < 3) which is also true so we take another step (to 'nd') - the next conditional is ($r < 2) which returns false so we do not step any further and are left with 'nd'. $r = 2 => 'nd' (2nd).

Finally some Advanced Samples

We can extend our simple cardinal=>ordinal to work for all numbers by using a modulus return of dividing the absolute of our number by ten (and one hundred to determine exceptions for 11,12 and 13) as shown below.

function ordinal($cdnl)
    {
    
$test_c = abs($cdnl) % 10;
    
$ext = ((abs($cdnl) %100 < 21 && abs($cdnl) %100 > 4) ? 'th'
            
: (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1)
            ?
'th' : 'st' : 'nd' : 'rd' : 'th'));
    return
$cdnl.$ext;
    }
// example echo ordinal(311). '<br />' .ordinal(-321);


To assign 'th' to 11,12 and 13 I moved the "true until fail" multiple ternary over to sit within the false return of a modulus 100 test - should work for all integers that PHP is capable of handling.

If you have read other parts of this site, you may have gathered already that a lot of my interest is directed at using images in PHP with the GD libraries. The next example uses a numeric returning function to determine which image creation function to use within a script. The function getimagesize returns an array wherein the second index holds a reference to the filetype, which can then be used to call a specific GD function for creating an image...

$f_type = getimagesize($base_image);
$created_image =     ($f_type[2] < 4)
                        ? (
$f_type[2] < 3)
                            ? (
$f_type[2] < 2)
                                ? (
$f_type[2] < 1) ?
                                
NULL
                            
: imagecreatefromgif($base_image)
                        :
imagecreatefromjpeg($base_image)
                    :
imagecreatefrompng($base_image)
                    :
NULL;
if(
$created_image !== NULL)
    {
    
// image created ok - continue script


If your build doesn't allow creation from .gif files, you could just replace the imagecreatefromgif call with NULL. You may note there are already two NULLs there anyway, one for a zero return (a non recognized image file) and one for a return of 4 (a .swf filetype).

Using multiple ternary operators for determining an action based upon a numeric return can be used in a large number of situations, mainly because PHP has so many functions and tests that return a recognized and formatted numeric. In recent builds, uploading files to the server has meant accessing the file variables from within the $_FILES (or $HTTP_POST_FILES) array, which is more secure than the old method and I personally think is a lot tidier and easier.

Along with the $_FILES array system of accessing variables for upload files came an additional index named 'error', which luckily for us returns a numeric between zero and four. A return of zero indicates a successful upload while all other returns indicate a failure somewhere and are quite specific about where the error came from. The code below could be used for handling server response after uploading any file.

$err_code = $_FILES['form_field_name']['error'];
if(
$err_code == 0)
    {
    
// successful upload of something - do more tests - add rest of upload code
    
}
else
    {
    echo (
$err_code < 5) ?  ($err_code < 4) ? ($err_code < 3) ? ($err_code < 2) ?
    
'Upload File was above ' .ini_get('upload_max_filesize'). ' bytes in size.<br />' :
    
'Upload File was above [ 89,000 ] bytes in size.<br />' :
    
'Upload File was only partially uploaded, please try again.<br />' :  
    
'No Upload File received, please try again.<br />' :
    
'Unknown Error Encountered, please try uploading again.<br />' ;
    }


The [ 89,000 ] represents the value as specified within the client form for MAX_FILE_SIZE.
The last line, 'Unknown Error' could really be replaced by an empty quote pair as there shouldn't be any circumstances where five or more is returned.

I hope that tutorial has been informative for you and that it has taught you a bit more about PHPs ternary operator than you knew before.
Thus endeth the lesson for today - now go practice ;o)

Back to Tutorials
Page 1: Using the Ternary Operator
Page 2: Sample uses for the Ternary Operator

SiteMap