"Developing Robust Code with PHP" is a series of articles about solving real-world problems in mid- to large-scale applications. In this article, PHP veteran Amol Hatwar discusses how to use variables effectively. He also demonstrates how to construct a configuration file parser using mutable variable names in PHP to simplify script configuration. In my previous article, I looked at some of the factors that must be considered during planning, design, and even writing code. In this article, you'll actually get your hands on the actual code and see something in action. If you haven't read the previous article, it's a good idea to take a look now. Correct handling of variables Variables and functions are essential elements of any computer language. With variables, you can abstract data; with functions, you can abstract lines of code. As Bruce Eckel says in his book "C++ Programming Thoughts", all programming languages provide abstractions. Assembly language is a small abstraction of the underlying machine. Many of the so-called imperative languages that followed (such as Fortran, BASIC, and C) were abstractions from assembly language. The kind and quality of abstraction a programming language provides is directly related to the complexity of the problems you can solve. Understanding how PHP handles variables and functions will help you use them effectively. What's in the name? As I mentioned in a previous article, naming conventions and coding conventions are important. Whatever naming convention you use, remember to stick to it strictly throughout your project. If you use the most widely used naming convention, your code will be accepted by more people. When naming variables, be especially careful not to overwrite variables you are using when including scripts. In large applications, this is a common source of errors when adding new functionality. The best way to prevent this problem is to use prefixes. Use the abbreviation of the module name of the variable as a prefix. For example, if a module that handles voting has a variable that holds a user ID, you could name the variable $poll_userID or $pollUserID. Understanding PHP Variables PHP is an interpreted language. This has many benefits, and you'll soon learn to take advantage of some of them. The first obvious benefit is this: it saves you from the design-code-compile-test cycle—any code you write in the editor is immediately available. However, the most important benefit is that you don't have to worry about the types of variables and how to manage them in memory. All memory allocated to the script is automatically reclaimed by PHP after the script is executed. Additionally, many operations can be performed on variables without knowing their type. The code in Listing 1 works perfectly fine in PHP, but throws a bunch of error messages in C and Java languages: Listing 1. Sample PHP code with variables After installing PHP, if you want to run the code , you can first save the code as a .php file, place the file on your Web server, and then point your browser to the file. A better idea is to install the CGI version of PHP. Then, run the script by entering the following command at a shell or command prompt, replacing script-name with the name of the file that contains your script. path-to-php/php script-name This code works because PHP is a loosely typed language. In plain English, you can assign strings to integers regardless of variable type, and replace smaller strings with larger strings effortlessly. This is not possible in a language like C. Internally, PHP stores the data held by the variable separately from the type. Types are stored in separate tables. Whenever an expression containing a different type occurs, PHP automatically determines what the programmer wants to do, changes the type in the table, and automatically evaluates the expression. Introducing a common trivia It's nice not to worry about type, but sometimes that can get you into real trouble. What's going on? Here's a practical example: I often have to move content created on a Windows-based PC to a Linux system so that I can use it on the web. Windows-based file systems are case-insensitive when handling file names. The filenames DefParser.php and defparser.php point to the same file on Windows. On Linux operating systems, they point to different files. You might advocate using either all uppercase or all lowercase filenames, but your best practice would be to keep case the same. Solving this little problem Suppose you want a function that checks whether a given file exists in a directory without taking case into account. First, break the task down into some simple steps. Breaking down your code might sound ridiculous, but it really helps you focus on that piece of code while you're writing it.Also, rewriting the steps on paper is always much easier than rewriting code: Get all filenames in the source directory filter out . and .. directory Check if the target file exists in that directory If the file exists, get the file with the correct case If the file name does not match, false is returned. To read the contents of a directory, you need to use the readdir() function. More details about this function can be found in the PHP manual (see Resources). For now, just know this: readdir() returns the names of all the files in a given directory one by one on each call. After all file names are listed, it returns false. You will use a loop that terminates when readdir() returns false. But is this enough? Keep in mind that PHP is a loosely typed language, which means that the integer value 0 is treated the same as false (even C treats 0 and the Boolean value false as equivalent). The question isn't whether the code works; imagine if the file's name was 0! The script terminates prematurely. You can use the following script (Listing 2) to determine the equivalence of 0 and the Boolean value false: Listing 2. Script to determine the equivalence of 0 and the Boolean value false So what can you do? You know that PHP stores types internally, and if you can access those types, the problem is solved. The Boolean value false is clearly different from the integer value 0. PHP has a gettype() function, but let's choose the simpler approach here. You can use the === operator (yes, there are three equal signs). The difference is that this operator compares both the value and the type of the data. If you're confused about this, PHP also has the !== operator. These new operators and the gettype() function are only available in PHP 4. Listing 3 shows the complete code that solves this problem: Listing 3. Complete code Lessons Learned from Observations I am not going to explain what the various functions in Listing 3 do. Instead, I encourage you to consult the PHP manual (see References material). Assumed parameter and return value types can be another source of error when you use unfamiliar functions. Rather than explaining the built-in functions in PHP, I'm going to explain something that's not immediately obvious. When different variable types are involved in the termination condition, it is important to perform strong type checking by using the === and !== operators. Code made up of parts I could have written the entire script as one function, but instead I split the code into two functions. Remember the “divide and conquer” rule from the previous article? I do this precisely because each function plays a different role. If you use other scripts to get the contents of a directory, you now have a convenient implementation. Here are a few things I want you to consider: Imagine implementing the entire script as a function, and then imagine the work required to debug, test, and reuse the code. Use loops correctly Now look at the foreach loop and think why not use a for loop? Using a for loop requires that you know the number of items in the array—an extra step is required. Additionally, when dealing with PHP arrays, it is possible to exceed the array bounds. That is, trying to access the 15th element in an array when it only has 10 elements. PHP does give a small warning, but as far as I know, in some cases when running a script repeatedly, the CPU activity rate suddenly jumps to 100% while the server performance continuously drops. I recommend that you avoid using for loops if possible. Assertive if Finally, I want you to look at the larger if condition in the get_file_list() function that ignores the . and .. directories. Obviously, I can go the traditional way and check the variables against constants. But in one of my many coding mishaps, I would often miss the equal sign and later be unable to figure out what went wrong. Of course, PHP doesn't throw an error because it thinks I want to do an assignment rather than a comparison. PHP throws an error message when you compare a constant against a variable and you are missing an equal sign. Mutable Variable Names Now let's talk about something weird. New developers often avoid using mutable variables because they think it's a convoluted way to accomplish a task. In fact, it's easy to understand and use mutable variables. They've helped me out of trouble more than once, and they're an important element of language.In fact, there are situations where using mutable variables is unavoidable. I'll look at one such real-life situation soon, but first let's look at what a mutable variable actually is. Let's try the code in Listing 4 first: Listing 4. Code with mutable variables First, the code in Listing 4 declares a variable named $myStr and assigns the string I to it. The following statement defines another variable. But this time, the name of the variable is the data in $myStr. $$myStr is a way of telling PHP to produce another variable, which means "I want a variable whose name can be found in the variable $myStr". Of course, in order to do this, $myStr must be defined. So now you have a variable called I and assign it a value with the string am. The following statement does the same