PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 3 ■ OBJECT BASICS


As you can see, the outputAddresses() method loops through an array of IP addresses, printing each
one. If the $resolve argument variable itself resolves to true, the method outputs the domain name as
well as the IP address.
Let’s examine some code that might invoke this method:


$settings = simplexml_load_file("settings.xml");
$manager = new AddressManager();
$manager->outputAddresses( (string)$settings->resolvedomains );


The code fragment uses the SimpleXML API (which was introduced with PHP 5) to acquire a value
for the resolvedomains element. In this example, I know that this value is the element text "false", and I
cast it to a string as the SimpleXML documentation suggests I should.
This code will not behave as you might expect. In passing the string "false" to the
outputAddresses() method, I misunderstand the implicit assumption the method makes about the
argument. The method is expecting a Boolean value (that is true or false). The string "false" will, in
fact, resolve to true in a test. This is because PHP will helpfully cast a nonempty string value to the
Boolean true for you in a test context. So


if ( "false" ) {
// ...
}


is equivalent to


if ( true ) {
// ...
}


There are a number of approaches you might take to fix this.
You could make the outputAddresses() method more forgiving so that it recognizes a string and
applies some basic rules to convert it to a Boolean equivalent.


// class AddressManager...
function outputAddresses( $resolve ) {
if ( is_string( $resolve ) ) {
$resolve =
( preg_match("/false|no|off/i", $resolve ) )?
false:true;
}
// ...
}


You could leave the outputAddresses() method as it is and include a comment containing clear
instructions that the $resolve argument should contain a Boolean value. This approach essentially tells
the coder to read the small print or reap the consequences.


/**



  • Outputs the list of addresses.

  • If $resolve is true then each address will be resolved

  • @param $resolve Boolean Resolve the address?
    */
    function outputAddresses( $resolve ) {
    // ...
    }


Finally, you could make outputAddresses() strict about the type of data it is prepared to find in the
$resolve argument.

Free download pdf