Contents


PHP renewed

The new face of PHP

Discover the major new language features in PHP

Comments

Content series:

This content is part # of # in the series: PHP renewed

Stay tuned for additional content in this series.

This content is part of the series:PHP renewed

Stay tuned for additional content in this series.

PHP is maintained and developed as an open source project, with hundreds — possibly thousands — of contributors actively working to evolve the language to meet the needs of modern web development. PHP continues to incorporate new programming ideas, and it borrows ideas from other programming languages, yet it maintains a high level of backward compatibility. These qualities have led PHP to its current prominence: The language helps to run 82 percent of the web and powers some of the biggest websites (such as Facebook). And PHP is the core technology behind content-management system (CMS) frameworks such as WordPress, Drupal, Magento, and Joomla! (which together power around 30 percent of the web).

If you haven't looked at PHP in a long time (or even in the last couple of years), you might not recognize the language that it has become. This article, the first in a four-part series, introduces you to the latest features added in recent releases such as PHP 5.3, 5.4, and 5.5.

Of course, PHP isn't changing in a vacuum, and new language features are only part of PHP's overall evolution. Ways in which PHP programmers are assembling their development servers, managing their third-party libraries, and addressing web security are also changing. Subsequent installments in this series will look into those aspects of the evolving PHP ecosystem.

I don't think anybody steals anything; all of us borrow.

B.B. King

Namespaces

Namespaces are a programming feature designed to allow classes (and functions) within different libraries to have the exact same names. Name conflicts started to become a major problem as PHP grew as a language and the reuse of code libraries became more prevalent. By segmenting each library into its own namespace, you can — with no bad consequences — install and use a third-party library that includes any classes whose names happen to match your own.

Before support for namespaces was built in, libraries solved this issue by prefacing all of their classes with a consistent phrase, such as Zend_ in the case of the Zend Framework. You could end up with esoteric class names such as Zend_Db_Table and need to type such prefixes repeatedly while coding. The problem came to a head when the (much needed) DateTime classes were added into the core of PHP at version 5.2. Suddenly, many open source libraries began breaking because they had created their own classes called DateTime to fill the gap.

Namespaces are created via the namespace keyword and separated by a backslash (\). Listing 1 shows a simple example.

Listing 1. Simple namespace usage
<?php
namespace zebra;

class DateTime
{
   public function __construct() {
      echo "Today!";
   }
}

function stripes() {
   echo "-=-=-=-=-=-=-=-";
}

In Listing 1, I define my own namespace, called zebra, and then define both a class and a function within it. Redefining the DateTime class in this case doesn't cause any issues or errors, because I make my own version of DateTime inside the namespace. Now I can use the namespace by referencing the full name with \ as a separator, as shown in Listing 2.

Listing 2. Using a custom namespace
<?php
include 'listing1.php';

// Use the stripes function I declared in my namespace:
zebra\stripes();

// Use my own DateTime class:
$dt = new zebra\DateTime();

// Now use the 'root' level Datetime class:
$real = new \DateTime('tomorrow noon');
echo $real->format(\DateTime::ATOM);

On line 2 of Listing 2, I include the file (listing1.php) that starts with the namespace directive. Then I can reference my classes and functions by prefacing them with the zebra\ namespace. I can also still use the global-level classes, such as the original DateTime, by prepending the backslash to denote the global namespace.

The technique in Listing 2 is handy, but there's a way to make the code simpler-looking: the new use keyword. This keyword states that you want to have direct access to a specific class from within that namespace, as shown in Listing 3.

Listing 3. Including the namespace with use
<?php
include 'listing1.php';
use zebra\DateTime;

// Use our own DateTime class:
$dt = new DateTime();

You can also have the use keyword create aliases, so that you can rename any class to something else for the scope you are in. Listing 4 shows how to create an alias.

Listing 4. Creating an alias
<?php
include 'listing1.php';
use zebra\DateTime as ZDT;

// Use our own DateTime class:
$dt = new ZDT();

You can do much more with namespaces than I've touched on here, including creating subnamespaces. Dig deeper in the official documentation.

Traits

Object-oriented programming is traditionally based deeply on the concept of classes and objects that inherit from one another. You begin with an abstract concept and continually subclass with children as you get more specific about the details. If you need a consistent API between your objects, the concept of interfaces comes into play; there, you can define the methods that the object needs to implement. But what if you don't merely want to declare which methods must exist, but you also want to provide their implementations at the same time? Enter traits.

Traits, added in PHP 5.4, are a facility for horizontal code reuse (whereas inheritance is vertical code reuse). In other languages this feature is sometimes called a mixin. The concept is straightforward in either case. A trait or mixin is a way to develop any number of methods once. Maybe you have some common methods for filtering and manipulating data or business logic that some objects should share. You can save them in a trait and then reuse them in any class that you might want.

Listing 5 shows a simplified example of providing a logging method that any class can use as a consistent way to log events.

Listing 5. Declaring and using a trait
<?php
trait logging {
   private static $LOG_ERROR = 100;
   private static $LOG_WARNING = 50;
   private static $LOG_NOTICE = 10;

   protected $log_location = 'output.log';

   protected function log($level, $msg) {

      $output = [];
      $output[] = "Class: ".__CLASS__.' | ';
      $output[] = "Level: {$level} | ";
      $output = array_merge($output, (array)$msg, ["\n"]);
      file_put_contents($this->log_location, $output, FILE_APPEND);
   }
}

class User {
   use logging;

   public function __construct() {
      $this->log(self::$LOG_NOTICE, 'New User Created');
   }
}

class DB {
   use logging;

   private $db = 'localhost:8080';

   public function connect() {
      // ... attempt to connect and fail:
      $this->log(self::$LOG_ERROR, ['Connection Failed-', $this->db]);
   }
}

In Listing 5, the declaration of trait logging begins on line 2. Note that this trait contains a method as well as a number of properties (including static ones). On the surface, the declaration looks similar to that of a class, but it uses the trait keyword instead.

Further down in Listing 5, to bring the trait into the User and DB classes, I use the use keyword again. The use logging; directive at the top of their class definitions essentially pulls all of the properties and methods from the logging trait into those classes natively. Now each class has access to all of the logging tools directly, without needing to implement them separately. The magic __CLASS__ variable used inside of the trait becomes the name of the class using the trait at that time, thereby enabling the log messages to be instantly customized to the class.

Closures (a.k.a. anonymous functions)

With older versions of PHP, you could create functions programmatically via create_function, and they allowed a workaround for passing functions: sending a function's name as a string and then calling the function via call_user_func and call_user_func_array. This option lacked the elegance of genuine anonymous functions that can be passed between methods and classes or saved in variables with appropriate scope.

Anonymous functions reign supreme in JavaScript, and PHP programmers who don't also know JavaScript are rare. So it was natural for PHP to evolve to include anonymous functions. As of PHP 5.3, you can use normal function-declaration syntax at any point where a variable could be used (for storage or passing).

As an example, Listing 6 shows the old way of using the built-in sorting functions to specify your own custom sorting function.

Listing 6. The old way of passing functions
<?php
$insurees = [
   'u4937' => ['name' => 'Thomas Smythe', 'age' => 33],
   'u1282' => ['name' => 'Gayle Runecor', 'age' => 25],
   'u9275' => ['name' => 'Sara Pinnicle', 'age' => 57],
   'u2078' => ['name' => 'Delilah Shock', 'age' => 41],
];

function insuree_age_sort($a, $b) {
   if ($a['age'] == $b['age']) { return 0; }
   return ($a['age'] > $b['age']) ? -1 : 1;
}

uasort($insurees, 'insuree_age_sort');

Listing 6 is somewhat clunky because of the need to define a function in the same scope and then use it — even if you'll never use it again. With closures, you can now directly create and use the function in one step. Listing 7 shows an example of this much more elegant solution.

Listing 7. Using an anonymous function for sorting
<?php
uasort($insurees, function ($a, $b) {
   if ($a['age'] == $b['age']) { return 0; }
   return ($a['age'] > $b['age']) ? -1 : 1;
});

Still, anyone would be hard-pressed to claim that this minor use case is the sole justification for this feature. But realize what is happening here. This function I create on the fly to pass into uasort() is a first-class variable citizen. You can store functions in variables and pass them around to different functions and classes. The real power of closures is evident when you look at the scoping feature that was added to PHP along with closures.

With the overloaded use keyword, you can specify certain variables in the current scope that the function should have access to. In this way, you can handle fairly complicated details without needing to constantly pass them into the function each time while accessing the function from its variable form. The (somewhat contrived) examples in Listing 8 and Listing 9 demonstrate this power.

Listing 8 uses inherited variable scope in a callback.

Listing 8. Using inherited variable scope in callback
<?php
// Find only people over a certain age
$minage = 40;

$over = array_filter($insurees, function($a) use ($minage) {
   return ($a['age'] >= $minage);
});

Listing 9 uses closures with multiple variable and direct calls.

Listing 9. Closures with multiple variables and direct calls
<?php
$urls = [
   'training' => '/training',
   'magazine' => '/magazine',
   't-shirt' => '/swag/tshirts',
];

$current = $_SERVER['REQUEST_URI']; // May come from somewhere else

// Helper for links, ignoring links if we are on that page:
$link = function($name) use ($urls, $current) {
   if ($current == $urls[$name]) {
      return $name;
   } else {
      return "<a href=\"{$urls[$name]}\">{$name}</a>";
   }
};
?>
<p>Welcome to our website!  Make sure to check out
   our <?= $link('training') ?> offerings, see the
   latest issue of our <?= $link('magazine'); ?>,
   and don't forget to check out our latest
   <?= $link('t-shirt') ?> designs as well.</p>

If you're used to working with closures in JavaScript, then you're already familiar with their power, flexibility, and sometimes dangerous nature.

Generators

When PHP 5.0 was released, it came with the beginnings of the Standard PHP Library (SPL). The SPL was meant to be a collection of standardized ways to solve certain computer-science problems, such as creating queues and linked lists (and to provide extensible features such as class-file autoloaders).

One feature included in the SPL is called an iterator. Iterator is an interface (with a collection of prebuilt classes) that you can use to make any class capable of being looped over as if it were an array, through the foreach keyword. This amazing invention makes it possible for all "lists of things" be to walked over in a uniform fashion. But Iterator is a fairly complicated system that requires you to create a class and define four methods. Sometimes you want the capability of a standard foreach loop but don't need the overhead of a class structure to achieve it.

With the newer generator feature, you can — via the yield keyword — make a function that generates a list of values and offers them back one at a time. Essentially, instead of returning one value, you yield as many values as you want. Then you can use a foreach loop on your function to retrieve all the values that the function wants to yield back.

Listing 10 shows a simple example of a function to divide a range of values into equal parts and return them.

Listing 10. A generator to divide into parts
<?php
function parts($start, $end, $parts) {
   // Find what our actual length is:
   $length = $end - $start;
   do {
      $start += $length / $parts;
      yield $start;
   } while ($start < $end);
}

// Break 5 feet into 3 parts:
foreach (parts(0, 5, 3) as $l) {
   echo $l, " ";
}
echo "\n";

// Break the range 10-90 into 2 parts:

foreach (parts(10, 90, 12) as $l) {
   echo $l, " ";
}
echo "\n";

The magic happens on line 7, where the yield keyword is used. At this point, essentially, the function stops executing, and the value that was yielded is returned. On each subsequent call to the function, execution begins where it left off, until the next yield happens or the function ends.

This example was obviously rather contrived, but you could imagine using this technique over the results of a database query, or on the results returned from parsing an XML file. You can even yield keys as well as values, to directly mimic an array by using the syntax yield $key => $value, as shown in the XML-based example in Listing 11.

Listing 11. Using a generator to process XML
<?php
$xml = <<<EOXML
<?xml version="1.0" encoding="UTF-8" ?>
<products>
  <books>
    <book isbn="978-1940111001">Mastering the SPL Library</book>
    <book isbn="978-1940111056">Functional Programming in PHP</book>
    <book isbn="978-0981034508">Guide to Date and Time Programming</book>
    <book isbn="0973589825">Guide to PHP Design Patterns</book>
  </books>
</products>
EOXML;

$books = function () use ($xml) {
   $products = simplexml_load_string($xml);
   foreach ($products->books->book as $book) {
      yield $book['isbn'] => (string)$book;
   }
};

foreach ($books() as $isbn => $title) {
   echo "{$isbn}: {$title}\n";
}

And much, much more ...

All of the new features in PHP are too numerous to cover here in detail. Table 1 is a quick list of some other notable additions from the last few years.

Table 1. Other new PHP language features
FeatureVersionDescription
Late static binding 5.3The ability for a parent class to call a static method or property that is defined by one of its children/inheritors (the opposite of how this is usually done). For example, allows for generic functionality to exist in a parent class that takes in configuration from its extended children.
Nowdoc syntax 5.3The ability to specify a string as a block of text without variables within it being interpreted.
Shortcut ternary (?:) 5.3The ability to omit the middle of a standard ternary operator, such that the true condition defaults back to the original comparison value. Example: $result = $value ?: 0;
Jump labels (goto) 5.3While not considered by some to be 'moving forward' with the language, the goto operator was added so that certain coding exercises, such as the creation of state machines, could more easily be done inside of PHP.
Magic methods
__callStatic
__invoke
__debugInfo

5.3
5.3
5.6
These three new magic methods were added to the others available since PHP 5.0 to complete the powerful slate of options you can use when designing your classes. Now you can have overloaded and undefined static methods, call your object as if it were a function, and control what's output when you debug your object.
Always-on shortcode echo (<?=) 5.4Previously if you had disabled shortcodes in PHP, all variations were turned off. As of PHP 5.4, the <?= shortcode, which is commonly used in templating, is always available to you.
Short array syntax 5.4Instead of declaring your arrays as array(1,2,3), you can now use brackets, as in: [1,2,3]
Built-in web server 5.4The PHP runtime now comes with a built-in web server, making it much easier to do simple code testing and development without the need for configuring Apache or IIS.

Conclusion

Modern PHP development doesn't look anything like the old procedural code of days past. And PHP continues to sustain a high rate of development. PHP 7 is already on the horizon, with a late 2015 release date planned.

The next installment of this series will look at the realm of ever-changing needs for password protection and what PHP has been doing to help web developers handle this complex requirement.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Open source
ArticleID=1001315
ArticleTitle=PHP renewed: The new face of PHP
publish-date=03252015