Test Drive PHP 5.5: A Sneak Peek

PHP 5.5

There’s been some talk about PHP 5.5.0 over the past couple of months even though it is barely on the horizon. The reason for this is that the PHP project has seen some increased levels of activity over the last two years since the dawn of PHP 5.4 and now in to the early twilight phase of PHP 5.5.0-dev. For those of you that haven’t been following the internals mailing list I’m about to give you a quick test-drive and sneak-peek at PHP 5.5 using the latest 5.5.0-dev branch (which is still TBD). I’m not just going to introduce you to some of the new features we can expect to see in PHP 5.5, but also I’ll be test-driving practical uses for some of those new features and even giving you some actual bench marks for generators in PHP 5.5.

There are no official road-maps laid out for PHP 5.5.0 yet. So things can change quite rapidly over the coming weeks. The early, but not voted on, plan was to get PHP 5.5.0 released by sometime during early 2013. This may or may not be delayed depending on what the RM decides in the next few weeks.

PHP In 2012

First, let’s start with a brief history of what’s taken place so far this year with the PHP project.

It’s been nearly 8 months since the release of PHP 5.4.0 early this year in March of 2012. So far PHP has seen a number of significant additions, omissions, changes, and improvements. In 5.4 we saw the long awaited departure of register_globals, allow_call_time_pass_reference, safe mode, and (good riddance) magic_quotes — among others. We also saw many engine-level improvements with welcomed performance benefits. There was also the addition of traits (for horizontal code reuse and addressing the alternatives to multiple inheritance and mixins in PHP). The favored shortned array syntax and FAD (Function Array De-refrencing) also made an appearance this year in PHP 5.4. Let’s also not forget about the new Session handling improvements with support for object oriented session handlers and a well rounded interface for better exposing user session APIs. Of course, there’s the now exceedingly popular built-in PHP testing server that’s gained good traction in just a short amount of time.

This all sounds great so far and 5.4 has made a lot of headway. Usage among the community appears to be welcoming these changes. The pace at which extensions in the PHP PECL repository is responding to the updates in 5.4, however, might be a bit a more lax. Most of the popular extensions have been tested well enough for 5.4 like Xdebug, and APC, but you still have your basic quirks every now and again.

What We Can Expect to See In PHP 5.5

Here are some of the things we can expect to see in the official release of PHP 5.5.0 next year…

These are the things that have already been voted on in the RFC process and implemented. So they’re highly likely to be in the next release unless there’s a last minute change. Some of the things that are still under discussion include…

These are things that seem to be yielding a well-rounded discussion and have attracted some decent amount of attention. It’s likely that these are some of the features that might get voted in, but of course there’s no telling if they’ll make it to the next release or not until they’ve gone through the voting process and have an actual working implementation.

New finally Keyword

In my last post I already discussed the new finally keyword in try/catch and went over the implementation in some detail. For this post I’ll just mention that the feature has been voted in and accepted, which means there’s already an excellent chance we’ll be seeing it in PHP 5.5 next year.

Support For list In foreach Construct

This is a minor change that has also been voted in and accepted. This feature allows you to use the list construct in foreach. This is basically just a good way to avoid another level of indirection in your foreach loops. A good use case would be for when you’re looping over an array of arrays and you want to avoid the indirection for the variables in your loop. Here’s an example to give you an idea of how this will work. Say we have an array of arrays that contain x,y coordinates like so…

$array = array(
               array(12,32),
               array(61,4),
         );

This is how we’d normally handle this in a foreach loop today…

foreach ($array as $coordinates) {
    echo "X = $coordinates[0], Y = $coordinates[1]\n";
}

The output would be…

X = 12, Y = 32
X = 61, Y = 4

Instead, we can avoid that extra level of indirection and do the following…

foreach ($array as list($x, $y)) {
    echo "X = $x, Y = $y\n";
}

Output is the same…

X = 12, Y = 32
X = 61, Y = 4

This is pretty similar to doing…

foreach ($arrays as $coordinates) {
  list($x, $y) = $coordinates;
  echo "X = $x, Y = $y\n";
}

Which isn’t very difficult to do now, but it’s also been a requested feature for some time and it does make things a bit more user-friendly in terms of delegating the construct to the de-referencing as opposed to handling it directly from within the loop.

Password Hashing API

This is a good and one I’ve personally vouched for. Let’s face it, crypt has one heck of an intimidating interface. It’s not pretty and it certainly isn’t very intuitive. Most people will find that just figuring out how to hash a password using crypt in PHP requires paying very close attention to the manual or silly mistakes can be made that can end up costing you big in terms of security compromise. PHP crypt has also had a number of significant changes since PHP 5.2 and not all of those changes are immediately obvious.

Let’s take a look at a very simple example of how we can hash a password, say GoogleGuy, using crypt today. First, we’ll need to pick a hashing algorithm. If you’re one of the few unfortunate folk to still be stuck with PHP 5.2, you’ll have to ensure that that hashing algorithm has an available implementation install on your system libcrypt. As of PHP 5.3 we can rest assured all of the algorithms listed at php.net/crypt are available as native PHP implementations as a fallback if the system does not provide them.

So say we’ve picked BLOWFISH as our hashing algorithm. Now, based on that algorithm we’ll have to define an appropriate salt. Every algorithm takes on a different salt and every salt has varying requirements, but all salts are represented by a single string in the salt parameter of crypt. Not to mention the salt is also split into ALGORITHM-COST/ROUNDS-SALT parts delimited by a ‘$’ character. Different algorithms also use different alphabets. Confusing, isn’t it?

So to use BLOWFISH we have to pick a salt that’s 22 characters long from the alphabet A-Za-z0-9./ and remember that this is not a base64 alphabet, but a close variant of base64. That’s not too difficult if we simply rely on functions such as mcrypt_create_iv to generate random data from a really good source of entropy like /dev/urandom. We’ll just have to ensure that the salt uses the appropriate characters from the required alphabet like so…

function make_blowfish_salt() {
  $alphabet = array_merge(range('A','Z'), range('a','z'), range(0,9), array('.','/'));
  shuffle($alphabet);
  $salt = '';
  if (($iv = mcrypt_create_iv(22, MCRYPT_DEV_URANDOM)) === false) {
    trigger_error("Unable to initialize vector from mcrypt.", E_USER_ERROR);
  }
  for ($i = strlen($iv) - 1; $i >= 0; $i--) {
    $salt .= $alphabet[ord($iv[$i]) % 64];
  }
  return $salt;
}

echo $salt = make_blowfish_salt();

Should output something similar to…

j/.FNM4B4ktUJvXrvxdlV6

Which is very good entropy-wise for a salt. Remember that if you use a salt shorter than the 22 character length crypt will null pad the rest. So the longer the salt the better for the purposes of password hashing.

Now that was just the part where you create the salt. We still have to supply the algorithm and cost along with that to the salt parameter of the crypt function.

$password = 'GoogleGuy';
echo $hash = crypt($password, '$2a$10$' . $salt . '$');

Outputs:

$2a$10$j/.FNM4B4ktUJvXrvxdlVungfSrbPOUPpyM5jxguu9tC2Y4w2z1wa

Here we supplied the BLOWFISH or BCRYPT algorithm using the $2a$ part of the salt argument in our string. The cost is then specified as 10, which is also delimited by a $ character and followed by our salt and a final $ character delimiter at the end. To verify future password authentication attempts we simply resend the $password along with the output we got from crypt (our $hash) and compare…

if ($hash === crypt($password, $hash)) {
  echo "Authentic!\n";
} else {
  echo "Not authentic :(\n";
}

Output:

Authentic!

It’s the first part (when we create the hash) that’s confusing. It doesn’t look very intuitive at first and most novices will get it wrong the first few times around. So with the simplified password hashing API we can now do this…

echo $hash = password_hash(
                           $password,
                           PASSWORD_BCRYPT,
                           array('cost' => 10)
                           );

Alternatively…

echo $hash = password_hash(
                           $password,
                           PASSWORD_DEFAULT,
                           );

This results in the same exact thing, but it looks a little more intuitive and easier to pick up on than what we’re currently using in crypt. There are also some neat features that we haven’t considered like the ability to verify a password without inadvertent variable comparison slips or remote timing attacks. Instead of what we did above consider…

if (password_verify($password, $hash)) {
  echo "Authentic!\n";
} else {
  echo "Not authentic :(\n";
}

Here they do the same thing, but the function name gives some verbosity as to what’s going on here. The implicit thing is it helps avoid our application from exposing us to any remote timing attacks which you won’t necessarily get with the previous method (comparing the hash with the result of crypt). Also, I happen to see this is an upside for developers to take notice since most beginners don’t easily grasp on to the fact that verifying or authenticating the hash from the password is as simple as comparing crypt’s output (using the supplied password) to the stored hash.

Note that you do not have to generate your salts manually using a similar function like the one demonstrated above. There was a proposal in the original RFC to have a password_make_salt() function, but it was decided not to expose this in the API and instead generate the salt automatically when one is not supplied. Provided a user-space implementation, like the make_blowfish_salt() function demonstrated here, one can still continue to supply their own salts. It’s just not a requirement for using the API and makes the entire process a lot more convenient.

Another added bonus is the ability to check a hash’s algorithm and cost parameters with ease. So now, if you wanted to test which algorithm and cost parameters were used for a particular hash you can do the following.

$hash_info = password_get_info($hash);
var_dump($hash_info);

Would output similar to…

array(3) {
  ["algo"]=>
  int(1)
  ["algoName"]=>
  string(6) "bcrypt"
  ["options"]=>
  array(1) {
    ["cost"]=>
    int(10)
  }
}

This allows us to make it easier for clients to verify if a hash needs to be regenerated in-case you later decide to change the hashing algorithm or cost parameter. Here’s a simple example to illustrate. Say we currently have a database full of thousands of hashes for our users’ passwords. They’re all currently using a BCRYPT hash, but with a cost parameter of 7 and we’d like to increase that cost to say 11 for stronger hashing. We’ll have to wait until each user re-authenticates (logs back in to the system) before we can rehash the password, but this means we’ll have to also verify that the password hasn’t already been rehashed to avoid unnecessary rehashing and writes to the database for those that have already completed the process. So we verify that by using the password_needs_rehash() function provided by the API like so…

$new_cost = 11;
$salt = make_blowfish_salt();
$hash = password_hash(
                      $password,
                      PASSWORD_BCRYPT,
                      array(
                            "cost" => 7,
                            "salt" => $salt
                           )
                     );

if (password_verify($password, $hash)) {

  // The password is good...
  if (password_needs_rehash($hash, PASSWORD_BCRYPT, array('cost' => $new_cost))) {
    // Go ahead and rehash the password here and save it to the database...
    echo "We need to rehash this password...\n";
    $new_hash = password_hash(
                              $password,
                              PASSWORD_BCRYPT,
                              array(
                                    'cost' => $new_cost,
                                   )
                             );
  } else {
    // Otherwise we don't need to rehash just continue...
    echo "We're all set!\n";
  }
  
} else {

  // The password is no good...
  echo "Wrong password...\n";
  
}

There are no actual performance gains or losses involving this new Simplified Password Hashing API, but it still does require that you have the PHP crypt extension enabled. It relies on it internally to do the actual work. One of the short-comings of this API is that it currently only supports the BLOWFISH_CRYPT algorithm, while crypt has support for a number of other algorithm not available here. Though BCRYPT is arguably the strongest of those algorithms, it would be nice to see perhaps SHA512 and some of the other SHA* family for backwards compatibility with those coming to the new API from crypt.

Generators

Last, but certainly not least, is the addition of Generators in PHP, which are currently available in languages like Python. Generators, according to the accepted RFC, “provide an easy, boilerplate-free way of implementing iterators“. This is a welcomed addition since I know first-hand of how messy it can get once you start writing tons of boilerplate code for implementing various iterators.

Let’s assume we wanted to write a very simplistic, straight-forward, iterator that can iterate over the lines in a text file.

class FileIterator implements Iterator {
  protected $fp, $filename, $line, $position;
 
  public function __construct($filename) {
    $this->filename = $filename;
    if (!$this->fp = fopen($this->filename, 'r')) {
      throw new RuntimeException("Couldn't open file '$filename'");
    }
  }

  public function rewind() {
    fseek($this->fp, 0);
    $this->line = fgets($this->fp);
    $this->position = 0;
  }
 
  public function valid() {
    return $this->line !== false;
  }
 
  public function current() {
    return $this->line;
  }

  public function key() {
    return $this->position;
  }
 
  public function next() {
    if ($this->line !== false) {
      $this->line = fgets($this->fp);
      $this->position++;
    }
  }
 
  public function __destruct() {
    fclose($this->fp);
  }
}

Now, our class FileIterator implements the iterator interface and is capable of iterating over the lines of a file with ease like so…

$filename = 'somefile.txt';
$it = new FileIterator($filename);

foreach ($it as $line) {
  echo $line;
}

The problem is this can leave us with a ton of boilerplate code hanging around for all kinds of iterators we may implement now or in the future. Generators make this process a lot more straight-forward. It’s much easier to comprehend what’s going on in the following code than it is in the previous code above (at least in my opinion it is).

function getLinesFromFile($fileName) {
  if (!$fileHandle = fopen($fileName, 'r')) {
    return;
  }
 
  while (false !== $line = fgets($fileHandle)) {
    yield $line;
  }
 
  fclose($fileHandle);
}

The above function automatically becomes a generator the moment the parser detects the yield keyword inside the function. This causes the function to behave like an object instead of a regular function. The trick is we then get the object to implement the iterator interface internally and avoid the whole debacle of having to write all of that iterator boilerplate code we did above. This leaves us with the added advantage of not having to load the entire file into memory, but instead traverse the lines of the file one-by-one without keeping it all in memory at the same time. So basically all the same benefits of the iterator, but without the hassle.

$filename = 'somefile.txt';
$gen = getLinesFromFile($filename);

foreach ($gen as $line) {
  echo $line;
}

As you can see we still call it just like a function, but its return value is actually an object. In fact, if we var_dump($gen) here we’ll get…

object(Generator)#1 (0) {
}

So the function just ends up passing back an object of type Generator the first time it gets called. Since this generator object implements the Iterator interface for us it becomes traversable and we can iterate over it in our foreach loop just like we did with the FileIterator class. The key here is that the object knows to “yield” or pass control back to the caller every time it hits the “yield” keyword. So to us this appears to be doing the same thing our iterator’s next method would normally do whenever we want to move the pointer forward. Instead of calling the object to change state we simply transfer control of the function back and forth between the callers.

Some Real Bench Marks Using PHP Generators

I thought to take this one out for a spin since I really liked the idea of generators in PHP from the beginning and I’ve personally rooted for it since its early development. To give you an idea generators fair closely in comparison to iterators when using very small sample sizes (say just a few hundred elements). Iterators sometimes prove slightly faster with very small samples, but this is mainly due to implementation details I’d rather not scrutinize at this stage. However, generators have demonstrated significant performance improvements (up to twice the performance gains) with large data sets.

Using a file of just 100 lines given the example above for both the FileIterator iterator and the getLinesFromFile generator, the iterator gave an average performance of about 2.75 microseconds per iteration. The generator gave an average performance of around 6.01 microseconds per iteration. That sounds horrible, I know (more than twice as slow as iterators). But in the grander scheme of things we’re only iterating over 100 lines so that means the real difference is just a few hundred microseconds, which is nothing really.

Despite this strange performance loss with small samples, however you’ll be shocked to see the difference when I tested this using a file of 1 million lines (totaling 834 MB). With this huge sample size iterators demonstrated an average performance of roughly 3.82 microseconds per iteration. Whereas generators showed an outstanding average of 1.80 microseconds per iteration. That’s more than twice as fast when we introduced four orders of magnitude more iterations!

Actual Run Times

Test Number of Iterations Average Runtime (seconds)
Iterator 100 0.000275
Generator 100 0.000601
Iterator 1,000,000 3.828718
Generator 1,000,000 1.800595
All of these benchmarks were done using Intel dual core and quad core processors on linux 64-bit built machines using PHP 5.5.0-dev and averaged out after redacting the first and last test runs.

Generators aren’t just fast, they can also save you a lot of development time. Reduced lines of code ultimately means a reduced potential for bugs since number of lines of code is proportional to the potential for bugs.

So Why Not Just Fill Arrays?

If you’re wondering, why not just do something like the following instead…

$filename = 'somefile.txt';
foreach (file($filename) as $line) {
  echo $line;
}

After all, this is far less lines of code than both the iterators and generators approach!

Well, the answer is ultimately going to come down to memory constraints. If you’re trying to iterate over 1 million lines like I did in this test, you aren’t just going to need enough memory to store the entire file when you fill an array with the lines of the file in PHP. You’re going to need approximately 73 to 137 MB more memory (depending on your build) on top of the 834 MB needed to load the file. This is because PHP arrays are very very costly in terms of memory. They are the least efficient means of storing an array since they aren’t really arrays, but ordered hashmaps. It’s well known that hashmaps sacrifice memory for performance when the memory storage requirements necessitate random-access, which PHP arrays offer.

You’re also not going to get such a huge performance benefit out of this method given that you carry an extra cost of loading the entire file into memory first, before iteration can even begin. You’re also hashing an entire 1 million element array in PHP instead of just dealing with binary strings, which is what it comes down to in our iterator/generator examples.

Consider that even with small sets the above method still proves slower than both iterators and generators with an average per-iteration time of 7.64 microseconds when performing on sets of just 100 lines. That’s slower than the generator performed with small samples. I had to kick memory up to 2GB to get this to work with foreach(file(…) …) method above using our large sample of 1 million lines. Keep in mind that’s 2GB per request since PHP doesn’t share memory, so that means you can expect a lot of out of memory fatals if you throws this up on a heavily trafficked site with a node that may not have hundreds of gigs of memory to spare. But here you’ll see that file() ended up performing even more poorly than iterators on large sets.

Test Number of Iterations Average Runtime (seconds)
Iterator 100 0.000275
Generator 100 0.000601
file() 100 0.000764
Iterator 1,000,000 3.828718
Generator 1,000,000 1.800595
file() 1,000,000 6.054362

At the end of the day, generators seem to win in terms of both memory efficiency over huge data sets (which iterators can also offer), as well as performance (which iterators seem to do worse on when given larger and larger data sets), and even in terms of code consumption and readability (generators seem to offer a more straight-forward way to write your code than iterators do).

Property Accessor Syntax

This one is still pretty iffy and we’re not sure yet if it will make it into PHP 5.5, but there’s a bit of active discussion around it so far. The idea stems from an early RFC a few years ago and is based on C#’s property accessor syntax. Here’s an example of what this feature tries to do in a nutshell…

Say we have a few properties in our class and they each behave a little differently. Currently, PHP offers magic getters and setters to allow you to autonomously deal with inaccessible properties in a uniform way. Unfortunately, this solution does not seem to work well for some scenarios, but works great for most. To illustrate let’s create a ShoppingCart class that has three properties.

class ShoppingCart {
  protected $items = [];
  private $tax, $total;

  public function __get($name) {
    /* Inaccessible properties */
    return $this->items[$name];
  }

  public function __set($name, $value) {
    /* Inaccessible properties */
    $this->items[$name] = $value;
  }
}

The $items array in the example above is declared as protected so only the class and its ancestors have access to it from object context. The only way to get at it is from within the class members themselves. So here’s an example of where I instantiate and add a few items to my ShoppingCart object.

$cart = new ShoppingCart;

$cart->book = 10.99;
$cart->laptop = 299.99;
$cart->camera = 99.99;

We’ve added the prices of three different items into the object. Here the magic setters get invoked and what we really end up with is adding them into the protected $items array. We can see this when we use var_dump($cart) to look at the object.

object(ShoppingCart)#1 (3) {
  ["items":protected]=>
  array(3) {
    ["book"]=>
    float(10.99)
    ["laptop"]=>
    float(299.99)
    ["camera"]=>
    float(99.99)
  }
  ["tax":"ShoppingCart":private]=>
  NULL
  ["total":"ShoppingCart":private]=>
  NULL
}

The problem now is how do we calculate the tax and add up the totals?

Well, here we’re going to have to modify our magic __set function to sum up the totals and calculate the tax for us, or else we would have to define our own calculateTax() and//or calculateTotal() methods and invoke them every time we wanted to sum up the totals. So we can do the following instead…

class ShoppingCart {
  protected $items = [];
  private $tax, $total;

  public function __get($name) {
    /* Inaccessible properties */
    return $this->items[$name];
  }

  public function __set($name, $value) {
    /* Inaccessible properties */
    $this->items[$name] = $value;
    /* First we'll calculate the subtotal */
    $sub_total = array_sum($this->items);
    /* Based on subtotal derive the tax rate */
    if ($sub_total < 100) {
      /* 7% tax for purchases under $100 */
      $tax_rate = 0.07;
    } elseif ($sub_total >= 100 && $sub_total <= 200) {
      /* 12% tax for purchases between $100 and $200 */
      $tax_rate = 0.12;
    } else {
      /* 15% tax for purchases over $200 */
      $tax_rate = 0.15;
    }
    /* Final tax amount is tax_rate * sub_total */
    $this->tax = $sub_total * $tax_rate;
    /* Grand total is sub_total + tax */
    $this->total = $sub_total + $this->tax;
  }
}

We want to keep the $total and $tax properties out of the hands of the public, because the client might inadvertently reassign the tax or total properties and mess up our entire logic. Keeping them private ensures that only the class and its members have access to modify this information. Now, the only problem remaining is how do we read from those properties.

We could do it two ways. One option is to prevent our magic setter from allowing us to define a property named tax or total. That way we can check the $name in our magic getter and return those values instead. However, that might get just a little confusing and/or annoying if we ever decide to have a product called tax or total. The other option is to define our own custom method to return these values. I’ll choose the latter for demonstration.

class ShoppingCart {
  protected $items = [];
  private $tax, $total;

  public function __get($name) {
    /* Inaccessible properties */
    return $this->items[$name];
  }

  public function __set($name, $value) {
    /* Inaccessible properties */
    $this->items[$name] = $value;
    /* First we'll calculate the subtotal */
    $sub_total = array_sum($this->items);
    /* Based on subtotal derive the tax rate */
    if ($sub_total < 100) {
      /* 7% tax for purchases under $100 */
      $tax_rate = 0.07;
    } elseif ($sub_total >= 100 && $sub_total <= 200) {
      /* 12% tax for purchases between $100 and $200 */
      $tax_rate = 0.12;
    } else {
      /* 15% tax for purchases over $200 */
      $tax_rate = 0.15;
    }
    /* Final tax amount is tax_rate * sub_total */
    $this->tax = $sub_total * $tax_rate;
    /* Grand total is sub_total + tax */
    $this->total = $sub_total + $this->tax;
  }

  public function Total() {
    return $this->total;
  }

  public function Tax() {
    return $this->tax;
  }
}

So now we can do the following to see our tax and totals…

$cart = new ShoppingCart;
$cart->book = 10.99;
$cart->laptop = 299.99;
$cart->camera = 99.99;

echo "Tax = {$cart->tax()}\n";
echo "Total = {$cart->total()}\n";

This should give us the following output.

Tax = 61.6455
Total = 472.6155

As you can see this entire scenario works out well for us until we suddenly realize that we need to add a subtotal property and a discount property. Now the behavior of these properties might be very different and this increases the complexity of our magic getters and setters because we lump the behavior of all properties into a single function.

The Solution Property Accessors Offer

A quick note from the RFC:

Properties provide a clean, easy to understand and unified syntax for get/set accessors. They allow incoming and outgoing requests (gets and sets) from a class member to be run through a method first. This method can perform validation or a transformation, or update other areas of the class. Properties do not even have to be associated with a class member, and can generate their own data on-the-fly.

class Shoppingcart {
  private $tax {
    get {
      if ($this->subTotal < 100) {
        $this->tax = 0.07;
      } elseif ($this->subTotal >= 100 && $this->subTotal <= 200) {
        $this->tax = 0.12;
      } else {
        $this->tax = 0.15;
      }
        return sprintf("%.2f%%", $this->tax * 100);
    }
    set {
      $this->total = $this->subTotal * $value;
    }
  }
	
  private $subTotal, $total;
}

Now the semantics of what we’re trying to do seem a little more straight-forward in this code. Every time the $tax property is updated or “set” we automatically recalculate the total based on the $subTotal property multiplied by whatever the tax percentage is set to. Note that here the $value variable holds the incoming value for the property when it’s set accessor method is invoked. So every time we update the tax rate we automatically update the totals. This is opposed to having done all of this from within our magic __set() method in the previous example where we update everything every time the client invokes the magic setter.

Both approaches work, it’s just a question of how well this feature could be implemented in PHP and how many people may find it useful.

Scalar Type Hints

This has been a pretty controversial one over the years. It’s actually been proposed as far back as PHP 5.3, but it never made it into release. The problem isn’t as simple as it appears to be. Most of the controversy around Scalar Type Hinting in PHP resonates from PHP’s implicit type-juggling behavior and no one can seem to come to a consensus on how this should be implemented.

If you haven’t been following this discussion in the past nikic has a really good post on the issue, called Scalar type hinting is harder than you think, and I believe he does a fine job of summing it up nicely. So I’d suggest you give that a read if you haven’t already.

Mostly, what’s different about this proposal is the feature will rely on explicit casting as opposed to strict type hinting behavior. Keep in mind PHP is not a statically typed language and it has no strict type enforcement and rarely any type safety checks. This is where a lot of people get confused about how Scalar Type Hints should work in PHP, because you can’t enforce scalar types in PHP in any reasonable manner. So the next best compromise was to use casting where lossy casts could be avoided or throw errors.

function Squared(int $num) {
  return pow($num, 2);
}
/*
  The problem is we have no guarantee
  that Squared() will always return an int
*/
$num = Squared(Squared(Squared(999)));

Here $num will end up being a float. There’s just no way to prevent this unless you make modification on an engine level that will end up breaking a lot of preexisting assumptions and probably millions of lines of existing PHP code. So ensuring type safety is probably not the best pursuit in this matter. If we resolve to at least non-fatal casts where data loss is non-existent, we can get some form of type safety check that is at least passable in PHP.

10 Responses to“Test Drive PHP 5.5: A Sneak Peek”

  1. October 22, 2012 at 10:53 pm #

    Please please please please bring us property accessors. It’s something I miss greatly after using C#.

    • Michael Davidson
      December 5, 2012 at 4:06 pm #

      I second this motion. I would love to see properties added to PHP.

  2. October 27, 2012 at 4:44 pm #

    Very nice blog post! A lot of good information in there.

  3. Asif Saifuddin
    November 13, 2012 at 1:32 pm #

    Let them bring more good features from ruby python asp.net C# and Scala.
    and for templete engine something like twig…….

  4. November 15, 2012 at 7:20 pm #

    Great article, thanks. I really like how PHP is getting more serious about OO and syntax candy. It gets a bit more difficult, but together with traits makes app design far more interesting :)

  5. yuri
    November 25, 2012 at 2:56 pm #

    Finally there will be “finally” :)

  6. Coby
    November 29, 2012 at 4:23 pm #

    I agree w/ Micha: what keeps PHP exciting for me is the commitment to improving support for OO. Property Accessors look like a great addition, and a more meaningful way to solve certain OO problems in general.

  7. Villa bali
    December 2, 2012 at 1:19 pm #

    Hey There. I discovered your weblog using msn. That is a very neatly written article.
    I’ll make sure to bookmark it and come back to read more of your useful info. Thank you for the post. I’ll certainly return.

  8. Duty free Perfume Review
    December 20, 2012 at 7:51 pm #

    Wonderful blog! Do you have any hints for aspiring writers?
    I’m planning to start my own blog soon but I’m a little lost on everything.
    Would you advise starting with a free platform like WordPress or go for a paid option?
    There are so many options out there that I’m totally confused .. Any recommendations? Kudos!

    • GoogleGuy
      December 21, 2012 at 9:19 am #

      Personally, I use WordPress for my own blog. One of the benefits to that, for me, is that it’s very easy to manage from the front end. It’s also got a lot of interesting plugins and some great support from the community. So I know that if I have a problem I can look through the documentation and I can usually fix the problem myself if there hasn’t been a fix from the community already. It’s open source and free so of course that means I can change it to suit me if need be and I can even push those changes back out to the upstream.

      I honestly don’t have a lot of time to develop my own content management system specifically for my blog. I do this as a hobby in my spare time and time I don’t have to spend writing code for my own CMS is time I can spend writing these articles for others to read. So to me that’s a win-win situation. I also don’t care to pay for a content management system since you won’t find anything out there worth paying for if all you want is a personal blog. Most CMS’ software these days is open source with an optional corporate licenses. I don’t think you need a corporate license with support options, do you?

      I really try not to recommend any specific product or service, but honestly if you want peace of mind you can go with WordPress. Of all the other competing frameworks out there this is the Model T Ford in the market right now.

Leave a Reply

Your email address will not be published. Required fields are marked *

(Required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>