Variable Handling and the PHP Novice
Demitrious S. Kelly on 2002 June 25
    

In the beginning, the file was void, and without text. The Programmer brought text to the file by saying "Let there be hello world" and there was hello world, and it was good. But soon hello world was not as good as it once was, and the Programmer said "let there be change!" And where there once was static content in the file, there was now variable content. Beholding the creation, the Programmer was happy, and all was well

.

Many a time PHP novices have struggled with the proper use of variables... Struggled with getting the information they WANT out of a variable... And just what they can DO with variables. So this is the completely-non-definitive guide

to PHP and using variables!

I'm not going to cover how to get variables directly (because they are the by-product of any number of things, which means that there are a million and three ways to get them), and I'm not going to cover ALL of the functions that you can use to work with variables for the same reason. I am going to cover the ideas of working with variables, plain and simple.

Ideas I plan to cover are as follows: Checking, Searching, Extracting, Converting, which will lead into my next article: Arrays



Checking your variables ('How to C.Y.A. when working with variables')

It strikes me that a lot of people take PHP's typecasting (see http://www.php.net/manual/en/language.types.type-juggling.php for an explanation of what I mean when I say 'typecasting') for granted, and fly by the seat of their pants... I will admit that the typecasting built into PHP saves an ungodly amount of time, but it breeds laziness by not properly preparing the novice programmers out there for what kind of confusion not knowing what kind of a variable--a variable happens to be! Take this for example:


<?php


    $data
=@file('http://blah.com/index.shtml');
    
foreach��(��$data��as��$line��)��{
         
echo��$line;
    }


?>


If you over glorify what typecasting is and does, then you would think that the above code is just fine... but if you run it on a server you'll find otherwise... You'll get some error saying something to the effect of foreach is expecting an array. By the book, file() returns an array except when there's an error. We can accommodate this problem by checking what kind of a variable $data happens to be, like so:


<?php


    $data
=@file('http://blah.com/index.shtml');
    
if��(��is_array($data)��)��{
        
foreach��(��$data��as��$line��)��{
            
echo��$line;
        }
    }
    
else��{
        
echo��'File Not Found!';
    }


?>


Now, I probably should have use a different example, but I had this handy and I felt it illustrated the problem appropriately - even though it's using an array and not a normal variable.



According to http://www.php.net/manual/en/language.types.php, PHP supports eight different 'types', however this document will only be covering the first four: boolean, integer, floating-point number (float), and string. Most of the functions I will be referencing throughout this tutorial are located here: http://www.php.net/manual/en/ref.variables.php, if you want to study up beforehand!

Now, usefully enough, PHP has provided us with build-in functions to check our variables with. This makes the life of a good programmer easier, and allows for

more fun time rather than debugging time...The first thing we have in our arsenal is the isset() function. A programmer would use this function to know if a given variable exists at all. Often times you will be writing a Web-based application which needs user input to function properly, and about as often the application will need to make sure that the user input what was needed before going about its business... you would implement isset() like this:

<html>
<body>


<?php


    
function showform() {

        
// We'll use a function to make all of our html form,
        // just to simplify things...
        // Here we declare $variable1 to be 'global'. When
        // a variable is not declared as global inside a
        // function, PHP basically goes'ok, since this is
        // NOT a global variable we'll make a "new"$variable1
        // JUST for use INSIDE this function.  And when the
        // function is finished executing, we can jut throw
        // that variable away! This approach is GREAT when 
        // we want to use variables as temporary things,
        // but not when we want what we're doing to affect
        // the rest of our script's 'world'. When we declare
        // a variable as 'global' it makes the PUBLIC version
        // of that variable available to the function, and
        // any changes we make to are permanent! Also of
        // importance: if you declare a variable as global
        // inside a function--and the variable did not exist in
        // the script beforehand--it does now, so be careful.
        // One last note before I get on with things:
        // if you declare a variable to be 'global' inside
        // one function, then it is global--but only for that
        // function, you must re-declare it as 'global' in each
        // function that you want to work with it globally. Got it?!

        
global $variable1$proof;
        
$proof='<hr>Proof Of Concept!';
        echo 
'<form method="get">';
        echo 
'<hr>';
        echo 
'<input type="text" size="25" name="variable1"
            value="'
.$variable1.'">';
        echo 
'<br>';
        echo 
'<input type="submit" value="TESTME!">';
        echo 
'</form>';

        
// The above is a simple form... I didn't check to see
        // if it conforms to all of the HTML standards, but it
        // works in my browser, and most likely yours, but don't
        // go around saying 'Demitrious SAID I could
        // make forms like this' cause I don't want to hear it!
    
}


    
// Check to see if the variable $variable1 exists at all...
    
if ( isset($variable1) ) {
        
// if it DOES exist
        
echo $variable1.'<br>';
    }
    else {
        
// if it does NOT exist
        
echo 'Missing $variable1<br>';
    }

    
// Show our html form
    
showform();

    
// I threw this in to illustrate a point I made earlier while
    // rambling...
    
echo $proof;


?>


</body>
</html>



Excellent! We can now make absolutely sure that a variable DOES exist, before trying to work with it... and it wasn't hard was it?! The next thing we might want to do is make sure that the type of data we're expecting is actually the type of data we got! We'll do that like this:

<html>
<body>


<?php


    
function showform() {
        global 
$variable1$variable2$variable3$variable4;
        echo 
'<form method="get">';
        echo 
'<hr>';
        echo 
'Enter A String: <input type="text" size="25"
            name="variable1" value="'
.$variable1.'">';
        echo 
'<br>';
        echo 
'Enter An Integer: <input type="text" size="25"
            name="variable2" value="'
.$variable2.'">';
        echo 
'<br>';
        echo 
'Enter A Floating Point Value: <input type="text"
            size="25" name="variable3" value="'
.$variable3.'">';
        echo 
'<br>';
        echo 
'Enter A Boolean Value: <input type="text"
            size="25" name="variable4" value="'
.$variable4.'">';
        echo 
'<br>';
        echo 
'<input type="submit" value="TESTME!">';
        echo 
'</form>';
    }

    
// Check to see if the variable $variable1 exists at all...
    
if ( isset($variable1) && isset($variable2) &&
        isset(
$variable3) && isset($variable4) ) {
        
// If they DO exist...
    
        // Test and see if $variable1 is a string.  Now, it's
        // fairly important to note that in PHP just about
        // ANYTHING counts as a string--thanks to the miracle
        // of typecasting, so this should just about never fail!
        // (even when someone submits "" (a blank line), so we'll
        // check for that too!)

        
if ( is_string($variable1) && $variable1 != "" ) {
            echo  
'String: '.$variable1.'<br>';
        }
        else {
            echo  
'String: INVALID!<br>';
        }

        
// I don't know about YOUR version of PHP, but the
        // manual touts that is_int and is_integer should do
        // the job, but my install won't EVER return true
        // with is_int.  You can test it on yours and see!

        
if ( is_numeric($variable2) ) {
            echo 
'Integer: '.$variable2.'<br>';
        }
        else {
            echo 
'Integer: INVALID!<br>';
        }

        
// AGAIN, if I could use PHP's functions for type
        // checking, I would.  However,m any time I try to
        // use is_float (even when I try
        // is_float(settype($variable3, 'float')) I fail
        // miserably.  So I find a way around this limitation.
        // First we check and see if it's a number with
        // is_numeric (as above), but we take it a step further:
        // if it IS a number, then we use stristr to see if it
        // has a decimal place.  If it DOES, then we consider
        // it a float (for this purpose). Realistically an even
        // number like 1 or 2 can be a float even though they
        // don't have obvious decimal places.  Back in the olden
        // days when programmers needed to actually declare a
        // type for their variables, they had to declare anything 
        // they needed a decimal point value for as a //
        // float--otherwise they were stuck with simple integer
        // values.

        
if ( is_numeric($variable3) ) {
            if ( 
stristr($variable3'.') ) {
                echo   
'Float: '.$variable3.'<br>';
            }
            else {
                echo   
'Float: INVALID!<br>';
            }
        }

        
// OY! Again with the functions not working! is_bool
        // is also always turning false so we have to come up
        // with a work-around. Here's what we'll do; since the
        // only values that can be a boolean are 'TRUE', 'FALSE',
        // '0' and '1' - we'll simply check for those. Now,
        // I don't know about you, but checking for FALSE and FALSe
        // and FALse and FAlse and... well, you get the idea...
        // sounds like a lot of work. To get around all this work,
        // we'll make a new variable called $temp, and $temp will
        // contain everything $variable4 contains, except all
        // lowercase. Now all we have to do is see if $temp is
        // 'false', 'true', 1, or 0. If it is, then we have a
        // boolean! Afterward, we'll free up that small chunk
        // of memory, and unset() $temp (like good little
        // programmers should!)

        
$temp=strtolower($variable4);
        if ( 
$temp == 'false' || $temp == 'true' ||
            
$temp == || $temp == ) {
            echo 
'Boolean: '.$variable4.'<br>';
        }
        else {
            echo 
'Boolean: INVALID!<br>';
        }
        unset(
$temp);

    }
    
    else {
        
// If it they do NOT exist
        
echo 'Missing variables!<br>';
    }

    
// Show our html form
    
showform();


?>


</body>
</html>

That looked like more code then it actually was. Most of that was all comments.



Realistically, checking to make sure we have the right type of value is very easy, and we can make some very simple functions for the types that PHP does not properly cover:

<html>
<body>


<?php


    
function showform() {
        global 
$variable1$variable2$variable3$variable4;
        echo 
'<form method="get">';
        echo 
'<hr>';
        echo 
'Enter A String: <input type="text" size="25"
            name="variable1" value="'
.$variable1.'">';
        echo 
'<br>';
        echo 
'Enter An Integer: <input type="text" size="25"
            name="variable2" value="'
.$variable2.'">';
        echo 
'<br>';
        echo 
'Enter A Floating Point Value: <input type="text"
            size="25" name="variable3" value="'
.$variable3.'">';
        echo 
'<br>';
        echo 
'Enter A Boolean Value: <input type="text"
            size="25" name="variable4" value="'
.$variable4.'">';
        echo 
'<br>';
        echo 
'<input type="submit" value="TESTME!">';
        echo 
'</form>';
    }

    function 
check_bool($var) {
        
$var=strtolower($var);
        if ( 
$var == 'false' || $var == 'true' || $var == ||
            
$var == ) {
            return(
TRUE);
        }
        else {
            return(
FALSE);
        }
    }

    if ( isset(
$variable1) && isset($variable2) &&
        isset(
$variable3) && isset($variable4) ) {

        if ( 
is_string($variable1) && $variable1 != "" ) {
            echo  
'String: '.$variable1.'<br>';
        }
        else {
            echo  
'String: INVALID!<br>';
        }

        if ( 
is_numeric($variable2) ) {
            echo 
'Integer: '.$variable2.'<br>';
        }
        else {
            echo 
'Integer: INVALID!<br>';
        }

        
// Since even a '2' can be a float
        
if ( is_numeric($variable3) ) {
            echo   
'Float: '.$variable3.'<br>';
        }
        else {
            echo   
'Float: INVALID!<br>';
        }

        if ( 
check_bool($variable4) ) {
            echo   
'Boolean: '.$variable4.'<br>';
        }
        else {
            echo   
'Boolean: INVALID!<BR>';
        }

    }
    
    else {
        
// If it they do NOT exist
        
echo 'Missing variables!<br>';
    }

    
// Show our html form
    
showform();


?>


</body>
</html>

I would like to take this time to say that although this is, technically, input validation - it's just the tip of the iceberg. Input validation deserves a whole tutorial in and of itself. So don't think that you're safe because you're doing type checking. ;)



Searching
('The Needle and the Haystack')

A good majority of the time, we depend on people as the source of our variables.


The problem with this is that people are inherently unreliable. And often times you need to search through all of the 'junk' to find what you are looking for. Now, all of the PHP manuals use the term 'haystack' for the data you are searching through, and 'needle' for what you are searching for. I quite like this convention, so let's stick with it...

1) Making sure a variable contains something


<?php


    $haystack
='Demitrious Shaun Kelly';
    
$needle='Shaun';
    if ( 
substr_count($haystack$needle) ) {
        echo 
'SUCCESS!';
    }
    else {
        echo 
'FAILURE!';
    }


?>


2) But what if a user is searching for 'shaun' and he needs to get 'Shaun' out
of my name? We COULD use strtolower() like I did before (with the boolean
values) but that's not very elegant, so we'll do it like this:


<?php

    
if ( stristr($haystack$needle) )

?>


NOTE: our second method can completely replace the first, as long as you want a
case insensitive search.


3) What happens if we're using numbers? EASY! PHP treats an integer (and boolean and float) just like a string when it needs to (this is where the raw beauty of typecasting comes into play!)


<?php


    $haystack
=123456789;
    
$needle=0;
    if ( 
stristr($haystack$needle) ) {
        echo 
'SUCCESS!';
    } 
    else {
        echo 
'FAILURE!';
    }


?>


That was georgeous wasnt it?!



Extracting from variables
('Diamonds in the Coal Mine!')

Lets say, for a moment, that you get a piece of data from a user; it is supposed

to be an e-mail address. Because you can rarely really trust your users, we need to make SURE that it's an e-mail address that they gave us. We'll do this two ways, the hard way, and the easy way. Both are valid, and both have their uses, which is why I'm going to present them to you now!


<?php


    
if ( ! isset($mail) || $mail == "" ) {
        
$mail='apokalyptik@apokalyptik.com';
    }

    function 
inputform() {
        
// Here we just make a simple html form with which to
        // enter an address... this way we can test the script
        // without having to edit it directly, we can just
        // change the form

        
global $mail;

        echo 
'<form method="get">';
        echo    
'<div align="center">'
            
.'Address: <input type="text" name="mail" value="'.$mail
            
.'"> <input type="submit" value="Test!"></div><hr>';
        echo 
'</form>';
    }

    function 
testaddr($addy) {
        
// an email address should have 3 distinct parts to it:
        // 1. a username
        // 2. an @ symbol
        // 3. a domain name
        // in that order.
        // Now, a domain name MUST be at least 2 fields,
        // separated by a '.' but can be any number of
        // fields separated by '.' characters...

        // Check to see if we have our @ symbol
        
if ( stristr($addy'@') ) {
            
// And if there's at least 1 character before the @

            
if  ( strpos($addy'@') > ) {
                
// Now we want to work only with everything
                // AFTER the @, so we use substr to get just that!

                
$domain=substr($addy, (strpos($addy'@') + 1));
                
// Why did I use '(strpos($addy, '@') + 1)' when
                // it seems like substr($addy, strpos($addy, '@'))
                // should do fine? Well, try it and put an
                // 'echo $domain;' in and see what happens.  ;)
                // A domain name would have to have at LEAST 3
                // characters 'x.y' which is forgiving, but we
                // aren't arguing Internet naming here;
                // just working through an example.  :)

                
if ( strlen($domain) > ) {
                    
// check for our period
                    
if ( stristr($domain'.') ) {
                        
// Check to make sure that the '.' is
                        // not the very last character in the
                        // domain; otherwise, its not very valid,
                        // is it?  (I suppose that technically it
                        // IS valid, but we're not getting into that,
                        // because if you want to get technical it
                        // should be .com.apokalyptik@apokalyptik,
                        // but that's just arguing semantics...
                        // on with the howto!)

                        
if ( strrpos($domain'.') < ( strlen($domain) - 1)) {
                            
// Why did I just do
                            // '( strlen($domain) - 1)'? Well, that's
                            // actually a VERY good question, and
                            // I'm glad you are so perceptive.  When
                            // working with these types of variables,
                            // it's always necessary to take into
                            // account the function that you are using:
                            // strlen() returns the total number of
                            // characters in the string, so strlen('a');
                            // would return 1, and strlen('aa'); would
                            // return 2.  Now, strpos and strrpos both
                            // consider the first character of a string
                            // to be the 0th position, so strlen('lazy');
                            // would return 4, while strrpos('lazy', 'y');
                            // would return 3, because strrpos considers
                            // 'l' to be 0, 'a' to be 1, 'z' to be 2,
                            // and 'y' to be 3. So, to compare the two
                            // directly we would need to subtract 1 from
                            // what strlen gives us, or add one to what
                            // strrpos returns--get it? Now we need to
                            // make sure that we've got SOMEthing between
                            // our '@' and our '.'

                            
if ( strpos($domain'.') > ) {
                                
// YES! It's valid ONLY if we've met all
                                // of these criteria!
                                
$return[]=substr($addy0strpos($addy'@'));
                                
$return[]=$domain;
                                return(
$return);
                            }
                            else {
                                
// If anything fails, we declare it invalid
                                // --thus this huge stream of return(0)'s
                                
return(0);
                            }
                        }
                        else {
                            return(
0);
                        }
                    }
                    else {
                        return(
0);
                    }
                }
                else {
                    return(
0);
                }
            }
            else {
                return(
0);
            }
        }
        else {
            return(
0);
        }
    }

    
inputform();
    
$test=testaddr($mail);
    if ( 
$test ) {
        echo 
'VALID! Username: "'.$test[0].'" Domain: "'.$test[1].'"';
    } else {
        echo 
'INVALID!';
    }


?>



That works beautifully! But it was kind of a long process, wasn't it? Well yes! There's the hard way, and the easy way (TNT) ...




<?php


    
if ( ! isset($mail) || $mail == "" ) {
        
$mail='apokalyptik@apokalyptik.com';
    }

    function 
inputform() {
        
// Here we just make a simple html form with which to
        // enter an address. This way, we can test the script
        // without having to edit it directly--we can just
        // change the form

        
global $mail;

        echo 
'<form method="get">';
        echo    
'<div align="center">'
            
.'Address: <input type="text" name="mail" value="'.$mail
            
.'"> <input type="submit" value="Test!"></div><hr>';
        echo 
'</form>';
    }

    function 
testaddr($addy) {
        
// WOW that works with only ONE test... but is it simpler?
        // Well... yes - if you spend the time to get familiar
        // with regular  expressions.
        // http://www.phpbuilder.com/columns/dario19990616.php3
        // is a good resource for this. But what, exactly,
        // did THIS mean? Well, I really do suggest reading about
        // regular expressions from  the beginning so, instead of
        // explaining it here piece by piece, I'll give you this url:
        // http://www.phpbuilder.com/columns/dario19990616.php3?page=4

        
if ( ereg('^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$'$addy$regs)) {
            
$return[]=substr($addy0strpos($addy'@'));
            
$return[]=substr($addy, (strrpos($addy'@') + 1));
            return(
$return);
        }
        else {
            return(
0);
        }
    }

    
inputform();
    
$test=testaddr($mail);
    if ( 
$test ) {
        echo 
'VALID! Username: "'.$test[0].'" Domain: "'.$test[1].'"';
    }
    else {
        echo 
'INVALID!';
    }


?>


These examples are only the tip of the iceberg when it comes to manipulating data in PHP, but they are good practice! With a little patience, and a lot of experimentation you'll be able to turn apples to oranges while working with the needle in the haystack even on the cloudiest of days!

-Demitrious

Home page: http://www.apokalyptik.com/
I'm also available for *nix and PHP consulting, e-mail
apokalyptik@apokalyptik.com if interested. Cheers!In the beginning, the file was void, and without text. The Programmer brought text to the file by saying "Let there be hello world" and there was hello world, and it was good. But soon hello world was not as good as it once was, and the Programmer said "let there be change!" And where there once was static content in the file, there was now variable content. Beholding the creation, the Programmer was happy, and all was well
Tentatively planning to Open Soon! (no dates ...) // Doing heavy development now...