Reactie toevoegen

A Look at PHP's Continuing Evolution

Guest post by Larry GarfieldLarry Garfield is a Senior Architect at Palantir.net, a web consultancy based in Chicago. When not developing sites for clients, he can also be found leading the Drupal 8 Web Services Initiative, evangelizing good coding practices, working to bring the PHP world closer together through the PHP Framework Interoperability Group, or providing training either for clients or the Drupal community. Occasionally he remembers to sleep.

PHP is not a young language. As of 2013, it's 18 years old; that's old enough to vote. Many upstart languages have appeared over the years to try and unseat PHP as the "lingua franca" of web applications but it still commands over 80% of the web market. One reason for PHP's popularity is no doubt the ease with which new developers can get started with it, but just as important is the fact that PHP has been evolving for all those 18 years.

Many PHP detractors had cited the language's sometimes inconsistent APIs or its procedural nature as a reason that PHP was just a "toy language." That charge is true... or rather, it was during the 1990s. What is true now is that PHP is an eclectic language that isn't bound to a single world-view or architecture – and this is one of its strengths. Procedural, Object-oriented, and Functional programming styles all have their pros and cons. PHP lets you pick and choose what to use rather than forcing everything and everyone into a single mindset.

Recent versions of PHP have expanded its capabilities, too, to keep up with evolving markets and technical requirements. Let's have a look at three of the more recent additions to PHP's arsenal that help it remain the world's leading server-side language.

Anonymous functions and closures

PHP 5.3 introduced anonymous functions to PHP for the first time. The syntax is quite simple, too:

<?php
$c
= 5;
$max_cap = function ($a, $b) use ($c) {
 
$max = max($a, $b);
  return
min($max, $c);
};
$max_cap(3, 6);
?>

This trivial function lets us create a routine that returns the maximum of 2 values, but with an overall limit. We can now call it from anywhere we pass $max_cap to. While this example may not be very useful per se, specifying one-off logic routines without a dedicated function can be extremely useful. Consider array_map(), which applies a function to every element of an array:

<?php
$factor
= 3
$triple
= array_map(function($elm) use ($factor) {
  return
$elm * $factor;
},
$array);
?>

$triple now contains all the elements of $array, multiplied by 3. There are far far more powerful opportunities with anonymous functions that can and have justified their own articles, so we'll leave that for now and just mention object binding.

As of PHP 5.4, anonymous functions can also be "bound" to an object. That is, $this within a closure can refer to an object we specify, like so:

<?php
class  Foo {
  private
$count = 0;
}
$func = function() {
  return ++
$this->count;
};
$foo = new Foo();
// second param specifies scope so it can access private vars.
$bound = $func->bindTo($foo, $foo);
print
$bound(); // prints 1
print $bound(); // prints 2
?>

For more on anonymous functions, see the PHP manual entries on anonymous functions and class closure.

Traits

PHP 5.4 also added a new feature for the OO crowd: Traits. Traits are, essentially, "compiler-assisted copy and paste" – or, sane multiple inheritance. They let you define methods that can be added to a class at code time without inheritance.

<?php
trait World {
  protected function
scope() {
    return
'World';
  }
}

class
Hello {
  use
World;
  public function
hello() {
    return
"Hello " . $this->scope();
  }
}
?>

To be sure, traits are not and should not be used as an alternative for object composition. Their main use is to minimize boilerplate code needed to fulfill an interface. Proper use of traits can greatly reduce boilerplate code while still allowing for clean separation and interface-centric development.

For more on traits, see the PHP manual entry on traits.

Generators

PHP 5.5 added a feature called generators. Generators are in some sense a greatly abbreviated syntax for iterators, but being so simple makes them considerably more powerful. Essentially, a generator is just a function that returns-and-pauses rather than returns-and-ends, and what is returned is not a value but an iterator. The canonical (if trivial) example is iterating an "array" with 10 million items, which normally would cause memory issues:

<?php
function xrange($start, $limit, $step = 1) {
  for (
$i = $start; $i <= $limit; $i += $step) {
    yield
$i;
  }
}
foreach (
xrange(1, 10000000, 5) as $i) {
  print
$i . PHP_EOL;
}
?>

PHP notices the yield keyword, so when xrange() is called, an iterator object is returned. Every time foreach() asks that object for the next value, xrange() runs until it hits a yield and returns that value; the next time it's called, it continues from right after that yield statement until it hits another yield or exits. The above code will print every 5th integer from 1 to 10 million, and use no more than a kilobyte of memory in the process.

You can also pass data into a generator via yield. For a less trivial example, let's copy data from one file to another, stripping out all comment lines along the way.

<?php
function no_comments($filename) {
 
$handle = fopen($filename, 'r');
  while ((
$buffer = fgets($handle, 4096)) !== false) {
    if (
strpos($buffer, '//') !== 0) {
      yield
$buffer;
    }
  }
 
fclose($handle);
}

function
stripped_file($file) {
 
$f = fopen($file, 'a');
  while (
true) {
   
$line = yield;
    if (
is_null($line)) {
      break;
    }
   
fwrite($f, $line);
  }
 
fclose($f);
}
$out = stripped_file('output.php');

foreach (
no_comments('input.php') as $line) {
 
$out->send($line);
}
$out->send(null);
?>

A tiny bit of setup and the resulting code at the end couldn't possibly be easier! And the memory usage is trivial.

You can read all about this, too, in the PHP manual entry on generators!

Conclusion

PHP has lasted as long as it has, and gained the marketshare it has because it is flexible. That flexibility is increasing with every version. We've only barely scratched the surface of modern PHP here. Since PHP 5.2, every release of the language has offered new features and functionality to give developers more power and more options than ever before.

That 80% marketshare is not going anywhere anytime soon.

Plain text

  • Geen HTML toegestaan.
  • Adressen van webpagina's en e-mailadressen worden automatisch naar links omgezet.
  • Regels en alinea's worden automatisch gesplitst.

Filtered HTML

  • Use [acphone_sales], [acphone_sales_text], [acphone_support], [acphone_international], [acphone_devcloud], [acphone_extra1] and [acphone_extra2] as placeholders for Acquia phone numbers. Add class "acquia-phones-link" to wrapper element to make number a link.
  • To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.
  • Adressen van webpagina's en e-mailadressen worden automatisch naar links omgezet.
  • Toegelaten HTML-tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <h4> <h5> <h2> <img>
  • Regels en alinea's worden automatisch gesplitst.
Bij het indienen van dit fomulier gaat u akkoord met het privacybeleid van Mollom.